由于每次在搭建项目的时候,都需要写各种配置,包括xml依赖配置,yml配置,有时候一些基本的注解也需要重复调用,但是碍于本人实在是懒得记,都是复制粘贴于上一个项目,这样还是感觉不太好,所以打算总结一些有哪些常见的配置文件的写法
pom.xml常见配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>***</groupId>
<artifactId>***</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>***</name>
<description>***</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!--配置swagger-->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.1.0</version>
</dependency>
<!--jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--阿里云fastJson依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<!--阿里云OSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
<!--pagehelper插件起步依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<!--解决JDK 11 兼容性问题-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
一些常用的依赖(除去Springboot构建时自带)基本可以复制粘贴(复制于某一练手项目)
上面的写法版本管理可能有点麻烦,可以采用以下写法
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
<skipTests>true</skipTests>
<druid.version>1.2.20</druid.version>
<hutool.version>5.8.22</hutool.version>
<mysql-connector.version>8.0.33</mysql-connector.version>
<jjwt.version>0.12.3</jjwt.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<springdoc-openapi.version>2.2.0</springdoc-openapi.version>
<velocity.version>2.3</velocity.version>
<spring-context.version>6.1.3</spring-context.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<docker.host>http://47.99.148.150:2380</docker.host>
<docker.maven.plugin.version>0.40.0</docker.maven.plugin.version>
</properties>
//摘至项目学长配置
想实现映射,需使用占位符${}
例如:${hutool.version}
但是,如果要实现这种映射,需要加一个配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
配置docker的xml配置
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.maven.plugin.version}</version>
<executions>
<!--如果想在项目打包时构建镜像添加-->
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Docker 远程管理地址-->
<dockerHost>${docker.host}</dockerHost>
<images>
<image>
<!--定义镜像名称-->
<name>ha_pancake_3/${project.name}:${project.version}</name>
<!--定义镜像构建行为-->
<build>
<!--定义基础镜像-->
<from>openjdk:17</from>
<args>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</args>
<!--定义哪些文件拷贝到容器中-->
<assembly>
<!--定义拷贝到容器的目录-->
<targetDir>/</targetDir>
<!--只拷贝生成的jar包-->
<descriptorRef>artifact</descriptorRef>
</assembly>
<!--定义容器启动命令-->
<entryPoint>["java", "-jar","/${project.build.finalName}.jar"]</entryPoint>
<!--定义维护者-->
<maintainer>why</maintainer>
</build>
</image>
</images>
</configuration>
</plugin>
docker可以参考这篇文章:https://blog.csdn.net/single_0910/article/details/121202659
附加Dockerfile写法:
# 该镜像需要依赖的基础镜像
FROM openjdk:17
# 将当前目录下的jar包复制到docker容器的/目录下
ADD ./hapancake-1.0.0-SNAPSHOT.jar /hapancake-1.0.0-SNAPSHOT.jar
# 声明服务运行在8090端口
EXPOSE 8090
# 指定docker容器启动时运行jar包
#COPY *.jar /hapancake-1.0.0-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar","/hapancake-2.0.0-SNAPSHOT.jar"]
# 指定维护者的名字
MAINTAINER coco
yml配置文件
spring活动配置
spring:
application:
name: 项目名
profiles:
active: prod #活动配置文件,命名规则:application-dev,application-prod
mvc:
pathmatch:
matching-strategy: ant_path_matcher
Spring允许循环依赖
spring:
main:
allow-circular-references: true
spring数据库连接配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://ip地址:端口号/数据库名称
username:用户名
password: 密码
spring日志输出配置
logging:
file:
path: /var/logs #日志输出路径
level:
root: info #
com.example.hapancake: info #项目名?
端口配置
server:
port: 8080
mybatisplus配置
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
configuration:
auto-mapping-behavior: partial
map-underscore-to-camel-case: true #驼峰映射
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志输出
swagger配置
springdoc:
api-docs:
# 是否开启接口文档
enabled: true
swagger-ui:
# 持久化认证数据,如果设置为 true,它会保留授权数据并且不会在浏览器关闭/刷新时丢失
persistAuthorization: true
path: /swagger-ui.html
常见配置类
拦截器配置
/*
* 本类用于配置拦截器
* */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor)
.addPathPatterns("/**").excludePathPatterns(
"/login/**",
"/enroll",
"/swagger**/**",
"/webjars/**",
"/v3/**",
"/doc.html",
);
}
}
swagget配置
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("标题")
.description("我的API文档")
.version("v1")
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("外部文档")
.url("https://springshop.wiki.github.org/docs"));
}}
mybatisplus分页工具配置类
@Configuration
public class MybatisConfig {
/*
* 配置mybatis plus分页插件
* */
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//1.初始化核心插件
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//2.添加分页插件
PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
pageInterceptor.setMaxLimit(1000L);//设置分页上限
interceptor.addInnerInterceptor(pageInterceptor);
minio配置
@Configuration
public class MinioConfig {
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint("http://ip地址:端口")
.credentials("hapancake3","hapancake3")
.build();
}
}
附加:minio在linux中的配置:https://blog.csdn.net/Ever_Ardour/article/details/120838919
跨域配置:
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOriginPattern("*");
//该用法在SpringBoot 2.7.0中已不再支持
//config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
常用工具类
拦截器工具(jwtUtil):
public class JwtUtil {
public static long currentId;
private static final long ACCESS_EXPIRE=3200*3;//令牌有效时间3小时
//private static final long ACCESS_EXPIRE=60;//令牌有效时间1分钟
private final static SecureDigestAlgorithm<SecretKey, SecretKey> ALGORITHM = Jwts.SIG.HS256;//加密算法
private final static String SECRET = "****_houduan_***_program_the_team_of_nanbeng";//密钥
public static final SecretKey KEY = Keys.hmacShaKeyFor(SECRET.getBytes());//密钥示例
/**
* 生成jwt令牌
* @author liyang
* @param account 账号
* @param id 主键id
* @return 生成令牌
*/
public static String getToken(String account,long id){
//将设置的延迟时间转换为过期时间
Date expireData = Date.from(Instant.now().plusSeconds(ACCESS_EXPIRE));
return Jwts.builder()
.claim("uid",account)
.claim("id",id)
.expiration(expireData)
.issuedAt(new Date())
.signWith(KEY)
.compact();
}
/**
* 校验token
* 校验这里我通过查找数据库看看token包含的用户信息是否匹配来进行判断,但目前数据库表还没写,于是先这样判断
* @param token token
* @return token有效返回true
*/
public static boolean verifyToken(String token){
return parseToken(token)!=null&&!isTokenExpired(token);
}
/**
* 解析token,获得负载信息
* @author liyang
* @param token token
* @return 负载信息
*/
public static Claims parseToken(String token) {
Claims claims = null;
try {
claims = Jwts.parser().verifyWith(KEY).build().parseSignedClaims(token).getPayload();
} catch (ExpiredJwtException e) {
throw new RuntimeException(e);
}
return claims;
}
/**
*获取uid
*/
public static String decodeUserUid(String token){
return (String) parseToken(token).get("uid");
}
/**
*获取电话号码
*/
// public static long decodeUserPhoneNUm(String token){
// return (long) parseToken(token).get("phoneNUm");
// }
/**
*获取id
*/
public static int decodeUserId(String token){
return (int) parseToken(token).get("id");
}
/**
* 判断token是否过期
* @param token token
* @return 过期返回true
*/
public static boolean isTokenExpired(String token){
return parseToken(token).getExpiration().before(new Date());
}
}
附拦截器:
@Slf4j
@Component
public class LoginEnrollCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.获取jwt令牌
String jwt = request.getHeader("token");
//2.判断jwt令牌是否存在
if(!StringUtils.hasLength(jwt)){
//2.1令牌不存在
response.getWriter().write(JSONUtil.toJsonStr(CommonResult.error("NOT_LOGIN")));
return false;
}
//3.校验jwt令牌
if(JwtUtil.verifyToken(jwt)){
//3.1.校验成功,解析令牌,获取当前登录用户的id
JwtUtil.currentId = JwtUtil.decodeUserId(jwt);
//3.2.放行
return true;
}
else{
response.getWriter().write(JSONUtil.toJsonStr(CommonResult.error("NOT_LOGIN")));
return false;
}
}
}
过滤器filter
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//1.获取请求参数
String url = req.getRequestURI();
log.info("url:",url);
//2.判断请求url是否包含login,若包含则放行
if(url.contains("login")){
log.info("登录操作,放行");
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//3.获取请求头中的令牌
String jwt = req.getHeader("token");
//4.判断令牌是否存在,如果不存在,返回错误信息
if(!StringUtils.hasLength(jwt)){
log.info("令牌不存在");
//Controller层中,@RestController会自动将Result转换为json格式数据,这里使用阿里巴巴提供的方法
resp.getWriter().write(JSONObject.toJSONString(Result.error("NOT_LOGIN"))) ;//返回错误提示信息
return;
}
//5.解析token,若解析失败,返回错误结果(未登录)
try {
JWTUtils.parseJwt(jwt);
} catch (Exception e) {
e.printStackTrace();
log.info("解析失败,返回未登录错误信息");
resp.getWriter().write(JSONObject.toJSONString(Result.error("NOT_LOGIN"))) ;//返回错误提示信息
return;
}
//6.jwt无误,放行
log.info("令牌合法,放行");
filterChain.doFilter(servletRequest,servletResponse);
}
}
全局异常处理器
/**
* 全局异常处理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理用户名重复异常
*/
@ExceptionHandler(value = UsernameDuplicateException.class/*异常的.class文件*/)
public ResultResponse UsernameDuplicateExceptionHandler(UsernameDuplicateException e){
return ResultResponse.error("用户名重复");
}
minioUtil
@Component
public class MinioUtil {
@Resource
MinioClient minioClient;
public String upload(MultipartFile file) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
// 避免文件被覆盖生成唯一uuid
String originalFileName = file.getOriginalFilename();
assert originalFileName != null;
String fileName = UUID.randomUUID().toString() + originalFileName.substring(originalFileName.lastIndexOf("."));
//上传文件
minioClient.putObject(PutObjectArgs.builder()
.bucket("hanpancake")
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.build());
//获取url并返回
String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.bucket("hanpancake").object(fileName)
.method(Method.POST)
.build());
int index = url.indexOf('?');//这里返回的url带签名,这里将签名移除(应该可以处理掉,没找到方法)
url = url.substring(0,index);
return url;
}
}
md5:
public static String md5Hex(String password) {
return DigestUtils.md5Hex(password + salter);
}
常用注解
依赖注入:
@RequiredArgsConstructor(onConstructor_ = {@Autowired})