最后
分享一些资料给大家,我觉得这些都是很有用的东西,大家也可以跟着来学习,查漏补缺。
《Java高级面试》
《Java高级架构知识》
《算法知识》
那这里有一个问题,HandlerMethod
是什么东西?他为什么会能有getMethodAnnotation()
方法去拿到给他传入的.class
的注解呢?
那这里就要引出SpringMVC
了,如果你学了它,你就会知道HandlerMethod
,其实就对应Handler
,也就是我们写的那些Controller
那知道了这个之后,根据上面的handler instanceof HandlerMethod
来判断他是不是controller,如果是,那就可以拿到controller上面所标记的注解,
以上就可以看到了@Login
所进行的流程,最后写了以上的还是不行的,我们需要将这个拦截器加入到spring的拦截器链表
中也就是上面的图,让他起作用
查找了下代码,他在com.tduck.cloud.api.config.WebMvcConfig
中实现了WebMvcConfigurer
重写了addInterceptors(InterceptorRegistry registry)
方法,把上面写的登录校验加入拦截器链中,并指定拦截所有请求!
这里的最后,查看他随便
使用到@Login
注解的地方,所以标注了它后会在拦截器中进行对token的校验,来判断用户是否登录
com.tduck.cloud.api.annotation.LoginUser
通过这个注解去控制这个某个参数封装用户信息
给他定义的是:
描述参数
/运行时生效
/**
- 登录用户信息
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {}
在项目中查找@LoginUser
注解,发现在com.tduck.cloud.api.web.resolver.LoginUserHandlerMethodArgumentResolver
中,他实现了HandlerMethodArgumentResolver
参数解析器,他就是解析请求发来的参数并解析成对应我们controller中对应方法参数,比如@RequestBody、@RequestParam等
【 HandlerMethodArgumentResolver的小文章 •‾̑⌣‾̑•) 】
需要获取到请求来的参数,并封装。
但是这里需要自定义,因为SpringMVC只封装对应的请求体,这里就直接自定义写了一个封装器
@Component
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
private final UserService userService;
//通过构造依赖,需要的userService
public LoginUserHandlerMethodArgumentResolver(UserService userService) {
this.userService = userService;
}
//这个方法返回的T/F,会直接决定下面的resolveArgument()方法是否能够被执行
@Override
public boolean supportsParameter(MethodParameter parameter) {
//拿到这个请求参数的类型
//判断他是不是UserEntity类,并判断他是不是有被注解@LoginUser标注
return parameter.getParameterType().isAssignableFrom(UserEntity.class) && parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
//从请求域中拿到用户的id
//这个用户的id是在 【@Login的拦截器里面最后放入到请求域中的】
Object object = request.getAttribute(AuthorizationInterceptor.USER_KEY, RequestAttributes.SCOPE_REQUEST);
if (object == null) {
return null;
}
//获取用户信息,并返回,返回后spring会自动给UserEntity类封装上查询到的信息
UserEntity user = userService.getById((Long) object);
return user;
}
}
最后写完了肯定要加入到MVC
的ArgumentResolvers参数解析器s
中,
在com.tduck.cloud.api.config.WebMvcConfig
这样子,主要标注了@LoginUser
的注解就会被这个参数解析器解析,并自动去查询获取封装对应的用户数据
同样这里的最后,也查看羡慕使用到@LoginUser
注解的地方,发现他使用的方式跟我们常用的各种封装数据类型的注解
一模一样
com.tduck.cloud.api.web.controller.UserController
com.tduck.cloud.api.annotation.NoRepeatSubmit
最后一个注解,通过它来控制不允许重复提交
给他定义的是:
描述方法、描述类&接口
/运行时生效
/**
- 不允许重复提交注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {}
如果你观察仔细,你在上面就会已经发现了这个注解的拦截器跟@Login
的拦截器在同一个包下
com.tduck.cloud.api.web.interceptor.NoRepeatSubmitInterceptor
不同的是,他是直接实现的HandlerInterceptor
,而@Login的拦截器是继承
HandlerInterceptor的一个实现类HandlerInterceptorAdapter
【 HandlerInterceptor&HandlerInterceptorAdapter区别 】 ´•.̫ • `
它先判断是否是HandlerMethod
,就是判断是不是Handler处理器,如果不是,就直接结束返回true;
再强转
,并再判断他是否又被@NoRepeatSubmit
标注,如果有就继续,不然就直接结束返回true;
在这里看到,他通过自定义的方式跟@Login
是一样的 (ฅ´ω`ฅ)!!!
然后判断是否是BodyReaderHttpServletRequestWrapper
那BodyReaderHttpServletRequestWrapper
是什么东西???
关联打开后发现代码很多
!!! 且发现他继承了HttpServletRequestWrapper
那问题就转移了,就是HttpServletRequestWrapper
是什么??? 【 HttpServletRequestWrapper类的作用 】
这里简单的概括就是因为我们很多时候都要改变HttpServletRequest
,但是由于java.util.Map包装的HttpServletRequest
对象的参数是不可改变,所以通过 【装饰者设计模式 】包装来改变其状态,这样子只需要在装饰类HttpServletRequestWrapper
中,按照需要重写其对应的方法即可
com.tduck.cloud.api.web.wrapper.BodyReaderHttpServletRequestWrapper
进行了对原HttpServletRequest包装装饰
,给每一个参数内容都加上了XSS过滤
,
最后
分布式技术专题+面试解析+相关的手写和学习的笔记pdf
还有更多Java笔记分享如下:
color_FFFFFF,t_70,g_se,x_16)
最后
分布式技术专题+面试解析+相关的手写和学习的笔记pdf
还有更多Java笔记分享如下:
[外链图片转存中…(img-hgAvsUAy-1715712059148)]