文章目录

  • 前言
  • 一、拦截器+方法参数解析器 是什么?
  • 二、具体实现步骤
    • 1.自定义权限拦截器LoginInterceptor拦截所有request请求,并将token解析为currentUser,最终放到request中。
    • 2.自定义参数注解@User,添加至controller的方法参数currentUser之上。
    • 3.自定义方法参数解析器CurrentUserHandlerMethodArgReslover,取出request中的currentUser,并赋值给添加了@User注解的参数currentUser。
    • 4.配置MVC
  • 三、总结

前言

需求:很多Controller方法,刚进来要先获取当前登录用户的信息,以便做后续的用户相关操作。
准备工作:前端每次请求都传token,后端封装一方法redisUtil.get(token),根据token解析得到currentUser。
这是一个常见的业务需求,为实现这个需求有以下三种解决方案:
  一、最原始直接的方式:即在每个Controller开始,先调用redisUtil.get(token),获取用户的信息,不够优雅。

  二、AOP:AOP可以解决很多切面类问题,思路同Spring AOP来自定义注解实现审计或日志记录(完整代码),将currentUser放到request里;比起拦截器稍重。

  三、拦截器+方法参数解析器:使用mvc拦截器HandlerInterceptor+方法参数解析器HandlerMethodArgumentResolver最合适。
本篇博客讲解第三种的具体实现步骤~

一、拦截器+方法参数解析器 是什么?

  SpringMVC提供了mvc拦截器HandlerInterceptor,包含以下3个方法:

  ①:preHandle
  ②:postHandle
  ③:afterCompletion
  HandlerInterceptor经常被用来解决拦截事件,如用户鉴权等。

  另外,Spring也向我们提供了多种解析器Resolver,如用来统一处理异常HandlerExceptionResolver,以及今天的主角HandlerMethodArgumentResolver。HandlerMethodArgumentResolver是用来处理方法参数的解析器,包含以下2个方法:

  ①:supportsParameter(满足某种要求,返回true,方可进入resolveArgument做参数处理)
  ②:resolveArgument

二、具体实现步骤

1.自定义权限拦截器LoginInterceptor拦截所有request请求,并将token解析为currentUser,最终放到request中。

  自定义权限拦截器LoginInterceptor,需实现HandlerInterceptor。在preHandle中调用redisUtil.get(token),获取到当前用户,最后塞进request中,如下:

public class LoginInterceptor implements HandlerInterceptor {//@Autowired//private ShoConfigService shoConfigService;@Autowiredprivate RedisUtil redisUtil;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {System.out.println(request.getRequestURL());String tokenHeader = request.getHeader("token");if (StringUtils.isBlank(tokenHeader)) {throw new AppException("openid为空", ResultCode.PERMISSION_NO_ACCESS.getCode());}CurrentUser currentUser = (CurrentUser) redisUtil.get(tokenHeader);if (currentUser == null) {throw new AppException("openid为空", ResultCode.PERMISSION_NO_ACCESS.getCode());}request.getSession().setAttribute("currentUser", currentUser);
//       调用接口的时候查询系统维护的状态/*JsonResult result = shoConfigService.selStatue();if (result.getData().equals(0)) {throw new AppException("系统维护中", ResultCode.SYSTEM_MAINTENANCE.getCode());}*/return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

2.自定义参数注解@User,添加至controller的方法参数currentUser之上。

  自定义方法参数上使用的注解@User,代表被它注解过的参数的值都需要由方法参数解析器CurrentUserHandlerMethodArgReslover来“注入”,如下:

package com.boduo.config.aop;import java.lang.annotation.*;/*** @Description:@User自定义注解* @Author nanyi* @Date 2021/4/16 20:03**/
@Target({ElementType.PARAMETER})//Annotation所修饰的对象范围:方法参数
@Retention(RetentionPolicy.RUNTIME)//Annotation被保留时间:运行时保留(有效)
@Documented//标记注解:java工具文档化
public @interface User {}

