2012-08-09 157 views
1

我想为我的JSON webservices创建一个验证系统。这个想法是让一个拦截器捕获每个Json @RequestBody,通过JacksonMapping来创建一个JSON对象。然后从它读取ValidationAnnotations来检查数据,以及何时通过完成正常流程,然后通过包含错误消息的modelandviewmap发回给发件人。HandlerInterceptorAdapter似乎并没有转发HttpServletRequestWrapper

知道此背景下考虑这个

@RequestMapping(value="/rest/contact/list/filter", method = RequestMethod.POST, consumes="application/json", produces="application/json") 
public @ResponseBody JsonContactList findFilteredContacts(@RequestBody JsonContactSelectorData selectorData, Model model) throws Exception { 
    MbaLog.debugLog(logger,"Finding Contacts with selector data: " + selectorData);  
    JsonContactList result = contactService.findContacts(selectorData); 
    return result; 
} 

这是我的控制器方法拦截器会前,以下是拦截

@Override 
public boolean preHandle(HttpServletRequest request, 
     HttpServletResponse response, Object handler) throws Exception { 
    ValidationRequestWrapper wrapper = new ValidationRequestWrapper(request); 
    //do complex validation here 
    return super.preHandle(wrapper, response, handler); 
} 

下就行了是RequestWrapper此类

public class ValidationRequestWrapper extends HttpServletRequestWrapper { 

    private String jsonString; 

    public ValidationRequestWrapper(HttpServletRequest request) throws IOException { 
     super(request); 
     jsonString = ""; 
     Scanner scanner = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A"); 
     if (scanner.hasNext()) 
      jsonString = scanner.next(); 

     System.out.println("need a break"); 
    } 

    @Override 
    public ServletInputStream getInputStream() 
     throws IOException { 

     final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(jsonString.getBytes()); 
     ServletInputStream inputStream = new ServletInputStream() { 
      public int read()  
       throws IOException { 
       return byteArrayInputStream.read(); 
      } 
     }; 
     return inputStream; 
    } 
} 

正如你所看到的,我抓住请求输入流,然后重写如在这些情况下习惯做的那样,getInputStream()。在拦截器中,你可以看到我实例化这个包装并将它传递给super.prehandle(...)。我期望然后进入控制器,并与我的jsonobject一起愉快地工作。但结果相当令人失望。

java.io.EOFException: No content to map to Object due to end of input 

被覆盖的inputstream方法似乎没有被调用?或者我有这个机制完全错误?我甚至可以使用HandlerInterceptorAdapter

回答

4

我设法弄清楚,使用HandlerInterceptorAdapter来完成我在我的问题中所要求的功能是不可能的。

我唯一的解决这一选项是使用一个javax.servlet.Filter的

例如

@Override 
public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain chain) throws IOException, ServletException { 
    InterceptorRequestWrapper myRequestWrapper = new InterceptorRequestWrapper((HttpServletRequest) request); 
    String httpRequestMethod = ((HttpServletRequest) request).getMethod(); 
    if("POST".equals(httpRequestMethod) || "PUT".equals(httpRequestMethod)){ 
     String body = myRequestWrapper.getBody(); 
     ErrorObject errorObject = new ErrorObject(); 
     errorObject.setSource(body); 
     Map<String, List<ErrorMessage>> errorMessages = new HashMap<String, List<ErrorMessage>>(); 
     ErrorMessage error = new ErrorMessage(); 
     error.setErrorLabel("myerror"); 
     errorMessages.put("test", Arrays.asList(error)); 
     errorObject.setErrorMessages(errorMessages); 
     myRequestWrapper.setAttribute("errorObject", errorObject); 
    } 
    chain.doFilter(myRequestWrapper, response); 
}