springboot使用过滤器对请求参数进行处理

前段时间对项目进行改造,需要实现对请求参数进行解密,再传输到控制层。参考了网上的一些文章,基本都是通过过滤器和实现RequestBodyAdvice接口进行处理。结合自己的项目要求,实现RequestBodyAdvice接口只能对参数在请求体中(@RequestBody)才生效,而项目中需要对get和post请求都进行处理,所以最后决定使用过滤器来实现。这里记录下代码实现,方便以后遇到相似的功能就不需要再去网上搜了。

首先需要继承HttpServletRequestWrapper类来自定义一个Request类,因为post请求需要使用request.getInputStream()来读取请求体中的参数,而流中的数据读取一次后就不能再读取了,这样传输到控制层就没有参数了,所以需要自定义一个request进行包装,将读取的参数处理后重新放回request中。

public class MyHttpRequest extends HttpServletRequestWrapper {
    /**
     * 保存流数据
     */
    private final byte[] body;
    /**
     * 保存参数
     */
    private Map<String, String[]> params = new HashMap<>();

    public MyHttpRequest(HttpServletRequest request) {
        super(request);
        body = getBodyString(request).getBytes(StandardCharsets.UTF_8);
        this.params.putAll(request.getParameterMap());
    }

    public MyHttpRequest(HttpServletRequest request, byte[] body) {
        super(request);
        this.body = body;
        this.params.putAll(request.getParameterMap());
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() {
                return bais.read();
            }
        };

    }
    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    @Override
    public String getParameter(String name) {
        String[] values = params.get(name);
        if(values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public Enumeration<String> getParameterNames() {
        return Collections.enumeration(params.keySet());
    }

    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return this.params;
    }

    public void setParameter(Map<String, String> map) {
        params.clear();
        map.forEach((key, value) -> params.put(key, new String[]{value}));
    }

    public String getBody() {
        return new String(body);
    }

    public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}

然后自定义一个过滤器,实现Filter接口

@WebFilter(filterName = "customParamFilter", urlPatterns = {"/*"})
public class CustomParamFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        MyHttpRequest requestWrapper = new MyHttpRequest(request);
        try {
            // get请求
            if (requestWrapper.getMethod().equals(HttpMethod.GET.name())) {
                // 对参数进行处理,得到新的参数,将参数重新设置到request中
                Map<String, String> params = handle(requestWrapper.getParameterMap());
                requestWrapper.setParameter(params);
            } else { // post请求,这里没有对x-www-form-urlencoded类型进行处理
                String body = requestWrapper.getBody();
                if (StringUtils.isNotEmpty(body)) {
                    JSONObject jsonObject = JSONObject.parseObject(body);
                    // 对参数进行处理
                    Map<String, String> params = handle(jsonObject);
                    // 由于body是设置成不可变的,所以需要重新创建一个request,将body设置进去
                    requestWrapper = new MyHttpRequest(requestWrapper, JSONObject.toJSONString(params).getBytes());
                }
            }
            filterChain.doFilter(requestWrapper, servletResponse);
        } catch (Exception ex) {
            outErrorMessage(servletResponse, ExceptionConfig.BUSINESS_CODE, ExceptionConfig.BUSINESS_MSG);
        }

    }

    public void outErrorMessage(ServletResponse servletResponse, Integer code, String msg) throws IOException {
        //返回json错误
        servletResponse.setCharacterEncoding("UTF-8");
        servletResponse.setContentType("application/json; charset=utf-8");
        PrintWriter out = servletResponse.getWriter();
        JSONObject res = new JSONObject();
        res.put("code", code);
        res.put("msg", msg);
        out.append(JSON.toJSONString(res));
    }
    
	private Map<String, String> handle(Object params) {
	    // 自定义参数的处理逻辑,最后将参数以map形式返回回去
	    // ......
	    
	    return new HashMap<>();
	}
}

类上加@WebFilter使过滤器生效即可。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
可以通过自定义过滤器,在过滤器中修改请求参数,实现调整某个方法请求参数。具体实现步骤如下: 1.编写自定义过滤器类,继承`javax.servlet.Filter`类,实现`doFilter()`方法,在该方法中获取请求参数,修改请求参数,然后将请求传递给下一个过滤器或者目标方法。 2.在SpringBoot主类中添加自定义过滤器,通过`@Bean`注解将自定义过滤器注入到Spring容器中。 下面是一个示例代码,演示如何通过自定义过滤器修改请求参数: ```java @Component public class MyFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 获取请求参数 HttpServletRequest req = (HttpServletRequest) request; String parameter = req.getParameter("param"); // 修改请求参数 if (parameter != null && !parameter.isEmpty()) { req.setAttribute("newParam", parameter + "new"); } // 将修改后的请求传递给下一个过滤器或者目标方法 chain.doFilter(request, response); } } @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } // 注册自定义过滤器 @Bean public FilterRegistrationBean<MyFilter> myFilter() { FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new MyFilter()); registrationBean.addUrlPatterns("/api/*"); return registrationBean; } } @RestController @RequestMapping("/api") public class ApiController { @GetMapping("/test") public String test(@RequestParam("param") String param) { return "param: " + param; } } ``` 在上面的示例中,自定义过滤器`MyFilter`会拦截所有以`/api`开头的请求,并在`doFilter()`方法中修改请求参数`param`,将其值添加了一个后缀`new`,然后将修改后的请求传递给目标方法。在`ApiController`中,我们定义了一个`/test`接口,接口中的`param`参数会被自定义过滤器修改后再传递给目标方法,最终返回给客户端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值