  给各Controller类中方法的参数添加此注解,案例如下:

/*** @Description:对应品牌的通知* @Author nanyi* @Date 2021/4/16 10:28**/
@RestController
@RequestMapping("/api/shop/notify")
@Api(tags = "首页")
@ApiSort(1)
public class NotifyController {@AutowiredNotifyService notifyService;/*** @Description:未查看通知列表*/@GetMapping("/list")@ApiOperation("通知列表")@ApiOperationSupport(order = 11)public JsonResult<NotifyDTO> noticesAll(@ApiIgnore @User CurrentUser currentUser) {if (currentUser.getIsVisitory()) {//      如果是游客,根据Openid和品牌id进行查询return notifyService.selNotifyByBrandId(currentUser.getUsername(), currentUser.getBrand().getBrandId());}
//        如果是VIP,根据AI系统里面的用户编号和品牌id进行查询return notifyService.selNotifyByBrandId(currentUser.getUsername(), currentUser.getBrand().getBrandId());}}

3.自定义方法参数解析器CurrentUserHandlerMethodArgReslover,取出request中的currentUser,并赋值给添加了@User注解的参数currentUser。

  自定义方法参数解析器CurrentUserHandlerMethodArgReslover,需实现HandlerMethodArgumentResolver。

package com.boduo.config.aop;import com.boduo.entity.CurrentUser;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;import javax.servlet.http.HttpServletRequest;/*** @Description:@User 注解解析器* @Author nanyi* @Date 2021/4/16 10:28**/
public class CurrentUserHandlerMethodArgReslover implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter methodParameter) {//如果该参数注解有@User且参数类型是Userreturn methodParameter.getParameterAnnotation(User.class) != null;}@Overridepublic Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {//取得HttpServletRequestHttpServletRequest request= (HttpServletRequest) nativeWebRequest.getNativeRequest();//取出session中的Userreturn (CurrentUser)request.getSession().getAttribute("currentUser");}
}

  拦截器定义好以后,在SpringMVC项目中,需要去SpringMVC的配置文件springmvc.xml添加该拦截器;但是在SpringBoot中,省去了很多配置文件,取而代之的是被注解@Configuration标识的配置类,SpringMVC配置文件对应的配置类需继承WebMvcConfigurer。同理,解析器定义好以后,也需被添加到SpringMVC的配置文件或配置类中。最后,额外的一步,配置mvc。

4.配置MVC

package com.boduo.config.aop;import com.boduo.config.properties.MyProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.List;/*** @Description:@User 注解解析器* @Author nanyi* @Date 2021/4/16 10:40**/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@AutowiredMyProperties myProperties;@Beanpublic LoginInterceptor LoginInterceptor() {return new LoginInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {/***此处拦截路径(/**)* 注意两个**。一个*号只拦截一级路径下,两个*号拦截所有* 将LoginInterceptor()给添加进来*/registry.addInterceptor(LoginInterceptor()).addPathPatterns("/**").excludePathPatterns(myProperties.getIgnoreUrls());}@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {//注册@User注解的实现类argumentResolvers.add(new CurrentUserHandlerMethodArgReslover());}public void addResourceHandlers(ResourceHandlerRegistry registry) {//将templates目录下的CSS、JS文件映射为静态资源,防止Spring把这些资源识别成thymeleaf模版registry.addResourceHandler("/static/**.js").addResourceLocations("classpath:/static/");
}

三、总结

成为一个小胖子,没事摸摸小肚子~

拦截器HandlerInterceptor+方法参数解析器HandlerMethodArgumentResolver用于统一获取当前登录用户信息相关推荐

  1. (十六)ATP应用测试平台——java应用中的过滤器Filter、拦截器Interceptor、参数解析器Resolver、Aop切面,你会了吗?

    前言 过滤器Filter.拦截器Interceptor.参数解析器Resolver.Aop切面是我们应用开发中经常使用到的技术,到底该如何使用这些web附属功能, 本小节我们就分别介绍一下其各自的用法 ...

  2. Linux下用于查看系统当前登录用户信息的4种方法

    作为系统管理员,你可能经常会(在某个时候)需要查看系统中有哪些用户正在活动.有些时候,你甚至需要知道他(她)们正在做什么.本文为我们总结了4种查看系统用户信息(通过编号(ID))的方法. 1. 使用w ...

  3. Linux查看系统中用户信息,Linux下用于查看系统当前登录用户信息的4种方法

    作为系统管理员,你可能经常会(在某个时候)需要查看系统中有哪些用户正在活动.有些时候,你甚至需要知道他(她)们正在做什么.本文为我们总结了4种查看系统用户信息(通过编号(ID))的方法. 1. 使用w ...

  4. CentOS下用于查看系统当前登录用户信息的4种方法

    1. 使用w命令查看登录用户正在使用的进程信息 w命令用于显示已经登录系统的用户的名称,以及他们正在做的事.该命令所使用的信息来源于/var/run/utmp文件.w命令输出的信息包括: 用户名称 用 ...

  5. wordpress获取当前登录用户信息的方法

    1). get_currentuserinfo(); 此函数将当前登录用户信息赋给全局变量$current_user以及一些单独的用户信息全局变量例如$display_name, $user_emai ...

