实际工作中学习技术是最快、最深刻的。当然,自身的持续学习意识是必须的
技术栈版本:
spring boot 2.0.2
遇到事儿了
近来做业务需求,前端同学fe将userId和userName放到request header中了。
后端api接口要想使用userId和userName,每个接口都要从header中获取。
试想一下,如果你有十个接口,那么每个接口都要写一遍Object.setUserId(request.getHeader(“userId”))。
正如下面代码段
@RestController @Validated @RequestMapping("/template") public class TemplateController { // 一个feign client @Autowired TemplateClient templateClient @PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE) public ResultVO create(@RequestBody @Valid TemplateParam param, HttpServletRequest request) { // 每个接口都要写一遍setXXX()方法 param.setUserI<strong style="color:transparent">来2源gaodaima#com搞(代@码&网</strong>d(request.getHeader("userId")); param.setUserName(request.getHeader("userName")); return templateClient.createTemplate(param).toResultVO(); } } @Data public class TemplateParam{ private Long templateId; private Long userId; private String userName; }
解决办法
大家都知道的两大利器,
tomcat的Filter和spring的Intercepter(具体为HandlerIntercepter)
实现原理
具体方法为定义一个Filter实现类和一个HandlerIntercepter的实现类。再定义一个HttpServletRequest实现类,其作用分别为
Filter实现类:UserInfoFilter
创建一个入口,在这个入口中定义一个机会:将我们自定义的CustomHttpServletRequestWrapper代替HttpServletRequest随着请求传递下去
HttpServletRequest实现类:customHttpServletRequestWrapper
因为HttpServletRequest对象的body数据只能get,不能set,即不能再次赋值。而我们的需求是需要给HttpServletRequest赋值,所以需要定义一个HttpServletRequest实现类:customHttpServletRequestWrapper,这个实现类可以被赋值来满足我们的需求。
HandlerIntercepter的实现类:CustomInterceptor
拦截请求,获取接口方法相关信息(方法名,参数,返回值等)。从而实现统一的给request body动态赋值
实现思路如上所述,具体的实现代码如下
代码实现
声明基础bean: UserInfoParam
UserInfoParam
:定义了包含userId,userName的实体bean,要想将用户信息注入进入,需要入参对象XXXParam继承UserInfoParam,拦截器中只处理@Requestbody中实现了UserInfoParam类的bean。
如上文controller中create方法的入参:TemplateParam,继承UserInfoParam
@Data public class TemplateParam extends UserInfoParam{ private Long templateId; // private Long userId; // private String userName; } @Data public class UserInfoParam { // 用户id private Long userId; // 用户名称 private String userName; }
定义Filter实现类: UserInfoFilter
@Slf4j public class UserInfoFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { CustomHttpServletRequestWrapper customHttpServletRequestWrapper = null; try { HttpServletRequest req = (HttpServletRequest)request; customHttpServletRequestWrapper = new CustomHttpServletRequestWrapper(req); }catch (Exception e){ log.warn("customHttpServletRequestWrapper Error:", e); } chain.doFilter((Objects.isNull(customHttpServletRequestWrapper) ? request : customHttpServletRequestWrapper), response); } }