java可复用代码
文章目录
- 插件相关复用
- 插件离线下载
- 1EasyCode
- 什么是EasyCode
- 配置
- 数据库属性设置
- 模版设置
- 使用方法
- 注意
- 新建文件模版
- JDBC
- database
- mappers
- mybatis
- MybatisUtils
- spring-mvc
- spring-mybatis
- 工具类
- AliOssUtil
- yaml配置
- 依赖
- java类代码
- 使用
- 密码
- JwtUtil
- 依赖
- 工具类
- 拦截器
- 注册响应拦截器
- ThreadLocalUtil
- 工具类
- 拦截器
- 注册响应拦截器
- 日期时间反序列化
- 注解validation
- 依赖
- 自定义全局异常处理器
- 自定义配置
插件相关复用
插件清单
名称 | 作用 |
---|---|
Chinese (Simplified) Language Pack /中文语言包 | 汉化插件 |
MyBatisX | Mybatis插件 |
通义灵码 | ai插件 ctrl + ↓ 使用ai提示的代码。 |
EasyCode(重点) | 一键生成实体类(Entity)、数据访问层(DAO/Mapper)、服务层(Service)、控制器(Controller)以及XML映射文件。建议搭配Lombok使用,通过注解自动生成Getter/Setter等方法。 |
Lombok插件 | 通过注解自动生成实体类中常见的 Getter/Setter、构造方法、toString()、equals() 和 hashCode() 等方法 |
Eclipse Groovy Compiler Plugin | 整合 Eclipse 生态的成熟编译能力,为 IDEA 用户提供了更完整的 Groovy 开发支持。Groovy 是一种基于 Java 虚拟机(JVM) 的 动态编程语言 |
插件离线下载
-
打开下载网址
-
离线下载
-
选择合适版本
-
第四步从设置打开
-
选择从磁盘安装插件
-
选择zip文件(注意不要解压出来)
-
点击应用然后重启idea
1EasyCode
什么是EasyCode
EasyCode:一键生成实体类(Entity)、数据访问层(DAO/Mapper)、服务层(Service)、控制器(Controller)以及XML映射文件。建议搭配Lombok使用,通过注解自动生成Getter/Setter等方法。
配置
数据库属性设置
全局配置File → Settings → Other Settings → Easy Code → Type Mapper。
临时配置:生成代码的弹窗界面中,点击Type Mapper标签页,可针对当前操作临时调整映射规则
模版设置
除了生成自带的Entity,DAO/Mapper,Service,Controller,XML映射文件,还可自己配置。
下面是File → Settings → Other Settings → Easy Code → Template 点击加号生成新的Template命名为 pojo
##引入宏定义
$!{define.vm}##使用宏定义设置回调(保存位置与文件后缀)
#save("/pojo", ".java")##使用宏定义设置包后缀
#setPackageSuffix("pojo") ## 修改为pojo##使用全局变量实现默认包导入
$!{autoImport.vm}
import java.io.Serializable;
## 新增Lombok包导入(需确保项目已添加Lombok依赖)
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;##使用宏定义实现类注释信息
#tableComment("实体类")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class $!{tableInfo.name} implements Serializable {private static final long serialVersionUID = $!tool.serial();
#foreach($column in $tableInfo.fullColumn)#if(${column.comment})/*** ${column.comment}*/#endprivate $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end## 已移除以下get/set方法生成代码块
}
使用这个模版会生成如下的代码
package com.itheima.helloworld.pojo;import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
/*** (Admin)实体类** @author makejava* @since 2025-03-27 10:37:52*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Admin implements Serializable {private static final long serialVersionUID = -31625727804398432L;private Integer id;private String adminname;private String adminpassword;private Integer age;}
添加@TableComment等自定义注解
附加属性:通过 Settings→EasyCode→Extra Column 添加虚拟字段(如逻辑删除标志deleted)
Lombok整合:在实体类模板中启用@Data注解,需提前在项目pom.xml添加Lombok依赖
使用方法
1下载
File(文件) —> Settings(设置) —> Plugins(插件) 搜索EasyCode
2 数据库连接,使用MySQL
3 在Database面板中右键选中目标表(支持多选),点击 EasyCode → Generate Code,进入配置界面
4 配置生成路径与模板
Module/Package:指定实体类存放的模块和包路径(如com.example.entity)
模板选择:在"Template"选项卡勾选"Entity"模板组 可以使用自己配置到Template
字段映射:检查数据库字段与Java类型的映射规则(如varchar→String)。上面配置的数据库属性设置
注意
1 如果模版有需要使用Lombok时,要在项目pom.xml中添加最新版Lombok依赖。
2 在IDEA设置中开启注解:
Build, Execution, Deployment→Compiler→Annotation Processors
勾选Enable annotation processing
勾选此选项后,IDEA会在编译时自动调用注解处理器,根据代码中的注解生成额外代码。例如:
- Lombok:通过@Data、@Getter等注解自动生成Getter/Setter方法
- MyBatis:通过
@Mapper
注解生成DAO接口实现类 - JPA:通过实体类注解生成DDL语句
新建文件模版
java新建模版的使用
选中右侧某个文件夹
JDBC
#数据库驱动
jdbc.driver=com.mysql.jdbc.Driver
#数据库地址
jdbc.url=jdbc:mysql://127.0.0.1:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false
#用户名
jdbc.username=root
#密码
jdbc.password=root
#最大连接数
c3p0.maxPoolSize=30
#最小连接数
c3p0.minPoolSize=10
#关闭连接后不自动commit
c3p0.autoCommitOnClose=false
#获取连接超时时间10000毫秒
c3p0.checkoutTimeout=10000
#当前获取连接失败重试次数
c3p0.acquireRetryAttempts=2
database
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/smbms?useSSL=false&&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true
uname = root
upwd = root
mappers
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="dao.XXXDao">
// 具体路径 若使用注解,下面可不写<select id="findId" resultType="pojo.Course"></select>
</mapper>
mybatis
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><!--配置数据源环境-->
<configuration><properties resource="batabase.properties"/><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><typeAliases><!-- 看具体路径,若为main/java/com/hz/pojo <package name="com.hz.pojo"/> --><package name="pojo"/></typeAliases><environments default="aa"><environment id="aa"><transactionManager type="JDBC"></transactionManager><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${uname}"/><property name="password" value="${upwd}"/></dataSource></environment></environments><!-- 3.读取映射文件--><!-- <mappers>--><!-- <mapper resource="xx文件夹/映射文件.xml"/>--><!-- </mappers>--><mappers><mapper resource=".xml"></mapper></mappers></configuration>
MybatisUtils
package utils;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class MybatiesUtils {private static SqlSessionFactory factory;static {try {InputStream is = Resources.getResourceAsStream("mybatis.xml");factory= new SqlSessionFactoryBuilder().build(is);
// SqlSession sqlSession= factory.openSession(true);} catch (IOException e) {throw new RuntimeException(e);}}public static SqlSession create(){return factory.openSession();}public static void close(SqlSession sqlSession){if(sqlSession!=null){sqlSession.close();}}// 关于使用
// SqlSession sqlSession = MybatiesUtils.create(); 创建
// CourseDao courseDao = sqlSession.getMapper(CourseDao.class); 转成类
// List<Course> course = courseDao.findAll(); 使用
// for (Course c:course) { for循环
// System.out.println(c);
// }
}
spring-mvc
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- web.xml跳到这,然后在这寻找需要的controller --><!--<bean name="/index" class="com.hz.controller.IndexController"/>--><!-- 扫描com.hz.controller下的文件 --><context:component-scan base-package="com.hz.controller"/><!-- 开启MVC注解 对应controller中的@RequestParam()--><mvc:annotation-driven/></beans>
spring-mybatis
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--1.读取数据库属性文件--><context:property-placeholder location="classpath:jdbc.properties"/><!--2.配置数据源 new c3p0类()--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="maxPoolSize" value="${c3p0.maxPoolSize}"/><property name="minPoolSize" value="${c3p0.minPoolSize}"/><property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}"/><property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/><property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"/></bean><!--3.创建SqlSessionFactory工厂对象--><bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"><!--//加载数据源--><property name="dataSource" ref="dataSource"/><!--读取mappers包下所有的映射文件--><property name="mapperLocations" value="classpath:mappers/*.xml"/><!--简化实体类的包名(路径)--><property name="typeAliasesPackage" value="com.hz.pojo"/><!--如果mybatis.xml文件中不需要log日志配置 不需要读取mybatis.xml--><!--<!–读取mybatis.xml文件–>--><!--<property name="configLocation" value="classpath:mybatis.xml"/>--></bean><!--4.创建MapperScannerConfigurer类的对象 SqlSession--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--扫描dao层--><property name="basePackage" value="com.hz.dao"/></bean><context:component-scan base-package="com.hz.*"/><!-- 上面这句相当于 <context:component-scan base-package="com.hz.dao,com.hz.service,com.hz.controller"/> --><!--开启事务 提供数据源--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--给事务指定数据源--><property name="dataSource" ref="dataSource"></property><!--数据源注入Dao层注意:原本是sessionFactory对象注入 注入的是一个bean用ref,但是固定写法用value这个属性(spring自行识别搞定注入)因为可以根据数据类型和名字匹配 自动注入所以这个属性配置可写可不写--><!--<property name="sqlSessionTemplateBeanName" value="sqlSessionFactory"/>--></bean><tx:annotation-driven></tx:annotation-driven><aop:aspectj-autoproxy></aop:aspectj-autoproxy><!-- spring-mvc --><!-- web.xml跳到这,然后在这寻找需要的controller --><!--<bean name="/index" class="com.hz.controller.IndexController"/>--><!-- 开启MVC注解 对应controller中的@RequestParam()--><mvc:annotation-driven/><!--页面中使用html css js 图片 释放静态资源--><!--<mvc:default-servlet-handler/>--><!--多个文件夹中有多个页面时 使用//视图渲染器 (简化页面路径) 跳转页面的后缀及其前缀都可以省略--><!--比如:webapp下有aa文件夹 aa文件夹里面有main,jsp页面 webapp/aa/main.jsp--><!--跳转main.jsp 可以如下配置 /aa/main.jsp 跳转路径可以写成 aa/main (/:表示根也就是 webapp) --><!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">--><!--<property name="prefix" value="/"></property>--><!--<property name="suffix" value=".jsp"></property>--><!--</bean>-->
</beans>
工具类
AliOssUtil
yaml配置
spring:servlet:multipart:# 传入文件大小max-file-size: 1000MBmax-request-size: 1000MB
依赖
<!-- 阿里云的OSS依赖坐标 --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency>
java类代码
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class AliOssUtil {private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";private static final String ACCESS_KEY_ID = "LTAI5tKhnJx38S3MJUxhVbNa";private static final String SECRET_ACCESS_KEY = "i1Y0e6gt78Wh67NURq5rhERHfU0Fr1";private static final String BUCKET_NAME = "teenage-education-network";/*** 上传本地视频文件到OSS* @param localFilePath 本地文件完整路径(如:"D:/videos/demo.mp4")* @return 文件的公网访问地址,上传失败返回空字符串*/public static String uploadLocalVideo(String localFilePath) {File file = new File(localFilePath);// 从路径中提取文件名作为OSS存储名称String objectName = file.getName();// 自动添加视频存储目录(可选)// String objectName = "videos/" + file.getName();try (InputStream inputStream = new FileInputStream(file)) {return uploadFile(objectName, inputStream);} catch (IOException e) {System.out.println("本地文件读取失败: " + e.getMessage());e.printStackTrace();return "";}}/** uploadFile方法* objectName:文件名称比如 "YEjdihp893bif1.jpg"* inputStream:文件流,用于读取文件比如,D:\Users\Administrator\Desktop\YEjdihp893bif1.jpg* 下面有使用流程* *///上传文件,返回文件的公网访问地址public static String uploadFile(String objectName, InputStream inputStream){// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACCESS_KEY_ID,SECRET_ACCESS_KEY);//公文访问地址String url = "";try {// 创建存储空间。ossClient.createBucket(BUCKET_NAME);ossClient.putObject(BUCKET_NAME, objectName, inputStream);// 这里是返回阿里云的url地址url = "https://"+BUCKET_NAME+"."+ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1)+"/"+objectName;} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}return url;}/*** 根据文件URL删除OSS上的文件* @param fileUrl 文件的完整URL(如:"https://teenage-education-network.oss-cn-beijing.aliyuncs.com/example.jpg")* @return 是否删除成功* String fileUrl = "https://teenage-education-network.oss-cn-beijing.aliyuncs.com/08c1a4f4-6a51-4cb1-babb-dfd101c5f5a3.mp4"* boolean success = AliOssUtil.deleteFile(fileUrl);* System.out.println(success ? "删除成功" : "删除失败");*/public static boolean deleteFile(String fileUrl) {// 从URL中提取object名称String objectName = extractObjectNameFromUrl(fileUrl);if (objectName == null || objectName.isEmpty()) {System.out.println("无法从URL中解析出有效文件路径");return false;}OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, SECRET_ACCESS_KEY);try {ossClient.deleteObject(BUCKET_NAME, objectName);return true;} catch (OSSException oe) {System.out.println("OSS异常: " + oe.getErrorMessage());} catch (ClientException ce) {System.out.println("客户端异常: " + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}return false;}/*** 从URL中提取OSS文件路径(object name)* 示例输入:https://teenage-education-network.oss-cn-beijing.aliyuncs.com/abc/example.jpg* 示例输出:abc/example.jpg*/private static String extractObjectNameFromUrl(String fileUrl) {try {// 移除URL协议头和参数String cleanedUrl = fileUrl.split("\\?")[0] // 去除参数.replace("https://", "").replace("http://", "");// 验证域名是否正确String expectedDomainPrefix = BUCKET_NAME + "." + ENDPOINT.replace("https://", "");if (!cleanedUrl.startsWith(expectedDomainPrefix + "/")) {System.out.println("URL不属于当前OSS Bucket");return "";}// 提取object路径return cleanedUrl.substring(expectedDomainPrefix.length() + 1);} catch (Exception e) {e.printStackTrace();return "";}}}
使用
@RestController
@RequestMapping("/upload")
public class UploadController {// 本次请求通过elementPlus的el-upload组件上传图片,通过el-upload组件的属性发起请求// 前端上传路径action="/api/upload/imgUpload" 要和后端一致 这里的/api是前端的反向代理的标识// 前端的name="img" 是这里的形参名// 前端的请求头添加token :headers="{'Authorization':tokenStore.token}"@PostMapping("/imgUpload")public Result<String> imgUpload(@RequestParam("img") MultipartFile img)throws IOException {
// System.out.println(img);if (img == null || img.isEmpty()) {// 处理文件为空的情况return Result.error("文件不能为空");}String originalFilename = img.getOriginalFilename();// 生成新的唯一的文件名String fileNmae = UUID.randomUUID().toString()+originalFilename.substring(originalFilename.lastIndexOf("."));String url = AliOssUtil.uploadFile(fileNmae, img.getInputStream());System.out.println(url);return Result.success(url);}}
密码
JwtUtil
依赖
<!-- JWT --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency>
工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static final String KEY = "xrkhy";// 配置秘钥//接收业务数据,生成token并返回public static String genToken(Map<String, Object> claims) {return JWT.create().withClaim("claims", claims)// 添加载荷.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24))//添加过期时间这是12个小时.sign(Algorithm.HMAC256(KEY));//指定算法配置秘钥}//接收token,验证token,并返回业务数据public static Map<String, Object> parseToken(String token) {return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token)//验证Token,生成解析后的jwt对象.getClaim("claims").asMap();}}
拦截器
package com.Teenage_education_network.interceptors;
// @/src/main/java/com/公司名/interceptors/interceptor.java
import com.Teenage_education_network.pojo.Result;
import com.Teenage_education_network.utils.JwtUtil;
import com.Teenage_education_network.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;//注册响应拦截器,添加到IOC容器中
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 令牌验证String token = request.getHeader("Authorization");// 解析Tokentry {Map<String,Object> claims = JwtUtil.parseToken(token);// 把业务数据存储到ThreadLocal中ThreadLocalUtil.set(claims);// 放行return true;} catch (Exception e) {// http响应状态码401response.setStatus(401);// 不放行return false;}}}
注册响应拦截器
// @/src/main/java/com/公司名/config/WebConfig
import com.Teenage_education_network.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {// 从IOC容器中注入响应拦截器@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录注册接口不拦截registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");}
}
ThreadLocalUtil
ThreadLocal 工具类 在拦截器中使用
工具类
import java.util.HashMap;
import java.util.Map;/*** ThreadLocal 工具类 在拦截器中使用*/
@SuppressWarnings("all")
public class ThreadLocalUtil {//提供ThreadLocal对象,private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();//根据键获取值public static <T> T get(){return (T) THREAD_LOCAL.get();}//存储键值对public static void set(Object value){THREAD_LOCAL.set(value);}//清除ThreadLocal 防止内存泄漏public static void remove(){THREAD_LOCAL.remove();}
}
拦截器
// @/src/main/java/com/公司名/interceptors/interceptor.java
import com.Teenage_education_network.pojo.Result;
import com.Teenage_education_network.utils.JwtUtil;
import com.Teenage_education_network.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;//注册响应拦截器,添加到IOC容器中
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {ThreadLocalUtil.remove();}
}
注册响应拦截器
// @/src/main/java/com/公司名/config/WebConfig
import com.Teenage_education_network.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {// 从IOC容器中注入响应拦截器@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录注册接口不拦截registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");}
}
日期时间反序列化
<!-- 日期时间类型提供对 LocalDateTime、LocalDate、ZonedDateTime、OffsetDateTime 等 Java 8日期时间类的序列化与反序列化能力。 --><dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>2.13.0</version></dependency>
注解validation
依赖
<!-- validation的使用 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>
自定义全局异常处理器
// @/src/main/java/com/公司名/handler/globalExceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public Result handleValidationError(MethodArgumentNotValidException ex) {List<String> errors = ex.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.toList());return Result.fail(400, "参数错误", errors);}
}
自定义配置
// @/src/main/java/com/公司名/validation/StateValidation
import com.Teenage_education_network.anno.State;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;// 参数说明 ConstraintValidator<给哪个注解提供校验规则,校验规则的数据类型>
public class StateValidation implements ConstraintValidator<State,String> {// 重写isValid方法/**** @param s 需要校验的数据* @param constraintValidatorContext* @return 如果返回false 则校验不通过*/@Overridepublic boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {// 提供校验规则if (s == null || s.isEmpty()) {return false;}return true;}}
// @/src/main/java/com/公司名/anno/State 接口
import com.Teenage_education_network.validation.StateValidation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;import java.lang.annotation.*;@Documented //元注解:注解被包含在文档中
// @Target:注解所修饰的对象范围 ElementType.FIELD作用在jopo类的属性上,
@Target({ElementType.FIELD})
// @Retention:注解在哪个阶段生效 RetentionPolicy.RUNTIME是运行时生效
@Retention(RetentionPolicy.RUNTIME)
// @Repeatable:是否可以重复使用 不需要可以删除
//@Repeatable(List.class)
// @Constraint:谁给这个注解添加校验规则
// validatedBy:指定校验规则的类
@Constraint( validatedBy = { StateValidation.class })
public @interface State {// message:校验失败时,返回给前端的提示信息String message() default "文章内容为空";// 指定分组Class<?>[] groups() default {};// 指定负载 获取到属性的附加信息 一般用不到Class<? extends Payload>[] payload() default {};
}