  6. Spring MVC自定义类型转换器Converter、参数解析器HandlerMethodArgumentResolver

    文章目录 一.前言 二.类型转换器Converter 1.自定义类型转换器 三.参数解析器 1.自定义分页参数解析器 2.自定义注解参数解析器 一.前言 Spring MVC源码分析相关文章已出: S ...

  7. SpringMVC 参数解析器

    一.问题 springMVC对于下面这种接口,参数是怎么解析的: @GetMapping("/hello/{id}") public void hello3(@PathVariab ...

  8. Spring参数解析器

    文章目录 请求映射处理适配器:RequestMappingHandlerAdapter 参数解析器:HandlerMethodArgumentResolver 参数处理相关注解 1.@PathVari ...

  9. springmvc自定义参数解析器/类型转换器

    概述 有些时候我们需要对GET请求的入参做自定义的处理,比较常见的就是字符串反序列化时间类型了,常用的像@DateTimeFormat注解,但是这需要在每个入参的属性上都加上这个注解,比较费手,那么我 ...

最新文章

  1. xgboost lightgbm catboost 多分类 多标签
  2. Linux下的kill函数的用法
  3. 各个级别镜像之间的跳转模型
  4. input file 上传文件格式限制
  5. line和spline_探索适用于Apache Spark的Spline Data Tracker和可视化工具(第1部分)
  6. Cannot merge new index 66395 into a non-jumbo instruction!,uses or overrides a deprecated API.
  7. 为什么相关性不等于因果性?终于有人讲明白了
  8. 12C 新特性 | 标量子查询自动转换
  9. 彪悍语录系列(摘于网络)
  10. javascript 未来新方法的介绍
  11. LL1分析构造法_行测技巧:比较构造法两步轻松解决方程题
  12. Android开发遇到的问题
  13. OSEK Os的任务调度
  14. Android Studio 怎么连接MUMU模拟器并永久使用
  15. 【小程序源码】经典语录大全多种分类语录
  16. EXCEL如何真正彻底去掉小数点后的数字
  17. 小游戏制作QQ宠物系列1 ---- 吹泡泡
  18. python计算给定的日期的星期_Python计算给定日期的周内的某一天
  19. Python爬取《创造营2020》小姐姐数据用腾讯云人脸识别做颜值评分
  20. 了解爬虫的工作流程及相关概念

热门文章

  1. win7安装python计算机丢失api-ms-win_无法启动此程序因为计算机中丢失api-ms-win
  2. 因式分解英语计算机,网易正式发布有道超级计算器 免费无广告离线高级运算...
  3. Visio无法复制文本框,内部错误1021
  4. 嘉弘恒信:拼多多新手期红包要怎么使用
  5. c语言中数组的变量j是什么,C语言中x[i][j]的意思是?
  6. IDEA中报错“Cannot resolve symple”解决办法
  7. java jit aot_对比JIT和AOT,各自有什么优点与缺点?
  8. swing的JTextField的介绍及其使用方法
  9. SAP创建客户主数据事务码和透明表
  10. 安装一个好用的Ubuntu桌面