功能实例
3293字约11分钟
2025-11-21
登录
com/mao/controller/UserPass.java
@RestController
public class UserPass {
@Autowired
private UserService userService;
@PostMapping("/login")
public Result login(@RequestBody User user) {
User user1 = userService.login(user);
// 数据库中查不到数据,则报错
return user1 != null ? Result.success() : Result.error("用户名或者密码错误");
}
}com/mao/service/UserService.java
public interface UserService {
User login(User user);
}com/mao/service/impl/UserServiceImpl.java
@Service
public class UserServiceImpl implements com.mao.service.UserService {
@Autowired
private UserMapper userMapper;
@Override
public User login(User user) {
User user1 = userMapper.getByUsernameAndPasswrd(user);
return user1;
}
}com/mao/mapper/UserMapper.java
@Mapper // 会自动生成该接口的实现类对象(代理对象),交给IOC容器管理
public interface UserMapper {
@Select("select * from user1 where name = #{name} and age = #{age}")
public User getByUsernameAndPasswrd(User user);
}发送链接:127.0.0.1:9000/login
{
"name": "zhangsna",
"age": "20"
}会话技术



JWT令牌

pom.xml
<!-- JWT 核心 API -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version> <!-- 最新稳定版,可按需更新 -->
</dependency>
<!-- 默认实现(必须引入,否则无法运行) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope> <!-- 运行时依赖 -->
</dependency>
<!-- 签名算法支持(如 HMAC、RSA 等,按需选择) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- 包含 JSON 处理和常用算法 -->
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>com/mao/controller/UserPass.java(发送自定义业务数据)
@Autowired
private UserService userService;
@PostMapping("/login")
public Result login(@RequestBody User user) {
User user1 = userService.login(user);
if (user1 != null) {
Map<String, Object> map = new HashMap();
map.put("id", user1.getId());
map.put("name", user1.getName());
map.put("age", user1.getAge());
String jwt = JwtUtils.getJwt(map);
return Result.success(jwt);
}
return Result.error("用户名或者密码错误");
}com/mao/utils/JwtUtils.java(生成JWT令牌)
public class JwtUtils {
// 生成256位强密码
private static SecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);
public static String getJwt(Map<String, Object> token) {
String jwt = Jwts.builder() // 创建JWT构建器
.setClaims(token) // 自定义业务数据(如用户 ID、角色、权限等)
.setIssuedAt(new Date()) // 签发时间
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 过期时间1小时
// 签名算法和自定义密钥,用于检测令牌是否被篡改
.signWith(secretKey)
// 将构建器配置的所有信息(header、payload、signature)组合并编码为最终的 JWT 字符串
.compact();
return jwt;
}
}时间单位关系:
1 秒 = 1000 毫秒(ms)
1 分钟 = 60 秒
1 小时 = 60 分钟
所以 3600000 毫秒为1小时校验JWT令牌
@Test
public void JWT2() {
Claims claims = Jwts.parser()
.setSigningKey("自定义密钥") // secretKey
.parseClaimsJws("JWT 字符串") // jwt
.getBody();
System.out.println(claims);
}过滤器 Filter
过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等




