spring在请求发起后动态修改请求参数

本文介绍了如何在Spring MVC中应对需要动态修改请求参数的需求。通过使用拦截器和过滤器,特别是过滤器,重写HttpServletRequestWrapper的方法,实现在请求发起后动态添加登录参数。该方法解决了当接口需要统一且部分需要登录验证时,无法仅用token注解注入用户参数的问题。

今天遇到了一个需求,由于需要封装一个统一的接口,用正则做路劲匹配,那么需要登录和不需要的登录的action都写在了一起。
于是乎,就不能用简单的一个token注解来完成注入用户参数的事情。而是需要根据是否被登录拦截器拦截(也就是是否需要登录)来判断以及动态的添加登录的参数;

@RequestMapping(value = { "/**/{serverID:*.do)
public Object service(@PathVariable("serviceId") String serviceId, @RequestParam Map<String, Object> map, HttpServletRequest request) {
	return map;
}

这里需要动态的往Map里添加参数
原来考虑过在拦截器中取出这个参数,但是拦截器中取出的参数无法修改。
@RequestParam 参数取值是根据HttpServletRequestWrapper中对应方法取值,那么我们的思路就可以定位到重写这个方法,然后用过滤器将请求定位到我们重写的HttpServletRequestWrapper中。
下面贴代码

/**
 * @author zhangmj
 * 2019年8月30日
 * 上午10:31:35
 */
public class TokenRequestWrapper extends HttpServletRequestWrapper{

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    private Map<String, String[]> params = new HashMap<String, String[]>();

    public TokenRequestWrapper(HttpServletRequest request) {
        super(request);
        //将现有pa
Spring框架中,修改请求和响应内容可以通过多种方式实现,具体取决于需要操作的层次以及需求的复杂程度。以下是一些常见的方法和位置: ### 1. 使用 `HandlerInterceptor` 拦截器 `HandlerInterceptor` 是 Spring MVC 提供的一个接口,允许在请求处理之前、之后或完成时进行拦截和处理。通过重写其 `preHandle`、`postHandle` 和 `afterCompletion` 方法,可以在请求进入控制器之前修改请求参数或在响应返回客户端之前修改响应内容。 ```java @Component public class CustomInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 修改请求参数设置新的属性 request.setAttribute("customAttribute", "CustomValue"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 可以在此处修改响应头或视图模型数据 response.setHeader("X-Custom-Header", "CustomValue"); } } ``` 注册拦截器Spring MVC 配置中: ```java @Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Autowired private CustomInterceptor customInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customInterceptor); } } ``` ### 2. 使用 `Filter` 过滤器 `Filter` 是 Java Servlet 规范的一部分,可以在请求到达控制器之前和响应发送给客户端之前进行拦截。适合用于日志记录、安全验证等通用逻辑。例如,使用 `MockMvc` 测试框架中的 `@AutoConfigureMockMvc` 和 `@SpringBootTest` 注解可以注入 `MockMvc` 实例,模拟 HTTP 请求并验证结果 [^1]。 ```java public class CustomFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; // 修改请求 String modifiedParam = httpRequest.getParameter("param") + "_modified"; // 创建自定义请求包装类来修改请求参数 // 修改响应 httpResponse.setHeader("X-Custom-Filter", "Modified"); chain.doFilter(request, response); } } ``` 注册过滤器: ```java @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<CustomFilter> customFilter() { FilterRegistrationBean<CustomFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(new CustomFilter()); registration.addUrlPatterns("/*"); return registration; } } ``` ### 3. 使用 `ThreadLocal` 存储请求上下文 在某些情况下,可能需要在整个请求生命周期中访问原始的 `HttpServletRequest` 对象。可以通过 `ThreadLocal` 来存储请求对象,确保每个线程独立访问自己的请求实例 [^2]。 ```java public class RequestContextHolder { private static final ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<>(); public static void set(HttpServletRequest request) { requestHolder.set(request); } public static HttpServletRequest get() { return requestHolder.get(); } public static void remove() { requestHolder.remove(); } } ``` 在过滤器设置请求对象: ```java @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; RequestContextHolder.set(httpRequest); try { chain.doFilter(request, response); } finally { RequestContextHolder.remove(); } } ``` ### 4. 使用 Zuul 或 Gateway 实现网关级修改 如果应用使用了微服务架构,并且依赖 Zuul 或 Spring Cloud Gateway 作为 API 网关,则可以在网关层面对请求和响应进行统一处理。例如,在 Zuul 中可以通过自定义 `ZuulFilter` 来添加响应头 [^3]。 ```java public class AddCustomHeaderFilter extends ZuulFilter { @Override public String filterType() { return POST_TYPE; // 在响应阶段执行 } @Override public int filterOrder() { return SEND_RESPONSE_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext context = RequestContext.getCurrentContext(); HttpServletResponse response = context.getResponse(); response.addHeader("X-Custom-Gateway-Header", "HeaderValue"); return null; } } ``` ### 5. 自定义 `RestClient` 或 `WebClient` 修改请求和响应 对于使用 `RestClient` 或 `WebClient` 发起外部 HTTP 请求的应用,可以通过自定义 `RestClient.Builder` 或 `WebClient.Builder` 来修改请求和响应内容 [^4]。 ```java @Bean public WebClient webClient() { return WebClient.builder() .baseUrl("https://api.example.com") .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .clientConnector(new ReactorClientHttpConnector( HttpClient.create().wiretap(true))) .build(); } ``` 通过上述方法,开发者可以根据具体需求选择合适的机制来修改请求和响应内容,从而实现灵活的请求处理逻辑。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值