|  由于最近在使用spring+jersey开发要设置基于servlet的filter。当在filter中通过request.getReader或者getInputStream读取body中的json参数处理时,由于rest风格的jersey框架底层亦是基于同样原理读取post请求body中参数。因为request自身的原则:getReader或者getInputStream只能调用其中一个且只有一次可以正常获取body中内容,导致在filter中通过getReader第一次读取body中参数成功,当放行时,jersey中控制器执行时候,会出现异常: java.lang.IllegalStateException: getReader() has already been called for this request。   ############################ ###           运行系统:windows8 ###          JDK版本 : JDK1.7 ###          框架:spring3x + jersey2.x ###          开发IDE:MyEclipse ############################ 1.0 在web.xml中配置spring过滤器filter,集成自定义filter    
  
  
  <filter>          <filter-name>DelegateFilter</filter-name>          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>          <init-param>              <param-name>targetBeanName</param-name>              <param-value>myFilter</param-value>         </init-param>          <init-param>              <param-name>targetFilterLifecycle</param-name>              <param-value>true</param-value>          </init-param>      </filter>      <filter-mapping>          <filter-name>DelegateFilter</filter-name>          <url-pattern>/*</url-pattern>      </filter-mapping>   2.0在spring配置文件application.xml中定义自定义filterbean。
      
  
  
  <bean id="myFilter" class="com.cybbj.action.filter.FilterPost"></bean>    
  
  
  PS:若是在filter中想使用springIOC容器中其他bean.如其他service类。那么可以在该bean中配置。  例如在filter中需要注入公用commonSerivce  public class myFilter implements Filter{      private CommonService commonService;    //需要setter     .......  }    
  
  
  要想使用commonService而不抛出空指针异常,需要在bean中配置依赖:  <bean id="myFilter" class="com.cybbj.action.filter.FilterPost">  <property name="commonService"> <ref bean="commonService"/> <!-- 其中commonService是通过注解或者xml配置到IOC容器中的类--></property></bean>      
  
  
  3.0 自定义filter  原始代码与运行结果如下:      
  
  
  public class FilterPost implements Filter{            private Log log = LogFactory.getLog(FilterPost.class);        String param = "";            public void destroy() {                        }        public void doFilter(ServletRequest req, ServletResponse res,              FilterChain chain) throws IOException, ServletException {             HttpServletRequest request = null;              if(req instanceof HttpServletRequest) {                  request = (HttpServletRequest)req;              }                            if("POST".equalsIgnoreCase(request.getMethod())){                  param = this.getBodyString(request.getReader());                  log.info("filter读取body中的参数>>>>>>>>>"+param);                  chain.doFilter(request, res);      }                }        public void init(FilterConfig config) throws ServletException {                }    
  
  
      lic static String getBodyString(BufferedReader br) {  String inputLine;       String str = "";     try {       while ((inputLine = br.readLine()) != null) {        str += inputLine;       }       br.close();     } catch (IOException e) {       System.out.println("IOException: " + e);     }     return str;     4.0基于jersey的controller中post请求处理    
  
  
  @POST  @Path("/postJson")  @Produces(MediaType.APPLICATION_JSON)  @Consumes(MediaType.APPLICATION_JSON)  public Map<String, String> postByJson(Map<String, Object> jsonParam) {        JSONObject jo = new JSONObject(jsonParam);      System.out.println(jsonParam);      Map<String, String> param = new HashMap<String, String>();      param.put("name", jo.getString("name").length()==0? "" : jo.getString("name"));      param.put("age", jo.getString("age").length()==0  ? "" :jo.getString("age"));      param.put("status", "200");      param.put("Msg", "ok,success");      return param;  }        
  
  
  5. 抛出异常  java.lang.IllegalStateException: getReader() has already been called for this request      at org.apache.catalina.connector.Request.getInputStream(Request.java:1085)   解决方法:
    
  
  
  结合JODD开源框架,且在Filter中将ServletRequest替换为ServletRequestWrapper 来解决该问题。       A:添加jodd支持:  在pom.xml中添加对jodd的依赖:    
  
  
   
  <dependency>  </span><groupId>org.jodd</groupId>  </span><artifactId>jodd-core</artifactId>  </span><version>3.4.8</version>  </dependency>        B:结合jodd创建自定义ServletRequestWrapper    
  
  
  public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper{         private final byte[] body; //用于保存读取body中数据                  public BodyReaderHttpServletRequestWrapper(HttpServletRequest request)         throws IOException {                super(request);                body = StreamUtil.readBytes(request.getReader(), "UTF-8");            }                    @Override            public BufferedReader getReader() throws IOException {                return new BufferedReader(new InputStreamReader(getInputStream()));            }                    @Override            public ServletInputStream getInputStream() throws IOException {                final ByteArrayInputStream bais = new ByteArrayInputStream(body);                return new ServletInputStream() {                            @Override                    public int read() throws IOException {                        return bais.read();                    }                    @Override                  public boolean isFinished() {                      // TODO Auto-generated method stub                      return false;                  }                    @Override                  public boolean isReady() {                      // TODO Auto-generated method stub                      return false;                  }                    @Override                  public void setReadListener(ReadListener arg0) {                      // TODO Auto-generated method stub                                        }                };            }    }    C:用wrapper替换request修改filter
      
  
  
  public void doFilter(ServletRequest req, ServletResponse res,              FilterChain chain) throws IOException, ServletException {            String method = "GET";             ServletRequest requestWrapper = null;                if(req instanceof HttpServletRequest) {                    method = ((HttpServletRequest) req).getMethod();                  requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) req);  //替换              }                              if("POST".equalsIgnoreCase(method)){                  param = this.getBodyString(requestWrapper.getReader());                  log.info("filter读取body中的参数>>>>>>>>>"+param);                  chain.doFilter(requestWrapper, res);      }              
 D:请求测试
   
 请求成功................   参考文章:http://liwx2000.iteye.com/blog/1542431   原文地址:https://blog.csdn.net/xiansky2015/article/details/52013690 |