pom.xml(调用阿里巴巴库:JSON.toJSONString)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>com/mao/filter/Filter1.java(过滤器)
@Slf4j
// 设置要过滤的url
@WebFilter(urlPatterns = "/*")
public class Filter1 implements Filter {
@Override
// 初始化方法
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
// 拦截请求之后调用
// 通过 servletRequest 读请求 → 判断是否拦截 →
// 拦截则用 servletResponse 写响应,不拦截则用 filterChain 放行
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
log.info("链接已拦截");
// 1.强转为 HTTP 专用对象,方便获取请求 URL、请求头(token)等 HTTP 相关信息。
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String url = request.getRequestURI().toString();
log.info("请求URL {}", url);
// 2.判断请求的url中是否包含有login,如果包含,则说明是登录操作,则放行
if (url.contains("login")) {
log.info("登录放行操作,放行。。。");
filterChain.doFilter(request, response);
return;
}
// 3.获取请求头中的 JWT 令牌
String jwt = request.getHeader("token");
// 4.如果请求头中有没有 token(或 token 为空字符串),直接返回 “未登录” 错误
if (!StringUtils.hasLength(jwt)) {
log.info("请求头token为空,则返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
String noLogin = JSON.toJSONString(error);
// 返回 JSON 格式的未登录错误信息
response.getWriter().write(noLogin);
return;
}
// 5.令牌合法性校验
try {
JwtUtils.getClaims(jwt);
} catch (Exception e) {
e.printStackTrace();
log.info("解析令牌失败,返回未登录错误信息");
Result error = Result.error("NOT_LOGIN");
String noLogin = JSON.toJSONString(error);
response.getWriter().write(noLogin);
return;
}
// 6.放行操作(放行响应和请求)
log.info("令牌合法,放行");
filterChain.doFilter(request, response);
}
@Override
// 销毁方法
public void destroy() {
Filter.super.destroy();
}
}拦截器


pom.xml(调用阿里巴巴库:JSON.toJSONString)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>com/mao/interceptor/LoginCheckInterceptor.java(拦截器)
@Slf4j
// 拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
// 请求处理之前执行(核心拦截点),返回true放行,返回false拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("链接已拦截");
String url = request.getRequestURI().toString();
log.info("请求URL {}", url);
// 2.判断请求的url中是否包含有login,如果包含,则说明是登录操作,则放行
if (url.contains("login")) {
log.info("登录放行操作,放行。。。");
return true;
}
// 3.获取请求头中的 JWT 令牌
String jwt = request.getHeader("token");
// 4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
if (!StringUtils.hasLength(jwt)) {
log.info("请求头token为空,则返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
String noLogin = JSON.toJSONString(error);
response.getWriter().write(noLogin);
return false;
}
// 5.令牌合法性校验
try {
JwtUtils.getClaims(jwt);
} catch (Exception e) {
e.printStackTrace();
log.info("解析令牌失败,返回未登录错误信息");
Result error = Result.error("NOT_LOGIN");
String noLogin = JSON.toJSONString(error);
response.getWriter().write(noLogin);
return false;
}
// 6.放行操作(放行响应和请求)
log.info("令牌合法,放行");
return true;
}
// 请求处理之后、视图渲染之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
// 请求处理完全结束后执行(最终清理)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}com/mao/config/WebConfig.java(拦截规则)
@Configuration // 配置类
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
// 注册拦截器并配置拦截规则
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}@Configuration与 @Component 的区别
| 特性 | @Configuration | @Component |
|---|---|---|
| 核心用途 | 定义 Bean 配置逻辑 | 标记普通组件(如业务类) |
@Bean 方法处理 | 默认代理,保证单例 | 无代理,@Bean 方法调用创建新实例 |
| 扫描优先级 | 专门的配置类,Spring 优先解析 | 普通组件,按需扫描 |
全局异常处理
// 这段代码是一个 全局异常处理器,用于统一捕获和处理 Spring 应用中抛出的异常
@RestControllerAdvice
public class GlobalException {
// 捕获所有异常
@ExceptionHandler(Exception.class)
public Result exception(Exception e) {
e.printStackTrace();
return Result.error("全局异常测试");
}
}事务管理
@Transactional


传播行为(b() 的配置) | a() 有事务 | a() 无事务 |
|---|---|---|
| REQUIRED | b() 加入 a() 的事务(a回滚,所以b日志保存失败) | b() 新建事务 |
| REQUIRES_NEW | b() 新建独立事务,a() 事务不受其影响 | b() 新建事务 |
src/main/resources/application.yml
# Spring 事务管理日志
logging:
level:
org.springframework.jdbc.support.JdbcTransactionManager: debug// @Transactional只有运行时异常才会混滚操作。其他异常不会回滚
// (rollbackFor = Exception.class)所有异常都会执行回滚操作
// 所以当删除数据库失败,并报异常,则执行回滚操作
@Transactional(rollbackFor = Exception.class)
@DeleteMapping("/hi/{id}")
public Result delete(@PathVariable Integer id) {
log.info("删除数据");
userMapper.delete(id);
userMapper.delete01(id);
return Result.success("删除成功: " + id);
}// 表示需要新事务,无论当前是否存在已有事务,都会创建一个全新的独立事务。
@Transactional(propagation = Propagation.REQUIRES_NEW)AOP


