环境:jdk17,springboot3.1.12
功能
配置文件
jwt拦截,进行登录
切面类制作
异常捕获
依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--mysql驱动 2023 -4 -18 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0 .33 </version> </dependency> <!--mybatisPlus 2023 -8 -8 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5 .5 </version> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.3 .0 </version> </dependency> <!-- JWT --> <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> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11 .5 </version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7 .5 </version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
配置文件 application.properties
1 2 3 4 5 6 7 8 9 10 11 12 13 spring.application.name=demo1 server.port=9090 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql: spring.datasource.username=root spring.datasource.password=196691 spring.mvc.pathmatch.matching-strategy=ant_path_matcher mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl mybatis-plus.mapper-locations=classpath:mapper
结果封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.zou.common;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data @NoArgsConstructor @AllArgsConstructor public class Result <T> { private int code; private String msg; private T data; public static <T> Result<T> success (String msg) { return new Result <>(200 , msg, null ); } public static <T> Result<T> success (String msg, T data) { return new Result <>(200 , msg, data); } public static <T> Result<T> error (String msg) { return new Result <>(500 , msg, null ); } }
jwt拦截
jwt工具类:负责生成,解析token,从token获取用户信息
jwt拦截器:对所有请求进行拦截,校验失败抛出异常
webConfig:接口拼接/api前缀,拦截器 注册,跨域处理
JwtUtil 创建jwt工具类 JwtUtil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package com.zou.common;import com.zou.pojo.User;import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import io.jsonwebtoken.security.Keys;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Configuration;import javax.crypto.SecretKey;import java.util.Date;@Configuration @Slf4j public class JwtUtil { private static final String secret = "zouwen" ; private static final SecretKey secret1 = Keys.secretKeyFor(SignatureAlgorithm.HS256); private static final long expirationTime = 1000 *60 *60 ; public String generateToken (User user) { log.info("jwt开始生成token,获取到的用户:" +user); return Jwts.builder() .claim("username" ,user.getUsername()) .setExpiration(new Date (System.currentTimeMillis()+expirationTime)) .signWith(SignatureAlgorithm.HS256,secret1) .compact(); } public boolean validateToken (String token) { try { Jwts.parser().setSigningKey(secret1).parseClaimsJws(token); log.info("jwt验证秘钥成功" ); return true ; } catch (Exception e) { log.error("jwt验证秘钥失败" ); return false ; } } public User getUserFromToken (String BearerToken) { String token = BearerToken.substring(7 ); log.warn("jwt开始解析token" ); Claims claims = Jwts.parserBuilder() .setSigningKey(secret1) .build() .parseClaimsJws(token) .getBody(); String username = (String) claims.get("username" ); User user = new User (); user.setUsername(username); return user; } }
JwtInterceptor 创建jwt拦截器 JwtInterceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package com.zou.Interceptor;import com.zou.common.JwtUtil;import com.zou.exception.CustomException;import jakarta.annotation.Resource;import jakarta.servlet.http.HttpServletRequest;import jakarta.servlet.http.HttpServletResponse;import lombok.extern.slf4j.Slf4j;import org.springframework.http.HttpMethod;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import java.util.Enumeration;@Component @Slf4j public class JwtInterceptor implements HandlerInterceptor { @Resource private JwtUtil jwtUtil; @Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.error("经过jwt拦截器预处理" ); if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) { return true ; } String requestPath = request.getRequestURI(); log.info("jwt拦截器拦截请求路径为:" +requestPath); String header = request.getHeader("User-Agent" ); log.info("jwt拦截器拦截请求头为:" +header); Enumeration<String> headerNames = request.getHeaderNames(); log.info("所有请求头的名称" +headerNames); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); System.out.println(headerName); } String authorizationHeader = request.getHeader("Authorization" ); log.warn("jwt拦截器拿到请求头" +authorizationHeader); if (authorizationHeader != null && authorizationHeader.startsWith("Bearer " )) { String token = authorizationHeader.substring(7 ); log.info("token为为:" +token); boolean b = jwtUtil.validateToken(token); if (!b){ log.error("检测到token有值,但是校验失败" ); throw new CustomException ("token验证失败---->jwt" ); } } else { log.warn("无效的token" ); return false ; } return true ; } }
WebConfig 创建WebConfig实现WebMvcConfigurer接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.zou.config;import com.zou.Interceptor.JwtInterceptor;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.core.Ordered;import org.springframework.web.method.HandlerTypePredicate;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Slf4j @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private JwtInterceptor jwtInterceptor; @Override public void configurePathMatch (PathMatchConfigurer configurer) { configurer.addPathPrefix("/api" , HandlerTypePredicate.forBasePackage("com.zou.controller" )); } @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**" ) .excludePathPatterns("/api/user/register" ) .excludePathPatterns("/api/user/login" ) .excludePathPatterns("/api/file/upload" ) .excludePathPatterns("/api/file/**" ) .order(Ordered.HIGHEST_PRECEDENCE);; } @Override public void addCorsMappings (CorsRegistry registry) { log.warn("经过cors" ); registry.addMapping("/**" ) .allowCredentials(true ) .allowedOriginPatterns("*" ) .allowedMethods(new String []{"GET" , "POST" , "PUT" , "DELETE" }) .allowedHeaders("*" ) .exposedHeaders("*" ); } }
异常 全局异常 创建GlobalException用来处理全局异常,通过ControllerAdvice可以获取所有异常,然后把自定义异常注入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.zou.exception;import com.zou.common.Result;import jakarta.servlet.http.HttpServletRequest;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice("com.example.controller") @Slf4j public class GlobalException { @ExceptionHandler(Exception.class) @ResponseBody public Result error (Exception e, HttpServletRequest request) { log.error("异常信息" ,e); return Result.error("系统异常" ); } @ExceptionHandler(CustomException.class) @ResponseBody public Result error (CustomException e, HttpServletRequest request) { return Result.error(e.getMsg()); } }
自定义异常 1 2 3 4 5 6 7 8 9 10 11 12 13 package com.zou.exception;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data @NoArgsConstructor @AllArgsConstructor public class CustomException extends RuntimeException { private String msg; }
切面 自定义注解 拦截所有方法,作用域
1 2 3 4 5 6 7 8 9 10 package com.zou.common;import java.lang.annotation.*;@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AutoLog { String value () default "" ; }
切面类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.zou.config;import com.zou.common.AutoLog;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Aspect @Slf4j @Component public class LogAspect { @Around("@annotation(autoLog)") public Object doAround (ProceedingJoinPoint joinPoint, AutoLog autoLog) throws Throwable{ log.info("我是门卫" ); return joinPoint.proceed(); } }
使用 1 2 3 4 5 6 @AutoLog @GetMapping("/getinfo") public Result getInfo (@RequestHeader("Authorization") String token) { User info = userService.getInfo(token); return Result.success("获取用户信息成功" ,info); }
用户信息 controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.zou.controller;import com.zou.common.AutoLog;import com.zou.common.Result;import com.zou.pojo.User;import com.zou.service.UserService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;@RestController @RequestMapping("/user") @Slf4j public class UserController { @Autowired private UserService userService; @GetMapping("/getall") public Result getAll () { return userService.getAll(); } @PostMapping("/register") public Result register (User user) { return userService.register(user); } @PostMapping("/login") public Result login (User user) { return userService.login(user); } @AutoLog @GetMapping("/getinfo") public Result getInfo (@RequestHeader("Authorization") String token) { return userService.getInfo(token); } }
service 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 package com.zou.service.Impl;import com.zou.common.JwtUtil;import com.zou.common.Result;import com.zou.mapper.UserMapper;import com.zou.pojo.User;import com.zou.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Service public class UserServiceImpl implements UserService { @Autowired private JwtUtil jwtUtil; @Autowired private UserMapper userMapper; @Override public Result getAll () { List<User> all = userMapper.getAll(); for (User user : userMapper.getAll()) { System.out.println(user); } return Result.success("查询所有用户成功" ,all); } @Override public Result register (User user) { User byUsername = userMapper.getByUsername(user); if (byUsername != null ){ return Result.error("注册失败,用户名重复" ); } Boolean register = userMapper.register(user); if (register){ return Result.success("注册用户成功" ); }else { return Result.error("注册用户失败" ); } } @Override public Result login (User user) { User byUsername = userMapper.getByUsername(user); if (byUsername != null ){ if (byUsername.getPassword().equals(user.getPassword())){ String token = jwtUtil.generateToken(user); return Result.success("用户登录成功" ,token); }else { return Result.error("密码错误" ); } }else { return Result.error("用户不存在" ); } } @Override public Result getInfo (String token) { User userFromToken = jwtUtil.getUserFromToken(token); User byUsername = userMapper.getByUsername(userFromToken); return Result.success("获取用户信息成功" ,byUsername); } }
mapper.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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="com.zou.mapper.UserMapper" > <insert id="register" parameterType="com.zou.pojo.User" > insert into user (id,username,password) values(#{id},#{username},#{password}) </insert> <select id="getAll" resultType="com.zou.pojo.User" > select * from user </select> <select id="getByUsername" resultType="com.zou.pojo.User" parameterType="com.zou.pojo.User" > select * from user where username = #{username} </select> </mapper>