SpringMVC 中统一的 Context 数据获取
1. 定义 User 类
import lombok.AllArgsConstructor;import lombok.Builder;import lombok.Data;import lombok.NoArgsConstructor;@Data@NoArgsConstructor@AllArgsConstructor@Builderpublic class User { private Long id; private String name;}
2. 定义 CurrentUser 注解
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; /** * 自定义 当前用户 注解 * 注解 参数 * 此注解在验证token通过后,获取当前token包含用户 */@Target({ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)public @interface CurrentUser {}
3. 实现 HandlerMethodArgumentResolver
import lombok.extern.slf4j.Slf4j;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.Cookie;import javax.servlet.http.HttpServletRequest;import java.util.Arrays;import java.util.Optional;/** * @CurrentUser 注解 解析器 */@Slf4jpublic class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { // 1. User 类的对象是否可以分配给当前的方法参数 boolean assignable = parameter.getParameterType().isAssignableFrom(User.class); // 2. 当前方法参数上是否有 CurrentUser 的注解 boolean hasAnnotation = parameter.hasParameterAnnotation(CurrentUser.class); return assignable && hasAnnotation; } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); Optional<String> id = getValue(request, "id"); Optional<String> name = getValue(request, "name"); return User.builder() .id(id.map(Long::parseLong).orElse(null)) .name(name.orElse(null)) .build(); } private Optional<String> getValue(HttpServletRequest request, String name) { return Arrays.stream(request.getCookies()) .filter(c -> c.getName().equals(name)) .findFirst() .map(Cookie::getValue); }}
4. 配置 WebMvcConfig
把 CurrentUserMethodArgumentResolver
添加到 SpringMVC 中。
import org.springframework.context.annotation.Configuration;import org.springframework.web.method.support.HandlerMethodArgumentResolver;import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;import java.util.List;@Configurationpublic class WebMvcConfig extends WebMvcConfigurationSupport { @Override protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new CurrentUserMethodArgumentResolver()); }}
5. 通过 Controller 进行测试
import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestController@Slf4jpublic class DemoController { @GetMapping("/test") public User test(@CurrentUser User user) { log.info("user: {}", user); return user; }}
启动服务,通过 postman 调用 /test
接口进行测试。
5.1 cookie 为空
cookie 为空
5.2 cookie 只包含 id
id=1
cookie 只包含id
5.3 cookie 包含id和 name
id=1;name=joy
cookie 包含id和 name
总结
1)定义你想要获取的 Context 数据对象
2)定义一个你想要在 Controller 方法中识别参数的注解
3)实现
HandlerMethodArgumentResolver
,并在其使用第( 1)和第( 2)步骤定义的数据对象和注解。4)通过
WebMvcConfigurationSupport
将第 (3)步实现的HandlerMethodArgumentResolver
添加到 SpringMVC 中。5)此后就可以在 Controller 中实现第( 1)和第( 2)步骤定义的数据对象和注解。
参考
NativeWebRequest获取cookie参数
HandlerMethodArgumentResolver用于统一获取当前登录用户
作者:蓝笔头
链接:https://www.jianshu.com/p/9e8aa6980e93