最近自己在搭建springboot项目的脚手架,涉及了一些常用的maven组件,这些组件对于经验丰富的小伙伴来说是信手拈来,对于刚入门或者转行的小伙伴来说,要想找到这些常用的组件还是比较困难,需要自己一个一个去搜,这里我就直接帮大家总结下吧。
首先,我是基于 springboot 2.3.2.RELEASE 来构建的。
springboot基础脚手架
这是下载springboot相关版本,后面的其他maven包都需要与这个版本对应,否则就会出现版本冲突,出现版本冲突后,我们需要降低或者提高其他依赖包的版本来保持兼容。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
Getter and Setter lombok
lombok
我们在使用idea 创建springboot 项目时,会让我们选择lombok,直接选择即可,他的作用就是在编译的时候帮们给属性自动生成Getter 和 Setter,帮助类生成有参数或无参数的构造函数。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
spring-boot-starter-test
单元测试,注意,单元测试的 包路径最好与 包名称一致。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
mysql相关
我们搭建web主要的就是操作数据库,目前大多数中小型互联网公司都是使用mysql数据库,我们这里来使用 mybatis的加强版 mybatis-plus 来连接数据库吧。
mybatis-plus-boot-starter
这个组件是对mybatis的加强,并没有修改mybatis
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
mysql-connector-java
要想使用mysql,这个组件必须。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
druid-spring-boot-starter
连接池,增加数据库处理性能,阿里出品,必属精品,连接池的配置,可以直接在我上一篇介绍springboot 安装指南获取
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
mybatis-plus-generator
有了数据库的连接,我们需要使用数据库模型文件(DO),如果每次都去手动生成,很浪费我们的时间,我们这里使用 generator插件来帮我们生成 DO, mapper 和 service接口。当然,如果你的myabtis-plus > 3.5.1,那么可以使用新的生成方法,详情见官网mybatis-plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
参数验证相关
spring-boot-starter-validation
我们经常接收用户输入的请求,这些参数需要我们去过滤验证,最后才能交给数据库处理,这里我们就使用 validation 开箱即可用。当我们安装好依赖后,还需要去捕获验证的异常,友好的提示返回给用户。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
捕获参数异常
package com.xxx.exception.handler;
//xxx 是我的真实报名,我替换了,
//ResponseEntity 是一个返回 code, data, msg的类
import com.xxx.entity.ResponseEntity;
import com.xxx.enums.TipsEnum;
import com.xxx.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
/**
* 全局异常处理类
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 验证异常
* @param e 参数异常
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity handle(MethodArgumentNotValidException e) {
e.printStackTrace();
return ResponseEntity.error(e.getBindingResult().getFieldError().getDefaultMessage(), TipsEnum.PARAMETER_ERROR.getCode());
}
@ExceptionHandler(BindException.class)
public ResponseEntity handle(BindException e) {
e.printStackTrace();
return ResponseEntity.error(e.getBindingResult().getFieldError().getDefaultMessage(), TipsEnum.PARAMETER_ERROR.getCode());
}
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity handle(ConstraintViolationException e) {
e.printStackTrace();
StringBuffer buffer = new StringBuffer();
for (ConstraintViolation<?> consts : e.getConstraintViolations()) {
buffer.append(consts.getMessage());
}
return ResponseEntity.error(buffer.toString(), TipsEnum.PARAMETER_ERROR.getCode());
}
}
redis缓存
RedisTemplate 和 Redisson
redis可以采用RedisTemplate, 也可以使用Redisson, 这里我把两个都写出来吧,
当然这两个写出来后,都需要自己去实现一个bean,初始化redis 序列化的实现,这个在我之前的一篇博客有,就不一一列举了。对于简单的缓存,我们可以使用注解来实现,复杂的注解可以使用StringReidsTemplate 或者 RedissonClient 来操作。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.6</version>
</dependency>
AOP spring-boot-starter-aop
如果我们要记录请求和返回日志,可以使用aop,面向切面编程,然后切入切点到我们的controller 包内,就可以实现
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
package com.yy.dd.aspect;
import com.alibaba.fastjson.JSON;
import com.yy.dd.enums.HeaderEnum;
import io.swagger.v3.oas.annotations.Operation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 切面,http请求和返回日志
*/
@Slf4j
@Aspect
@Component
public class LogAspect {
/**
* 请求参数
*/
@Data
class LogParams {
private String date;
private String domain;
private String ip;
private String token;
private String traceId;
private String method;
private String pathInfo;
private String actions;
private String level;
private String message;
private Object[] params;
private String extra;
}
/**
* 返回参数
*/
@Data
class ResponseParams {
private Object result;
private Long cost;
}
//切入控制器包下的所有控制器,有请求和返回的日志
@Pointcut("within(com.yy.dd.controller..*)")
public void httpLog() {
}
@Around("httpLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
if (proceedingJoinPoint == null) {
return null;
}
Object result = proceedingJoinPoint.proceed();
long cost = System.currentTimeMillis() - startTime;
ResponseParams responseParams = new ResponseParams();
responseParams.setResult(result);
responseParams.setCost(cost);
log.info("返回参数: {}", JSON.toJSONString(responseParams));
return result;
}
@Before("httpLog()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
//根据springdoc 文档的注解来读取接口的备注名称
Operation tag = method.getAnnotation(Operation.class);
String msg = "ingore";
if (tag != null) {
msg = tag.summary();
}
Object[] args = joinPoint.getArgs();
LogParams params = new LogParams();
params.setDate(DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
params.setDomain(request.getServerName());
params.setIp(request.getRemoteAddr());
params.setToken(request.getHeader(HeaderEnum.AUTHORIZATION.getHeader()));
params.setTraceId(request.getHeader(HeaderEnum.TRACE_ID.getHeader()));
params.setMessage(request.getMethod());
params.setPathInfo(request.getPathInfo());
String controllerAndMethod = joinPoint.getSignature().getDeclaringTypeName() + "@" + joinPoint.getSignature().getName();
params.setActions(controllerAndMethod);
params.setLevel("info");
params.setMessage(msg);
if (ignoreController(controllerAndMethod)) {
//忽略文件上传的参数
params.setParams(null);
} else {
params.setParams(args);
}
params.setExtra("");
if (!controllerAndMethod.toLowerCase().contains("swagger")) {
log.info("请求参数: {}", JSON.toJSONString(params));
}
}
@After("httpLog()")
public void doAfter() {
}
/**
* 忽略记录请求参数的控制器
* @param currentController 忽略记录参数的控制器
* @return
*/
private Boolean ignoreController(String currentController) {
List<String> controllers = new ArrayList<>();
controllers.add("UploadController@upload"); //上传方法忽略
controllers.add("LoginController@import"); //导入方法忽略
controllers.add("LoginController@download"); //下载方法忽略
for (String con : controllers) {
if (currentController.contains(con)) {
return true;
}
}
return false;
}
}
fastjson 友好处理json
这个版本至少在1.2.69以上,1.2.68 有反序列化漏洞。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
commons-pool2 对象池处理工具
这是apache 出品,主要针对对象安全做了处理,java 原始包提供的没有很好的处理线程安全问题。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
commons-io 对 io处理的封装
很好的处理 文件的读写,字符和字节处理
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
commons-lang3 对java lang 包的封装
主要处理日期、字符串、数字等,号称java的第二api,很好用。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
rabbitmq - spring-boot-starter-amqp
springboot mq 是开箱即用的,非常方便
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
okhttp3 http请求包,类似curl
okhttp3 提供了 restful 所有请求的实现,同时支持传统的form表单提交,文件上传等。
使用前,也需要配置Bean, 配置相关参数
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>
springdoc 接口文档
springdoc 是一直在维护的文档,和swagger一样,可以方便的实现接口文档生成
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
配置bean 后 容器可以管理它,直接使用 Tag、Operation和Schema 就可以进行文档编写了
package com.yy.dd.config;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringDocConfig {
@Bean
public OpenAPI dcOpenApi() {
return new OpenAPI()
.info(new Info()
.title("接口文档")
.description("java接口文档")
.version("v0.0.1")
.license(new License()
.name("许可协议")
.url("http://127.0.0.1:8089"))
.contact(new Contact()
.name("dd-yy team")
.email("example@gmail.com")
)
)
.externalDocs(new ExternalDocumentation()
.description("dd team")
.url("http://127.0.0.1:8089")
);
}
/**
* 接口文档分组
* @return
*/
@Bean
public GroupedOpenApi adminApi() {
return GroupedOpenApi.builder().group("admin").pathsToMatch("/admin/**").build();
}
}
spring-cloud 相关组件
spring-cloud-starter-alibaba-nacos-config
安装nacos服务端和配置,请参考springboot安装指南
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
spring-cloud-starter-alibaba-nacos-discovery
这是服务注册与发现
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
spring-cloud-starter-openfeign
服务调用,接口方式 feign, 也可以使用RestTemplate
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
easyexcel 操作execel 上传和下载
她也是阿里出品的,文档地址:EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
oss 文档存储
阿里云,阿里的文档看 快速入门就可以搞定 上传和下载了。
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.0</version>
</dependency>
亚马逊云,亚马逊的对接稍微麻烦点。
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
<version>2.18.18</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.18.18</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>iam</artifactId>
<version>2.18.18</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>kinesis</artifactId>
<version>2.18.18</version>
</dependency>