spring boot 使用注意事项

兼容问题

spring-boot-starter-parent切换回1.5.2.RELEASE版本

因为1.5.4.RELEASE、1.5.5.RELEASE、1.5.6.RELEASE、1.5.7.RELEASE、2.0.0.M1、2.0.0.M2、2.0.0.M3都存在使用spring-boot-starter-data-redis时,会出现异常

java.lang.NoSuchMethodError: org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource.<init>异常

请查看https://github.com/spring-projects/spring-boot/issues/9606

外部 Tomcat 容器部署

外部 Tomcat 等容器部署war,要继承 SpringBootServletInitializer 类

war部署要重写SpringBootServletInitializer的configure方法,可以不要main方法,main方法是jar部署时候会执行的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;

/**
* 启动器
*
* @author YL
*/
@SpringBootApplication(
excludeName = {
"org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration",
// 数据库相关
"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration",
"org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration",
"org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration",
"org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration",
// jmx 相关
"org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration",
// websocket 相关
"org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration",
"org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration",
"org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration",
// mail相关
"org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration",
"org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration",
// 模版引擎
"org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration",
"org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration",
// actuate trace:保存最近100次请求记录在内容,没什么卵用
"org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration",
"org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration",
"org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration",
// 其他
"org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration"
}
)
public class App extends SpringBootServletInitializer {

/**
* Common
*/
private static SpringApplicationBuilder configureSpringBuilder(SpringApplicationBuilder builder) {
// 自定义事件监听器,实现 ApplicationListener
-- builder.listeners(new EnvironmentPreparedEventListener());
return builder.sources(App.class);

}

/**
* for WAR deploy
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return configureSpringBuilder(builder);
}

/**
* for JAR deploy
*/
public static void main(String[] args) {
configureSpringBuilder(new SpringApplicationBuilder())
.run(args);
}
}

attach=false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
<includes>
<include>
<groupId>nothing</groupId>
<artifactId>nothing</artifactId>
</include>
</includes>
<!-- 将原始的包作为 install 和 deploy 的对象,而不是包含了依赖的包 -->
<attach>false</attach>
</configuration>
</plugin>

spring-boot升级到2.0

  1. 弃用WebMvcConfigurerAdapter,替换成WebMvcConfigurer
1
2
3
4
5
6
7
8
9
10
@Configuratiion
public class WebAdapter extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT");
}
}

在 spring-boot 2.0 中需要注意,因为使用的是 spring 5,原先的方法是继承WebMvcConfigurerAdapter抽象类,现在是直接扩展 WebMvcConfigurer 这个接口。原先的方式很能生效,不过已经被 spring 5弃用了(@Deprecated)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuratiion
public class MyConfiguration {
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
// 跨域配置
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
// 拦截器配置
@Override
public void addInterceptors(InterceptorRegistry registry) {

}
// ...
};
}
}
  1. 其他

@RequestBody

  1. 使用 @RequestBody 注解时,如果注解的参数没有传入,则会抛出org.springframework.http.converter.HttpMessageNotReadableException异常
  2. 配合hibernate-validator不起作用的问题

在参数前面使用org.springframework.validation.annotation.Validated注解,或者javax.validation.Valid注解均可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;

import java.io.Serializable;

/**
* @author Created by YL on 2017/10/19
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MarketRebateDTO implements Serializable {
@NotBlank(message = "营销活动 Id 不能为空")
@Length(min = 5, max = 8, message = "营销活动 Id[${validatedValue}] 长度必须在 {min} 和 {max} 之间")
private String marketCfgId;

private String productNo;

private String rebateAmt;

private String tradeType;
}

import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;

/**
* 广东省营销接口
*
* @author Created by YL on 2017/10/18
*/
@RestController
@RequestMapping("/api/market")
public class MarketController extends BaseRestController {
@Reference
private MarketService marketService;

@PostMapping("/rebate")
public BaseResponse rebate(@RequestBody @Valid MarketRebateDTO rebate) throws CoreException, OkHttpException {
return marketService.doRebate(rebate);
}
}

@RequestParam

  1. 使用 @RequestParam 注解时,如果注解的参数没有传入,则会抛出org.springframework.web.bind.MissingServletRequestParameterException异常
  2. 配合hibernate-validator不起作用的问题

要注册 MethodValidationPostProcessor Bean,并且在上面使用org.springframework.validation.annotation.Validated注解

注意:使用javax.validation.Valid注解对RequestParam对应的参数进行注解,是无效的,需要使用@Validated注解来使得验证生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Bean
public Validator validator() {
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class)
.configure()
// 1、普通模式(默认是这个模式)
// 普通模式(会校验完所有的属性,然后返回所有的验证失败信息)
// 2、快速失败返回模式
// 快速失败返回模式(只要有一个验证失败,则返回)
// .addProperty("hibernate.validator.fail_fast", "true")
.failFast(true)
.buildValidatorFactory();
return factory.getValidator();
}

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
// 设置validator模式为快速失败返回
postProcessor.setValidator(validator());
return postProcessor;
}

import com.alibaba.dubbo.config.annotation.Reference;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* csp 平台接口封装
*
* @author Created by YL on 2017/9/19
*/
@RestController
@RequestMapping("/api/csp")
@Validated
public class CspController extends BaseRestController {
@Reference
private CspService cspService;

@GetMapping
public BaseResponse get(@RequestParam
@NotBlank(message = "组件名不能为空")
String func,
@RequestParam
@NotBlank(message = "参数值不能为空")
String param) throws OkHttpException, OpenApiException {
return new BaseResponse(cspService.get(func, param));
}
}

至此,Bean Validator 和 hibernate-validator的@Size、@Min、@Max、@Length、@NotBlank等注解就生效了

  • 本文作者: forever杨
  • 本文链接: https://blog.yl-online.top/posts/47aa1712.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。如果文章内容对你有用,请记录到你的笔记中。本博客站点随时会停止服务,请不要收藏、转载!