2016-08-03 51 views
1

好吧,我一直在嘗試實現一個系統,其中檢查請求上的參數(如Path)後,我將實際修改響應以用不同的數據進行回答。想法是創建後端演示功能,通過這種方式,客戶端可以演示(不測試)應用程序,而無需實際發出數據庫請求。Java Spring在處理它之前更改響應

所以,我的第一次嘗試是使用servlet過濾器,這個很好的答案可以找到here,還有一些很好的文檔The Essentials of Filters。但我無法讓它工作,我想因爲我使用@Controller和@ResponseBody的spring,即使我遵循完全相同的示例,我會得到一個null作爲wrapperResponse。

然後我試了Interceptors, here有很好的例子,並且很好的回答here。但問題在於,通常人們會使用postHandle來修改主體,而我真的不希望句柄甚至會觸發,因爲這意味着DB調用也會被觸發。如果我使用preHandler作爲here它只會創建一個新的servlet,而我不想那樣做。

最後,我嘗試@ControllerAdvice,它基本上允許您在發送之前重新寫入主體,但同樣,處理程序得到處理,所有數據庫調用與它。我的目標是,我不必在每個處理程序中放置重複的代碼,我可以讓一個preHandler插入一些額外的頭文件並在@ControllerAdvice中檢查該頭文件,但這意味着我必須使某些IF /在處理程序中的ELSE,所以它不會得到處理,我必須重複在系統中的@Controllers的100,我想幹。

我敢肯定的解決方案是在過濾器中的這個answer

public void doFilter(ServletRequest request, ServletResponse response, 
    FilterChain chain) throws IOException, ServletException { 

System.out.println("BEFORE filter"); 
PrintWriter out = response.getWriter(); 
CharResponseWrapper responseWrapper = new CharResponseWrapper(
     (HttpServletResponse) response); 

chain.doFilter(request, responseWrapper); 

String servletResponse = new String(responseWrapper.toString()); 

out.write(servletResponse + " filtered"); // Here you can change the response 


System.out.println("AFTER filter, original response: " 
     + servletResponse); 

} 

的方式,但我不能使它與春天和電話@ResponseBody工作。真的被告知,this不回答我的問題。

回答

0

這是我設法做到這一點的方式。

首先我創建了一個攔截器,它實際上過濾了請求,只傳遞想要演示的請求。在預處理程序,而不是試圖創建一個響應那裏使用響應outstream我只是使用RequestDispatcher 轉發請求到一個新的控制器,我稱之爲演示控制器。

@Override 
public boolean preHandle(HttpServletRequest request, 
     HttpServletResponse response, Object handler) throws Exception { 
    // TODO Auto-generated method stub 

    Pattern pattern = Pattern.compile("someregex"); 
    Matcher matcher = pattern.matcher(request.getPathInfo()); 

    if (matcher.find()) 
    { 
     if (matcher.group(0).equals("SOMETHING")) 
     { 
      HandlerMethod handlerMethod = ((HandlerMethod)handler); 
      request.setAttribute("methodName", handlerMethod.getBeanType().getSimpleName()); 
      request.getRequestDispatcher("/demo").forward(request, response); 
      return false; 
     } 
     return true; 
    } 
    else 
    { 
     return true; 
    } 
} 

在演示控制器中,你可以創建一個你想演示的正確響應。這裏的好處在於,在新的演示中,轉發的請求將具有原始請求javax.servlet.forward.request_uri的屬性,並且您可以在轉發之前將請求中的數據作爲請求的controllerName。所有這些數據都可以在Demo控制器中提取,以生成所需的數據。