自定义注解实现后台获取当前登陆的用户信息
思路:
1.自定义注解
2.将用户信息存储在session中 ,当然如果是shiro的话直接通过shiro用户登陆即可。
3.实现HandlerMethodArgumentResolver参数解析类
4.配置拦截器注册自定义的参数解析器
原理:
用户登陆 -> 获取session存储用户信息或者shiro登陆
->解析每个请求,判断是否有自定义注解,有 、解析自定义注解的参数,将session或shiro中的用户获取返回给自定义注解中的参数
注意:解析返回的数据类型一定要是自定义注解参数本身或者他的子类
同时拦截器应该实现 WebMvcConfigurer 因为WebMvcConfigurerAdapter已经过期 继承WebMvcConfigurationSupport也可以(不推荐)
因为:【会使静态资源失效,静态资源路径找不到。需要重写addResourceHandlers()方法来手动映射路径:】
在jdk1.8后接口增加了default方法,接口中的方法不必被实现类全部实现,所以直接实现WebMvcConfigurer即可,不需要通过抽象类WebMvcConfigurerAdapter来过渡。
代码实现:
自定义注解:
import java.lang.annotation.*; /** * * 功能描述: 登录用户注解 * * @auther: zhao * @date: 2019/8/1 18:04 * 1.@Target 指定注解的使用范围,这里我们指定ElementType为PARAMETER,也就是参数即可。 * 2.@Retention作用是定义该注解能保留多久,一共有三种策略,这里我们指定为RUNTIME,也就是运行时。 */ @Retention(RetentionPolicy.RUNTIME) @Target(value = ElementType.PARAMETER) public @interface LoginUser { /** * 当前用户在session对象中的key,"user" // session.setAttribute("user",one); */ String value() default "user" ; }
自定义参数解析器:
loginUser.value()值就是定义的”user“
import com.could.demo.entity.User; 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; /** * * 功能描述: 登录用户的MethodArgumentResolver * * @auther: zhao * @date: 2019/8/1 18:06 */ public class LoginUserMethodArgumentResolver implements HandlerMethodArgumentResolver { /** *若不想自定义注解,可以直接在实现HandlerMethodArgumentResolver的supportsParameter直接返回true 这样每一个请求过来的都会分解该参数 * 功能描述: 用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。 * @param: [methodParameter] * @return: boolean * @auther: zhao * @date: 2019/8/1 18:06 * supportsParameter方法, * 判断什么时候要执行下面的resolveArgument方法。这里我们判断当一个方法的参数含有@LoginUser * 并且方法的参数是我们的用户类时返回true。 */ @Override public boolean supportsParameter(MethodParameter methodParameter) { return methodParameter.hasParameterAnnotation(LoginUser.class) && User.class.isAssignableFrom(methodParameter.getParameterType()); // return methodParameter.hasParameterAnnotation(LoginUser.class); } /** * * 功能描述: 真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。(获得登录用户信息) * @param: [methodParameter, modelAndViewContainer, nativeWebRequest, webDataBinderFactory] * @return: java.lang.Object * @auther: zhao * @date: 2019/8/1 18:05 * resolveArgument方法,在这里我们直接把放在session中的用户信息放回去即可。 */ @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { /** * 如果是shiro的话直接通过shiro获取用户信息即可 */ LoginUser loginUser = methodParameter.getParameterAnnotation(LoginUser.class); if( loginUser != null){ return nativeWebRequest.getAttribute(loginUser.value(), NativeWebRequest.SCOPE_SESSION); } return null; } }
注册拦截器:
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.WebMvcConfigurer; import java.util.List; /** * * 功能描述: 获得登录用户的配置类 *WebMvcConfigurerAdapter已过时 * 在jdk1.8后增加了default,接口中的方法不必被实现类全部实现,所以直接实现WebMvcConfigurer即可,不需要通过抽象类WebMvcConfigurerAdapter来过渡。 * @auther: zhao * @date: 2019/8/1 18:04 */ @Configuration public class LoginUserConfigurer implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { // 注册loginUserMethodArgumentResolver的参数分解器 argumentResolvers.add(loginUserMethodArgumentResolver()); } @Bean(name = "loginUserMethodArgumentResolver") public LoginUserMethodArgumentResolver loginUserMethodArgumentResolver(){ return new LoginUserMethodArgumentResolver(); } }
有@Configuration的类可以很多,他们加载时会合并,但要注解@Bean(name = "loginUserMethodArgumentResolver")中的name不要重复。
Controller类:
import com.could.demo.config.security.LoginUser; import com.could.demo.entity.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; /** * AUTHOR :zhao * 日期:2020/3/21 20:47 */ @RestController public class UserAnnotationController { @GetMapping("/loginUser") public String login(HttpSession session){ User user = new User(); user.setName("头皮发麻"); user.setPassword("10086"); session.setAttribute("user",user); return "ok"; } /** * 测试注解是否能拿到值 * @param managers * @return */ @GetMapping(value = "/testUser") public Object testUser(@LoginUser User managers) { return managers; } @GetMapping(value = "/test") public Object test(User managers) { return managers; } }