Java相关技术选择
组件名称 | 版本 | 说明 |
---|---|---|
Java | 1.8.0_212 | elasticsearch依赖最低版本1.8.0_131springboot2至少依赖1.8 |
Spring Boot | 2.1.5.RELEASE | feign多文件需要简单配置 |
Servlet 容器 | tomcat | 忠宇反馈评审人员对于不熟悉的undertow持否定态度,采用springboot自带的tomcat |
Elasticsearch | 6.3.2 | 采用restclient代替transportclient,根据需要再开发2.4相关版本 |
数据库 | PostgreSQL(11.4) | |
持久层框架 | MyBatis(3.5.1) | mybatis-spring-boot-starter(2.0.1)内部mybatis就是3.5.1 |
swagger | 2.7.0 | 从2.8.0之后版本ui不好用 |
参数校验 | javax.validation | 统一异常处理 |
统一异常处理 | 分层处理 | 需要自己封装 |
统一返回数据对象 | 需要自己封装 | |
工具类 | commons-lang3 commons-collections4 commons-io http(okhttp)json(jackson)日期操作 |
需要自己封装 |
版本详情
Java
官方当前1.8最新稳定版 Java SE Development Kit 8u212
最低要求版本1.8.0_131(elasticsearch6.0官方要求的最低版本)
Spring Boot
最新稳定版 2.1.5.RELEASE
之前项目中使用springboot 如果需要使用feign的文件上传需要配置的地方比较多
2.0以后feign采用openfeign,不需要配置,只有在多文件上传时需要简单配置
class MultipartSupportConfig {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Encoder feignEncoder() {
return new SpringMultipartEncoder(new SpringEncoder(messageConverters));
}
}
class SpringMultipartEncoder extends SpringFormEncoder {
public SpringMultipartEncoder() {
this(new Default());
}
public SpringMultipartEncoder(Encoder delegate) {
super(delegate);
MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(ContentType.MULTIPART);
processor.addWriter(new SpringSingleMultipartFileWriter());
processor.addWriter(new SpringManyMultipartFilesWriter());
}
@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (bodyType.equals(MultipartFile.class)) {
// 单MultipartFile判断
MultipartFile file = (MultipartFile) object;
Map data = singletonMap(file.getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
} else if (bodyType.equals(MultipartFile[].class)) {
// MultipartFile数组处理
MultipartFile[] file = (MultipartFile[]) object;
if (file != null) {
Map data = singletonMap(file.length == 0 ? "" : file[0].getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
}
}
// 其他类型调用父类默认处理方法
super.encode(object, bodyType, template);
}
}
文件上传的feign配置
@FeignClient(name = "file", url = "http://127.0.0.1:8080", configuration = FileFeign.MultipartSupportConfig.class)
Servlet容器
使用springboot自带的tomcat
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
使用统一异常处理捕获文件大小异常
配置文件上传大小为10M示例
application.yml
server:
# 该配置项可以在统一异常处理中捕获上传文件大小异常
tomcat:
max-swallow-size: -1
spring:
servlet:
multipart:
max-file-size: 10MB
统一异常处理
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MaxUploadSizeExceededException.class)
@ResponseStatus(value = HttpStatus.PAYLOAD_TOO_LARGE)
public String handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
return e.getMessage();
}
}
上面的方法只能处理单文件的异常,对于多文件上传,一个表单项上传多文件的情况,如果是每个文件不过超过10MB,那么选择两个6MB的同样会报错,可以采用如下配置
@SpringBootApplication(exclude = MultipartAutoConfiguration.class)
在启动类上排除MultipartAutoConfiguration,使用自定义的MultipartResolver
@Value("${spring.servlet.multipart.max-file-size:1MB}")
private String maxFileSize;
@Bean(name = "multipartResolver")
@Primary
public MultipartResolver multipartResolver() {
log.info("maxUploadSize {}", maxFileSize);
long maxSize = DataSize.parse(maxFileSize).toBytes();
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setDefaultEncoding("utf-8");
multipartResolver.setMaxUploadSizePerFile(maxSize);
return multipartResolver;
}
Elasticsearch
使用6.3.2作为开发版本
采用RestHighLevelClient操作
依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.3.2</version>
</dependency>
示例
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
创建索引
client.indices().create(request);
删除索引
client.indices().delete(request);
查询数据
client.search(request);
数据库
PostgreSQL 11.4
持久层框架
MyBatis 3.5.1
mybatis-spring-boot-starter(2.0.1)内部mybatis就是3.5.1
swagger
从2.8.0开始界面变化太大,操作不方便,使用2.7.0
依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
参数校验
比如参数不能为空,一些正则的校验
@NotEmpty(message = "手机号不能为空")
@Pattern(regexp = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$", message = "手机号格式不对")
private String telephone;
示例
请求对象
@Data
public class ParamVo {
@NotEmpty(message = "用户名不能为空")
private String username;
@NotEmpty(message = "手机号不能为空")
@Pattern(regexp = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$", message = "手机号格式不对")
private String telephone;
}
请求controller
@ApiOperation(value = "参数校验")
@PostMapping("/paramValidate")
public ParamVo paramValidate(@RequestBody @Valid ParamVo paramVo) {
return paramVo;
}
统一异常处理
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleBindException(MethodArgumentNotValidException e) {
// log.error("参数校验异常:{}", e);
StringBuilder errorStr = new StringBuilder();
e.getBindingResult().getAllErrors().
forEach(x -> errorStr.append(x.getDefaultMessage() + ","));
String message = errorStr.substring(0, errorStr.length() - 1);
// message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return message;
}