2016-08-03 5 views
1

Хорошо, я пытаюсь реализовать систему, в которой после проверки параметров запроса, например Path, я фактически изменю ответ на ответ с разными данными. Идея заключается в создании функциональных возможностей бэкэнд-демки, таким образом, клиент может демонтировать (НЕ ТЕСТ) приложение без фактических запросов БД.Java Spring изменить ответ до его обработки

Итак, моя первая попытка использовала фильтры сервлетов, очень хороший ответ для этого можно найти here, а также некоторый хороший документ под названием The Essentials of Filters. Но я не мог заставить его работать, я думаю, потому что я использую весну с @Controller и @ResponseBody, даже я следую точно такой же выборке, что получаю null как wrapperResponse.

Затем я попробовал Interceptors, here есть хороший пример, и хороший ответ на вопрос here. Но проблема заключается в том, что обычно люди будут использовать postHandle для изменения тела, и я действительно не хочу, чтобы дескриптор даже запускался, потому что это означает, что вызовы БД также будут запущены. И если я использую preHandler как here, он просто сделает новый сервлет, и я не хочу этого.

Наконец-то я попробую @ControllerAdvice, который в принципе позволяет вам переписать тело перед отправкой, но снова обработчик обрабатывается и все вызовы БД с ним.

Моя цель состоит в том, что мне не нужно ставить повторяющийся код в каждом обработчике, я мог бы сделать preHandler вставить дополнительный заголовок и проверить этот заголовок в @ControllerAdvice, но это означает, что я должен сделать некоторые IF/ELSE в обработчике, чтобы он не обрабатывался, и я должен повторить, что на 100s @Controllers, которые у меня есть в системе, я хочу быть СУХОЙ.

Я уверен, что решение находится на фильтре в пути этого 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

Вот как мне это удается.

Сначала я создал перехватчик, который фактически фильтрует запрос, чтобы передать только то, что мы хотим для демонстрации. В предварительном обработчике вместо того, чтобы пытаться создать ответ там, используя ответный поток Response, я просто использовал 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 и что вы можете вставлять данные в качестве имени контроллера по запросу перед переходом. Все эти данные могут быть извлечены в демо-контроллере для генерации необходимых данных.