拦截器token
创建 token拦截器 文件
在 /src/main/java/com/example/xys1/interceptor/Xys1TokenInterceptor.java 文件中写入以下代码
package com.example.xys1.interceptor;
import cn.hutool.core.util.StrUtil;
import com.example.xys1.exception.TokenException;
import com.example.xys1.service.Xys1TokenService;
import com.example.xys1.utils.UserIdHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Xys1TokenInterceptor implements HandlerInterceptor {
@Resource
private Xys1TokenService xys1TokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("xys1-token");
if (StrUtil.isBlank(token)) {
throw new TokenException("请先登录");
}
// token -> userId
Long userId = xys1TokenService.tokenToUserId(token);
UserIdHolder.setUserId(userId);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
UserIdHolder.clear();
}
}
项目配置中 添加token拦截器
在 /src/main/java/com/example/xys1/config/Xys1BusinessWebConfig.java 文件中写入以下代码
package com.example.xys1.config;
import com.example.xys1.interceptor.TraceIdInterceptor;
import com.example.xys1.interceptor.Xys1TokenInterceptor;
import org.springframework.context.annotation.Bean;
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 Xys1BusinessWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// traceId拦截器
registry.addInterceptor(traceIdInterceptor()).addPathPatterns("/**");
// token拦截器
registry.addInterceptor(xys1TokenInterceptor())
.excludePathPatterns("/xys/**") // 不拦截
.excludePathPatterns("/login/**") // 不拦截
.addPathPatterns("/**");// 拦截
}
@Bean
public TraceIdInterceptor traceIdInterceptor() {
return new TraceIdInterceptor();
}
@Bean
public Xys1TokenInterceptor xys1TokenInterceptor() {
return new Xys1TokenInterceptor();
}
}
创建 Xys1TokenService 文件
在 /src/main/java/com/example/xys1/service/Xys1TokenService.java 文件中写入以下代码
package com.example.xys1.service;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdUtil;
import com.example.xys1.exception.TokenException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Service
public class Xys1TokenService {
@Resource
private RedisTemplate<String,String> redisTemplate;
public String createToken(Long userId) {
String token = IdUtil.fastSimpleUUID();
redisTemplate.opsForValue().set(
"token:toUserId:"+token,
userId+"",
60 * 60 * 24 * 90, TimeUnit.SECONDS
);
return token;
}
public Long tokenToUserId(String token) {
String s = redisTemplate.opsForValue().get("token:toUserId:" + token);
Long userId = Convert.toLong(s);
if (userId == null) {
throw new TokenException("token已过期");
}
return userId;
}
}
创建 UserIdHolder 文件
在 /src/main/java/com/example/xys1/utils/UserIdHolder.java 文件中写入以下代码
package com.example.xys1.utils;
public class UserIdHolder {
private static final ThreadLocal<Long> userId = new ThreadLocal<>();
public static void setUserId(Long id) {
userId.set(id);
}
public static Long getUserId() {
return userId.get();
}
public static void clear() {
userId.remove();
}
}
创建 TokenException 文件
在 /src/main/java/com/example/xys1/exception/TokenException.java 文件中写入以下代码
package com.example.xys1.exception;
public final class TokenException extends RuntimeException {
public TokenException(String message) {
super(message);
}
}
创建 GlobalExceptionHandler 文件
在 /src/main/java/com/example/xys1/handler/GlobalExceptionHandler.java 文件中写入以下代码
package com.example.xys1.handler;
import com.example.xys1.exception.TokenException;
import com.example.xys1.exception.Xys1Exception;
import com.example.xys1.utils.res.ResUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Xys1Exception.class)
public ResUtil<?> handleXys1Exception(Xys1Exception e) {
return ResUtil.fail(e.getMessage());
}
@ExceptionHandler(TokenException.class)
public ResUtil<?> handleTokenException(TokenException e) {
return ResUtil.tokenFail(e.getMessage());
}
/**
* 兜底
*/
@ExceptionHandler(Exception.class)
public ResUtil<?> handleException(Exception e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("发生系统异常。请求地址:{}", requestURI, e);
return ResUtil.fail("系统异常");
}
}
创建 LoginController 文件
在 /src/main/java/com/example/xys1/controller/LoginController.java 文件中写入以下代码
package com.example.xys1.controller;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.xys1.dto.login.LoginByAccountDto;
import com.example.xys1.entity.UserEntity;
import com.example.xys1.service.UserService;
import com.example.xys1.service.Xys1TokenService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.xys1.utils.res.ResUtil;
import javax.annotation.Resource;
// 标识为控制器,且所有方法返回值直接转为 JSON(无需视图解析)
@RestController
@RequestMapping("/login")
public class LoginController {
@Resource
private UserService userService;
@Resource
private Xys1TokenService xys1TokenService;
@PostMapping("/loginByAccount")
public ResUtil<String> loginByAccount(@RequestBody LoginByAccountDto dto) {
// 参数限制
dto.validate();
// 查询账号是否存在
LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserEntity::getAccount, dto.getAccount());
UserEntity find = userService.getOne(queryWrapper);
if (ObjectUtil.isNull(find)) {
return ResUtil.fail("账户不存在");
}
// 账户状态是否正常
// 比对密码是否正确
if (ObjectUtil.notEqual(dto.getPassword(), find.getPassword())) {
return ResUtil.fail("账户/密码不正确");
}
// 创建token
String token = xys1TokenService.createToken(find.getId());
// return
return ResUtil.ok(token);
}
}
创建 LoginUserController 文件
在 /src/main/java/com/example/xys1/controller/LoginUserController.java 文件中写入以下代码
package com.example.xys1.controller;
import com.example.xys1.entity.UserEntity;
import com.example.xys1.service.UserService;
import com.example.xys1.utils.UserIdHolder;
import com.example.xys1.utils.res.ResUtil;
import com.example.xys1.vo.loginUser.LoginUserGetInfoVo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
// 标识为控制器,且所有方法返回值直接转为 JSON(无需视图解析)
@RestController
@RequestMapping("/loginUser")
public class LoginUserController {
@Resource
private UserService userService;
@PostMapping("/loginUserGetInfo")
public ResUtil<LoginUserGetInfoVo> loginUserGetInfo() {
Long userId = UserIdHolder.getUserId();
UserEntity loginUser = userService.getById(userId);
LoginUserGetInfoVo vo = new LoginUserGetInfoVo();
vo.setId(loginUser.getId());
vo.setAccount(loginUser.getAccount());
vo.setPhone(loginUser.getPhone());
return ResUtil.ok(vo);
}
}