相当于AOP对象和目标对象结合成一个新的代理对象,然后当我们调用目标对象的时候会自动调用结合好的代理对象,从而实现添加的功能

通知类型

pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class MyAspect {
@Around("execution(* com.mao.service.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
// 运行切入点
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
long time = end - start;
log.info(joinPoint.getSignature() + "运行时间:{}ms", time);
return result;
}
@After("execution(* com.mao.service.*.*(..))")
public void after(JoinPoint joinPoint) throws Throwable {
log.info("after end");
}
@Before("execution(* com.mao.service.*.*(..))")
public void before(JoinPoint joinPoint) throws Throwable {
log.info("before...");
}
@AfterReturning("execution(* com.mao.service.*.*(..))")
public void afterReturning(JoinPoint joinPoint) throws Throwable {
log.info("afterReturning...");
}
@AfterThrowing("execution(* com.mao.service.*.*(..))")
public void afterThrowing(JoinPoint joinPoint) throws Throwable {
log.info("afterThrowing...");
}
}公共切点

自定义注解
com/mao/aop/MyLog.java(声明MyLog)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 声明Mylog
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyLog {}com/mao/service/impl/UserServiceImpl.java(标注MyLog)
@MyLog
@Override
public String login() {
return "hi";
}com/mao/aop/MyAspect.java(当执行 MyLog 标记的方法时,切入)
@Pointcut("@annotation(com.mao.aop.MyLog)")
private void pt(){}
@Around("pt()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
// 运行切入点
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
long time = end - start;
log.info(joinPoint.getSignature() + "运行时间:{}ms", time);
return result;
}通知顺序

切入点表达式


// 多个切入点表达式
@Before("execution(* com.mao.service.UserService.page(..)) ||" +
"execution(* com.mao.service.UserService.login(..))")
public void before(JoinPoint joinPoint) throws Throwable {
log.info("before...");
}获取执行方法的相关信息

@Around("execution(* com.mao.service.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取目标对象的类名
String className = joinPoint.getTarget().getClass().getName();
// 获取目标对象的方法名
String methodName = joinPoint.getSignature().getName();
// 获取目标方法的传入参数
Object[] args = joinPoint.getArgs();
// 让目标方法运行
Object result = joinPoint.proceed();
// 获取目标方法的返回值
log.info("目标方法的返回值:{}", result);
return result;
}打包项目

要理解这些 Maven 生命周期阶段的含义,我们可以逐一说明:
- clean:清理项目,删除编译生成的输出目录(如
target文件夹),确保项目以干净的状态构建。 - validate:验证项目的正确性,检查必要的配置、依赖是否完整有效。
- compile:编译项目的源代码,将
src/main/java下的 Java 源码编译成字节码文件,输出到target/classes目录。 - test:执行单元测试,运行
src/test/java下的测试用例,验证代码逻辑的正确性。 - package:将项目打包,根据项目类型生成对应的包文件(如 Java 项目生成 JAR 包,Web 项目生成 WAR 包),输出到
target目录。 - verify:在打包后执行集成测试、代码质量检查等验证操作,确保包的质量符合要求。
- install:将打包生成的包文件安装到本地 Maven 仓库(通常是用户目录下的
.m2文件夹),以便其他本地项目可以依赖该包。 - site:生成项目的站点文档,包含项目信息、依赖、测试报告等静态网页内容。
- deploy:将打包好的包文件部署到远程 Maven 仓库(如私服),供团队其他成员或项目共享使用。
Bean管理
获取IOC容器中的Bean对象
@SpringBootTest
public class Bash01 {
// IOC 容器管理对象
@Autowired
private ApplicationContext applicationContext;
@Test
public void test() {
// bean名称获取,其首字母要小写
UserServiceImpl bean1 = (UserServiceImpl) applicationContext.getBean("userServiceImpl");
System.out.println(bean1);
// 根据bean的类型获取
UserService bean2 = applicationContext.getBean(UserServiceImpl.class);
System.out.println(bean2);
// 根据bean的名称和类获取
UserService bean3 = applicationContext.getBean("userServiceImpl", UserServiceImpl.class);
System.out.println(bean3);
}
}Bean作用域


