zoukankan      html  css  js  c++  java
  • @RequestBody注解的参数仅仅读取一次的问题解决。

    最近在写日志管理,想着使用拦截器加注解的方式,但是遇到了一个问题,就是如果使用@RequestBody注解接收的参数只能读取一次,造成了我在拦截器中如果接收了参数,在Controller层就接收不到了,为了解决这个问题,在网上查了方法。自定义一个MyRequestWrapper 继承 HttpServletRequestWrapper不多说,看代码:

    package cn.huimin100.cms.handler;
     
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.*;
     
    /**
    * 与HttpServletRequestWrapperFilter配合使用,保证@RequestBody注解的参数可以读取两次
    * 因为要在拦截器中获取参数
    */
    public class MyRequestWrapper extends HttpServletRequestWrapper {
    private final String body;
    public MyRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    StringBuilder stringBuilder = new StringBuilder();
    BufferedReader bufferedReader = null;
    try {
    InputStream inputStream = request.getInputStream();
    if (inputStream != null) {
    bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    char[] charBuffer = new char[128];
    int bytesRead = -1;
    while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
    stringBuilder.append(charBuffer, 0, bytesRead);
    }
    } else {
    stringBuilder.append("");
    }
    } catch (IOException ex) {
    throw ex;
    } finally {
    if (bufferedReader != null) {
    try {
    bufferedReader.close();
    } catch (IOException ex) {
    throw ex;
    }
    }
    }
    body = stringBuilder.toString();
    }
     
    @Override
    public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
    ServletInputStream servletInputStream = new ServletInputStream() {
     
     
    @Override
    public boolean isFinished() {
    return false;
    }
     
    @Override
    public boolean isReady() {
    return false;
    }
     
    @Override
    public void setReadListener(ReadListener readListener) {
     
    }
     
    public int read() throws IOException {
    return byteArrayInputStream.read();
    }
    };
    return servletInputStream;
    }
     
    @Override
    public BufferedReader getReader() throws IOException {
    return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
     
    public String getBody() {
    return this.body;
    }
    }
     
    需要结合过滤器使用:
    package cn.huimin100.cms.handler;
     
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
     
    /**
    * 该过滤器与MyRequestWrapper配合使用,可以让@RequestBody注解的参数至少可以读取两次,
    * 从而使得在拦截器中可以获取@RequestBody注解的参数。
    */
    @WebFilter(filterName="HttpServletRequestWrapperFilter",urlPatterns="/*")
    public class HttpServletRequestWrapperFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
     
    }
     
    @Override
    public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    ServletRequest requestWrapper= null;
    if(request instanceof HttpServletRequest){
    requestWrapper = new MyRequestWrapper((HttpServletRequest) request);
    }
    if(null == requestWrapper){
    filterChain.doFilter(request,servletResponse);
    }else{
    filterChain.doFilter(requestWrapper,servletResponse);
    }
    }
     
    @Override
    public void destroy() {
     
    }
    }
     
    拦截器中这样获取参数
    package cn.huimin100.cms.handler;
     
    import cn.huimin100.cms.config.LogAnnotation;
    import cn.huimin100.cms.mapper.newcms.ActionLogsMapper;
    import cn.huimin100.cms.pojo.po.ActionLogs;
    import cn.huimin100.cms.util.DateUtil;
    import com.alibaba.fastjson.JSONObject;
    import org.apache.commons.lang.time.DateFormatUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.Method;
    import java.util.Date;
    import java.util.Map;
     
    /**
    * 在读取@RequestBody注解的参数的时候,需要配合MyRequestWrapper使用
    * 一遍保证这些参数可以在Controller层再次读取
    */
    public class LogManageInterceptor extends HandlerInterceptorAdapter {
    private final Logger logger = LoggerFactory.getLogger(LogManageInterceptor.class);
     
    @Autowired
    private ActionLogsMapper logMapper;
     
    public static final String USER_NAME="user__name";
    public static final String BRANCH_ID="branch__id";
    public static final String USER_ID="user__id";
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     
    if (handler instanceof HandlerMethod) {
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    Method method = handlerMethod.getMethod();
    LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
    if(annotation != null){
    try{
    ActionLogs log = new ActionLogs();
    //操作类型
    log.setAction(annotation.action().getCode());
    //操作目标方法
    log.setCategory(annotation.targetMethod().getCode());
    //操作人姓名
    log.setActionTime(DateFormatUtils.format(new Date(), DateUtil.DATETIME_DEFAULT_FORMAT));
    log.setIsmiddlemode(2);
    Map<String, String[]> parameterMap = request.getParameterMap();
    if(parameterMap == null || parameterMap.isEmpty()){
    MyRequestWrapper myRequestWrapper = new MyRequestWrapper((HttpServletRequest) request);
    String body = myRequestWrapper.getBody();
    JSONObject jsonObject = JSONObject.parseObject(body);
    log.setOperator(jsonObject.getString(USER_NAME));
    log.setOperatorId(jsonObject.getInteger(USER_ID));
    log.setBranchId(jsonObject.getInteger(BRANCH_ID));
    }else{
    log.setOperator(request.getParameter(USER_NAME));
    log.setOperatorId(Integer.valueOf(request.getParameter(USER_ID)));
    log.setBranchId(Integer.valueOf(request.getParameter(BRANCH_ID)));
    }
    logMapper.insertSelective(log);
    }catch (Exception e){
    logger.error("记录操作日志错误 e:{}",e);
    }
    }
    }
    return true;
    }
    }

  • 相关阅读:
    今天在国外网站上做了个测试,结果竟然这样
    中考总算考完了
    [转]从磁芯大战谈汇编
    位运算Pascal相关函数/过程
    本Blog已经迁往Wordpress.com
    PhyTopic测试结果...
    POJ1273 dinic Pascal模板
    C#解析xml文件
    并行和并发
    RI工具库参考
  • 原文地址:https://www.cnblogs.com/bfyq/p/9265803.html
Copyright © 2011-2022 走看看