springboot升级到版本2.7.9
springboot启动
正常启动
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
启动时输出pid文件
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.addListeners(new ApplicationPidFileWriter());
ConfigurableApplicationContext applicationContext = application.run(args);
applicationContext.registerShutdownHook();
}
}
指定项目访问名称
项目访问路径
server.servlet.context-path = itemAccessName
springboot启动指定参数
--server.port=8081 启动指定端口号
--spring.config.location=/opt/application.properties 启动指定配置文件
启动时指定日志路径:
-Domp.logging.path=logs
${sys:omp.logging.path:-./log/}
添加指定系统参数
System.setProperty("", "");
springboot配置文件
spring.pid.file=application.pid 默认pid文件名称
spring.application.name=itemName 启动项目名称
#eureka上显示IP地址配置下面两项
eureka.instance.prefer-ip-address = true
eureka.instance.preferIpAddress = true
#eureka注册增加实例名称
eureka.instance.instance-id = ${spring.cloud.client.ip-address}:${server.port}
#springboot配置日志文件位置
logging.config = config/logback-spring.xml
springboot加载资源文件
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("a.txt");
IOUtils.toString(inputStream);
springboot配置文件加载顺序
application.properties 配置文件加载顺序
file:./config/
file:./
classpath:/config/
classpath:/
加载优先级由高到低,高优先级的配置会覆盖低优先级的配置
sprinboot测试用例
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@Transactional
@AutoConfigureMockMvc
出现下面错误时查询是否是导入的org.junit.Test
org.junit.runners.model.InvalidTestClassError: Invalid test class
AOP
@EnableAspectJAutoProxy
@Aspect @Pointcut @Before @After @Around @AfterThrowing @AfterReturning
@EnableTransactionManagement
InfrastructureAdvisorAutoProxyCreator
@EnableAspectJAutoProxy
AnnotationAwareAspectJAutoProxyCreator
CglibAopProxy DynamicAdvisedInterceptor intercept
ReflectiveMethodInvocation.proceed()
ExposeInvocationInterceptor.invoke()
异常返回通知
AspectJAfterThrowingAdvice.invoke()
正常返回通知
AfterReturningAdviceInterceptor.invoke()
后置通知
AspectJAfterAdvice.invoke()
环绕通知
AspectJAroundAdvice.invoke()
前置通知
MethodBeforeAdviceInterceptor.invoke()
正常过程
@Arount:执行目标方法之前
@Before-----除法运行之前
----div----
@Arount:执行目标方法之后
@After-----除法结束
@AfterReturning-----除法正常返回
异常过程
@Arount:执行目标方法之前
@Before-----除法运行之前
----div----
@After-----除法结束
@AfterThrowing-----运行异常
// 切入点
execution(* * cn.com.spring.service.impl..*.*(..))
1)* 所有的修饰符(如public)
2)* 所有的返回类型(如void)
3).. 所有的包及其子包下的文件
4)* 所有的类名
5)* 所有的方法名
6)* ..所有的参数名
配置文件参数自动转List类型
参数自动转为List
@Value("#{'${csp.security:menuList,portalList}'.split(',')}")
private List<String> verifyTokenUrlList;
maven jar包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.13</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
打包插件
org.springframework.boot mvn打包springboot项目jar或war
spring-boot-maven-plugin
org.apache.maven.plugins 测试用例插件(默认已有)
maven-surefire-plugin
org.apache.maven.plugins 资源插件(处理资源文件)
maven-resources-plugin
org.apache.maven.plugins 部署插件(发布远程仓库)
maven-deploy-plugin
org.apache.maven.plugins jar包插件(打成可运行jar包)
maven-jar-plugin
org.apache.maven.plugins 依赖插件(添加额外jar包)
maven-dependency-plugin
pl.project13.maven git插件(获取git版本信息)
git-commit-id-plugin
maven-assembly-plugin 装配插件(支持定制化打包)
@InitBinder日期格式化
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) throws IllegalArgumentException {
Date date = null;
try {
date = new SimpleDateFormat("yyyy-MM-ddHH:mm:ss").parse(text);
} catch (ParseException e) {
}
if (date == null) {
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(text);
} catch (ParseException e1) {
}
}
setValue(date);
}
});
}
前后端交互日期格式化
前台传后台时间格式化(form表单形式)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date date;
前台传后台时间格式化(json形式)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
后台传前台时间格式化
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
手动控制事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(def);
try {
// TODO 保存数据
dataSourceTransactionManager.commit(transactionStatus);
} catch (Exception e) {
log.error("", e);
dataSourceTransactionManager.rollback(transactionStatus);
throw new RuntimeException(e);
}
Validation参数验证使用时调用
Validation.buildDefaultValidatorFactory().getValidator().validate(obj).forEach((s)->{
throw new RuntimeException("["+s.getPropertyPath()+s.getMessage()+"]");
});
newDecimalFormat("#,###").format(123456789)) -> 123,456,789
Springboot项目无法加载配置文件时添加插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>logback-spring.xml</exclude>
<exclude>application.properties</exclude>
</excludes>
</configuration>
</plugin>
修复跨站脚本漏洞
org.springframework.web.util.HtmlUtils.htmlEscape(str);
spring boot关闭actuator路径
关闭actuator所有端点
management.endpoints.enabled-by-default=false
禁用监控HTTP端点,因为http端口的范围是:1~65535,因此-1是访问不了的,此时访问/actuator路径也是404了
management.server.port = -1
actuator默认开启了health、info端点,可以单独关闭
management.endpoint.info.enabled=false
management.endpoint.health.enabled=false
单独开启服务端点,如开启info、health
management.endpoint.info.enabled=true
management.endpoint.health.enabled=true
批量暴露端点,例如暴露mapping、metrics端点
management.endpoints.web.exposure.include=mapping,metric
暴露所有端点
management.endpoints.web.exposure.include=*
日志
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
@Slf4j
或者Logger log = LoggerFactory.getLogger(A.class);
异常统一处理
@ControllerAdvice
@ExceptionHandler({Exception.class})
@ResponseBody
public void methodException(HttpServletRequest request, Exception ex, HttpServletResponse response) throws IOException {
response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
response.setContentType("application/json;charset=UTF-8");
//response.setContentType("text/plain;charset=UTF-8");
response.getWriter().write(JSON.toJSONString(new JSONObject().fluentPut("code", "111").fluentPut("msg", ex.getMessage())));
}
url匹配判断
PathMatcher antPathMatcher = new AntPathMatcher();
antPathMatcher.match("/url/**", req.getServletPath());
url请求强匹配
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false).setUseTrailingSlashMatch(true);
}
}
post请求时,验证传递的参数名是否必须在实体类中存在
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
// 设置false时忽略不存在的属性,设置true时验证属性必须存在
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
}
}
自动时间转换
在实体类的Date类型字段上添加此注解,在入参、及转成json格式时会转成字符串
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
Valid参数验证实例
@Valid 支持嵌套,可以验证类中类属性
@Validated 不支持嵌套,仅可以验证本类属性
常用的用法
@NotNull
@NotEmpty
@Pattern(regexp = "^[0-9]?$")
嵌套实例
@Data
public class A{
@Valid
@NotEmpty
@NotNull
private List<B> list;
@Data
public static class B{
@NotNull
private Long objectId;
}
}
获取request、respone
//获取请求体 request
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
//获取响应体 response
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
http响应返回状态码
响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599):
日志可以使用这种方式替换变量
log.info("消息内容替换[{}]", "message");
输出为:消息内容替换[message]
过滤器、拦截器
// 过滤器优于拦截器先执行
// 拦截器示例
@Component
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
}
@Configuration
public class MyConfig extends WebMvcConfigurationSupport {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns 添加拦截规则
// excludePathPatterns 排除拦截
registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/error/**");
}
}
// 过滤器示例
@WebFilter(filterName = "MyFilter", urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
chain.doFilter(req, resp);
}
}
// 过滤器生效需要在启动类上添加注解:@ServletComponentScan(basePackages = { "扫描filter的包" })
添加过滤器判断系统仅支持post请求
@WebFilter(filterName = "MyFilter", urlPatterns = "/*")
public class MyFilter implements Filter {
private final static PathMatcher antPathMatcher = new AntPathMatcher();
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
if (!antPathMatcher.match("/info/**", request.getServletPath())) {
if ("GET".equals(request.getMethod())) {
req.getRequestDispatcher("/error/handleError").forward(req, resp);
return;
}
}
chain.doFilter(req, resp);
}
}
// 添加错误访问方法,为了跳转到全局异常过滤器
@RestController
@RequestMapping(value = "/api/error")
public class ErrorController {
@GetMapping("handleError")
public void handleError() {
throw new ServiceException("Request method 'GET' not supported");
}
}
获取处理项目的URL
// spring获取请求url地址
UrlPathHelper helper = new UrlPathHelper();
String uri = helper.getOriginatingServletPath(request);
// 获取系统所有的url
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : requestMappingHandlerMapping.getHandlerMethods().entrySet()) {
for (String url : entry.getKey().getPatternsCondition().getPatterns()) {
System.out.println(url);
}
}
// 获取url的请求匹配类方法
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : RequestMappingHandlerMapping.getHandlerMethods().entrySet()) {
RequestMappingInfo m = entry.getKey().getMatchingCondition(request);
Set<String> urlPatterns = m.getPatternsCondition().getPatterns();
HandlerMethod value = entry.getValue();
}
spring自带缓存功能
@CacheEvict(allEntries=true)
@Cacheable(value="a", key="#id")
https://www.cnblogs.com/goloving/p/16040705.html
feign的调用
Object obj = Feign.builder().client(applicatonContext.gerBean(Client.class))
.encoder(applicatonContext.gerBean(Encoder.class))
.decoder(applicatonContext.gerBean(Decoder.class))
.contract(new SpringMvcContract())
.target(Object.class, "http://microServiceName/path");
springcloud高版本ribbon问题
springcloud高版本不能使用ribbon,可以直接删除ribbon,直接使用loadbalancer
https://blog.csdn.net/SirLZF/article/details/117127361
解决类上@FeignClient、@RequestMapping同时存在时的报错问题
@Bean
@Primary
public SpringMvcContract feignContract(List<AnnotatedParameterProcessor> parameterProcessors,
ConversionService feignConversionService,
FeignClientProperties feignClientProperties) {
boolean decodeSlash = feignClientProperties == null || feignClientProperties.isDecodeSlash();
return new SpringMvcContract(parameterProcessors, feignConversionService, decodeSlash) {
@Override
protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
CollectionFormat collectionFormat = findMergedAnnotation(clz, CollectionFormat.class);
if (collectionFormat != null) {
data.template().collectionFormat(collectionFormat.value());
}
}
};
}
测试用例注解
@Transactional
@Rollback(true)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
配置druid的sql监控生效的配置
spring.datasource.druid.web-stat-filter.enabled = true
spring.datasource.druid.stat-view-servlet.enabled = true
spring.datasource.druid.stat-view-servlet.allow = 127.0.0.1/0
spring.datasource.druid.filter.stat.enabled = true
spring.datasource.druid.filter.stat.log-slow-sql = true
spring.datasource.druid.filter.stat.merge-sql = true
spring.datasource.druid.filter.stat.slow-sql-millis = 3000
spring.datasource.druid.stat-view-servlet.reset-enable = false
spring.datasource.druid.stat-view-servlet.login-username = admin
spring.datasource.druid.stat-view-servlet.login-password = admin@123
定时任务设置
@Scheduled(cron = "${refresh.space:0 0 3 * * ?}")
初始化后执行方法
@PostConstruct
日期自动转换器
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class DateConverter implements Converter<String, Date> {
private static final List<String> FORMAT_LIST = new ArrayList<>();
static {
FORMAT_LIST.add("yyyy-MM");
FORMAT_LIST.add("yyyy-MM-dd");
FORMAT_LIST.add("yyyy-MM-dd HH:mm");
FORMAT_LIST.add("yyyy-MM-dd HH:mm:ss");
}
@Override
public Date convert(String source) {
String value = source.trim();
if ("".equals(value)) {
return null;
}
if (value.matches("^\\d{4}-\\d{1,2}$")) {
return parseDate(value, FORMAT_LIST.get(0));
} else if (value.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
return parseDate(source, FORMAT_LIST.get(1));
} else if (value.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) {
return parseDate(source, FORMAT_LIST.get(2));
} else if (value.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {
return parseDate(value, FORMAT_LIST.get(3));
} else {
throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
}
}
private Date parseDate(String dateStr, String format) {
Date date = null;
try {
DateFormat dateFormat = new SimpleDateFormat(format);
date = dateFormat.parse(dateStr);
} catch (Exception e) {
log.error("格式化日期异常", e);
}
return date;
}
}
SpringBoot如何解决跨域问题
跨域可以在前端通过 JSONP 来解决,但是 JSONP 只可以发送 GET 请求,
无法发送其他类型的请求,在 RESTful 风格的应用中,就显得非常鸡肋,
因此我们推荐在后端通过 (CORS,Cross-origin resource sharing)来解决跨域问题。
这种解决方案并非SpringBoot特有的,在传统的SSM框架中,就可以通过 CORS 来解决跨域问题,
只不过之前我们是在 XML 文件中配置 CORS ,
现在可以通过实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
请求参数加签名
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@WebFilter(filterName = "GetParamFilter", urlPatterns = "/*", dispatcherTypes = DispatcherType.REQUEST)
public class GetParamFilter implements Filter {
private static final String SIGN_NAME = "sign";
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
if ("GET".equalsIgnoreCase(request.getMethod())) {
if (!validSign(request)) {
responseJsonMessage(resp, "错误信息提示");
return;
}
}
chain.doFilter(req, resp);
}
public static boolean validSign(HttpServletRequest request) {
Map<String, String> paramMap = new HashMap<>();
Enumeration<String> enumeration = request.getParameterNames();
while (enumeration.hasMoreElements()) {
String paramName = enumeration.nextElement();
paramMap.put(paramName, request.getParameter(paramName));
}
paramMap.remove(SIGN_NAME);
if (MapUtils.isEmpty(paramMap) || StringUtils.isBlank(request.getParameter(SIGN_NAME))) {
return true;
}
return StringUtils.equals(request.getParameter(SIGN_NAME), cn.hutool.crypto.SecureUtil.md5("待加密的字符串"));
}
private void responseJsonMessage(ServletResponse resp, Object obj) throws IOException {
resp.setContentType("application/json; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print(JSONObject.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat));
writer.close();
resp.flushBuffer();
}
}
适配管理库时,需要添加下面数据库适配器
# 添加下面后,在xml中可以使用_databaseId来进行各个数据库的判断了
@Configuration
public class DatabaseAdapterConfig {
@Bean
public DatabaseIdProvider getDatabaseIdProvider() {
DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
Properties p = new Properties();
p.setProperty("PostgreSQL", "postgres");
p.setProperty("DM DBMS", "dm7");
p.setProperty("Oracle", "oracle");
p.setProperty("MySQL", "mysql");
databaseIdProvider.setProperties(p);
return databaseIdProvider;
}
}
jpa低版本适配达梦
#方案一 添加兼容包加配置参数:
1、添加兼容包:DmDialect-for-hibernate
2、添加参数参数(涉及类JpaProperties,):spring.jpa.database-platform = org.hibernate.dialect.DmDialect
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmDialect-for-hibernate5.6</artifactId>
<version>8.1.3.140</version>
</dependency>
#重写了类JpaBaseConfiguration的方法:jpaVendorAdapter(),并注册bean
@Configuration
public class JpaVendorAdapterConfig {
@Value("${spring.jpa.database-platform:org.hibernate.dialect.DmDialect}")
private String databasePlatform;
@Value("${dm.driver.class.name:dm.jdbc.driver.DmDriver}")
private String dmDriverClassName;
@Value("${spring.datasource.driver-class-name}")
private String springDatasourceDriverClassName;
@Bean
@Primary
public JpaVendorAdapter jpaVendorAdapter(JpaProperties properties) {
AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(properties.isShowSql());
if (properties.getDatabase() != null) {
adapter.setDatabase(properties.getDatabase());
}
if (StringUtils.isNotBlank(properties.getDatabasePlatform())) {
adapter.setDatabasePlatform(properties.getDatabasePlatform());
} else if (StringUtils.equalsIgnoreCase(springDatasourceDriverClassName, dmDriverClassName)) {
adapter.setDatabasePlatform(databasePlatform);
}
adapter.setGenerateDdl(properties.isGenerateDdl());
return adapter;
}
}
方案二 通过url添加参数让jpa使用oracle的类
url连接添加参数:?compatibleMode=oracle&comOra=true 添加1个参数即可(配置参数的作用位置DmdbDatabaseMetaData #getDatabaseProductName())
测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Transactional
//@AutoConfigureMockMvc
//@ContextConfiguration(locations = {"classpath:xmls/spring-context.xml"})
public abstract class BaseTest {
public void assertResultCodeEquals(Result expect, Result actual) {
Assert.assertEquals(expect.getCode(), actual.getCode());
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@AutoConfigureMockMvc
public abstract class BaseTestMockMvc {
@Autowired
protected MockMvc mockMvc;
protected void mockMvcRequestGetForm(String url, MultiValueMap<String, String> params) throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get(url)
.params(params)
.header("Authorization", authorization)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
io.jsonwebtoken.lang.Assert.isTrue(mvcResult.getResponse().getStatus() == 200);
printlnMvcResult(mvcResult);
}
protected void mockMvcRequestPostForm(String url, MultiValueMap<String, String> params) throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(url)
.params(params)
.header("Authorization", authorization)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
io.jsonwebtoken.lang.Assert.isTrue(mvcResult.getResponse().getStatus() == 200);
printlnMvcResult(mvcResult);
}
protected void mockMvcRequestPostBody(String url, Object obj) throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(url)
.content(JSON.toJSONString(obj))
.header("Authorization", authorization)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
printlnMvcResult(mvcResult);
}
private static void printlnMvcResult(MvcResult mvcResult) throws Exception {
io.jsonwebtoken.lang.Assert.isTrue(mvcResult.getResponse().getStatus() == 200);
String content = mvcResult.getResponse().getContentAsString();
System.out.println();
System.out.println(content);
Result result = JsonUtils.readValue(content, Result.class);
Assert.isTrue(MsgCode.SUCCESS.getCode().equals(result.getCode()), result.getMsg());
}
}
@Transactional
public class Test extends BaseTestMockMvc {
@Test
public void test() throws Exception {
Object reqVO = new Object();
Object.setUserId("npi");
Object.setUserName("npi");
mockMvcRequestPostBody("/oper/list", Object);
}
}
springboot3自动加载实例化读取的文件
#目录
src/main/resources/META-INF/spring
#文件
org.springframework.boot.autoconfigure.AutoConfiguration.imports