之前获取登录用户的方法是BaseController中封装统一的方法或者封装一个UserContextHolder的工具类,然后代码中用工具类获取。最近项目中看到Controller中获取当前用户直接参数上标记一下。
1. 用户类和获取登录用户的工具类
package com.xm.ggn.utils; import lombok.Data; /** * @Author: qlq * @Description * @Date: 18:43 2021/1/2 */ @Data public class User { private String username; private String fullname; }
获取登录用户的工具类:
package com.xm.ggn.utils; /** * @Author: qlq * @Description * @Date: 12:52 2021/1/2 */ public class UserCeontextHolder { /** * 模拟获取用户工具的方式,可以从session获取;前后端分离可以根据token获取 * * @return */ public static User getCurrentUser() { User user = new User(); user.setUsername("zs"); user.setFullname("张三"); // 权限以及其他相关等信息 return user; } }
2. 自定义注解以及Controller做标记
package com.xm.ggn.utils; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Author: qlq * @Description * @Date: 19:29 2021/1/2 */ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface LoginUser { }
测试Controller:
package com.xm.ggn.controller.common; import com.xm.ggn.utils.LoginUser; import com.xm.ggn.utils.User; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Author: qlq * @Description * @Date: 0:23 2020/12/12 */ @RestController @Slf4j public class TestController { @RequestMapping("/test") public User test(User user) { log.debug("user: {}", user); return user; } @RequestMapping("/test2") public User test2(@LoginUser User user) { log.debug("user: {}", user); return user; } }
3.自定义参数解析器
package com.xm.ggn.utils; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; 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; /** * @Author: qlq * @Description * @Date: 18:48 2021/1/2 */ @Component public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) {return parameter.getParameterType().isAssignableFrom(User.class) && parameter.hasParameterAnnotation(LoginUser.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { return UserCeontextHolder.getCurrentUser(); } }
4.添加到Spring中
package com.xm.ggn.config; import com.xm.ggn.utils.UserMethodArgumentResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import java.util.List; /** * 设置匹配指定后缀*.action *.do的路径(导致静态资源文件失败,没有解决) * * @author Administrator */ @Configuration public class UrlMatchConfig extends WebMvcConfigurationSupport { @Override public void configurePathMatch(PathMatchConfigurer configurer) { // setUseSuffixPatternMatch 后缀模式匹配 configurer.setUseSuffixPatternMatch(true); // setUseTrailingSlashMatch 自动后缀路径模式匹配 configurer.setUseTrailingSlashMatch(true); } /** * 设置匹配*.action后缀请求 * * @param dispatcherServlet * @return */ @Bean public ServletRegistrationBean servletRegistrationBean(DispatcherServlet dispatcherServlet) { ServletRegistrationBean servletServletRegistrationBean = new ServletRegistrationBean(dispatcherServlet); // 参数接受可变类型的多个参数支持多种后缀的匹配 servletServletRegistrationBean.addUrlMappings("*.action", "*.do"); return servletServletRegistrationBean; } @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); } @Autowired private UserMethodArgumentResolver userMethodArgumentResolver; /** * 参数解析器 * * @param argumentResolvers */ @Override protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(userMethodArgumentResolver); super.addArgumentResolvers(argumentResolvers); } }
5.测试
liqiang@root MINGW64 /e/xiangmu/bs-media/media-server (master) $ curl http://localhost:8088/test.do % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-100 33 0 33 0 0 39 0 --:--:-100 33 0 33 0 0 38 0 --:--:-- --:--:-- --:--:-- 39{"username":null,"fullname":null} liqiang@root MINGW64 /e/xiangmu/bs-media/media-server (master) $ curl http://localhost:8088/test2.do % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-100 37 0 37 0 0 787 0 --:--:-- --:--:-- --:--:-- 2312{"username":"zs","fullname":"张三"}
如果Controller所有的User方法都是获取当前登录的用户,可以去掉自定义注解,然后修改UserMethodArgumentResolver为:
package com.xm.ggn.utils; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; 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; /** * @Author: qlq * @Description * @Date: 18:48 2021/1/2 */ @Component public class UserMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.getParameterType().isAssignableFrom(User.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { return UserCeontextHolder.getCurrentUser(); } }
补充:class1.isAssignableFrom(class2) 和 instanceof 的区别
instanceof 关键字判断某个对象是否是某个类的实例,子类的对象也是父类的对象
class1.isAssignableFrom(class2) 方法用于判定此 class1对象所表示的类或接口与指定的 class2参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false。
public static void main(String[] args) { List<String> result = new ArrayList<>(); result.add("1"); System.out.println(result instanceof ArrayList); System.out.println(result instanceof List); // 测试 System.out.println("===="); System.out.println(List.class.isAssignableFrom(ArrayList.class)); System.out.println(List.class.isAssignableFrom(List.class)); System.out.println(ArrayList.class.isAssignableFrom(ArrayList.class)); System.out.println(ArrayList.class.isAssignableFrom(List.class)); }
结果:
true
true
====
true
true
true
false