Bean对象如果想每次使用的时候都为新的实例,则使用 @Scope("prototype")
第三方Bean
当我们引入第三方的对象时,该对象默认是不在IOC容器中的,所以需要自己手动引入到IOC容器中,方便使用
@Configuration
public class CommonConfig {
// SAXReader读取XML文件的第三方对象
@Bean // 将该方法的返回值交给IOC容器管理,成为IOC容器Bean
public SAXReader saxParser() {
return new SAXReader();
}
}自动配置(引入外部自定义对象)
**src/main/java/utils/java/**Hi.java
public class Hi {
public String hi() {
return "hi";
}
}**src/main/java/utils/java/**Bean01.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 自定义定义多个Bean对象
@Configuration
public class Bean01 {
// 定义自定义Bean
@Bean
public Hi Hi() {
return new Hi();
}
}**src/main/java/utils/java/**MyImportSelector.java
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {"utils.java.Bean01"};
}
}**src/main/java/utils/java/**Zhujie.java
import org.springframework.context.annotation.Import;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(Bean01.class) // 导入Bean01对象
public @interface Zhujie { }**src/test/java/com/mao/**Bash01.java
@SpringBootTest
@Zhujie // 通过Zhujie接口访问到Bean01对象,然后在问到Bean01中的方法
public class Bash01 {
@Autowired
private Bean01 Bean01;
@Test
public void test2() {
System.out.println(Bean01.Hi().hi()); // hi
}
}SpringBoot默认是无法扫描外部对象的,所以通过自定义的注解调用
自定义starter库

创建SpringBoot项目,然后进行精简,大概文件如下

starter 是 “入口”,autoconfigure 是 “核心逻辑”,两者配合实现 Spring Boot 最核心的 “自动配置
具体流程:项目引入starter,通过starter调用autoconfigure中的代码
ceshi-spring-boot-autoconfigure
com/maven1/Name.java
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @Data @ConfigurationProperties(prefix = "ceshi") public class Name { private String name = "autoconfigure01ceshi"; public String name() { return name; } }com/maven1/AutoConfig01.java()
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties(Name.class) public class AutoConfig01 { @Bean public Name Name() { return new Name(); } }resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.maven1.AutoConfig01pom.xml
<!-- 其它代码省略 --> // 删除 <!-- <name>ceshi-spring-boot-autoconfigure</name>--> <!-- <description>ceshi-spring-boot-autoconfigure</description>--> // 删除 <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-test</artifactId>--> <!-- <scope>test</scope>--> <!-- </dependency>--> <!-- Name中需要Lombox,按需引入即可 --> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> // 删除 build 项目 <!-- <build>--> <!-- </build>-->
ceshi-spring-boot-starter
pom.xml
<!-- 其它代码省略 --> <!-- 按需删掉多余的代码 --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- 引入autoconfigure --> <dependency> <groupId>com.maven1</groupId> <artifactId>ceshi-spring-boot-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies>
springboot1
com/maven1/demos/ceshi.java
import com.maven1.Name; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ceshi { @Autowired private Name Name; @PostMapping("/ceshi") public String ceshi() { return Name.name(); // autoconfigure01ceshi } }pom.xml
<!-- 引入starter --> <dependency> <groupId>com.maven1</groupId> <artifactId>ceshi-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
SpringBoot框架结构


SpringMVC + SpringFramework + Mybatis = SSM
