阅读 74

SpringMVC 中统一的 Context 数据获取

1. 定义 User 类

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public 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 注解 解析器
 */
@Slf4j
public 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;

@Configuration
public 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
@Slf4j
public 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)步骤定义的数据对象和注解。

参考

作者:蓝笔头

原文链接:https://www.jianshu.com/p/9e8aa6980e93

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