2010-09-01 1 views
9

У меня есть ErrorFilter, который удлиняет весну GenericFilterBean. Я хочу показать страницу с ошибками, украшенную плитками, если произошла какая-то ошибка.Установка имени вида в пружинном фильтре

Есть ли способ установить имя вида из фильтра?

<filter> 
    <filter-name>errorFilter</filter-name> 
    <filter-class>com.abc.filter.ErrorFilter</filter-class> 
    <init-param> 
     <param-name>errorPage</param-name> 
     <param-value>/jsp/errorpage.jsp</param-value> 
    </init-param> 
</filter> 

Это конфигурация в web.xml и метод doFilter в errorfilter является следующее:

public void doFilter(ServletRequest req, ServletResponse resp, 
     FilterChain chain) throws IOException, ServletException { 

    HttpServletRequest httpReq = (HttpServletRequest) req; 
    StringBuffer reqUrl = httpReq.getRequestURL(); 
    try { 
     chain.doFilter(req, resp); 
    } catch (Exception ex) { 
     String requestRepresentation = createRequestRepresentation(req); 
     errorService.handleException(reqUrl.toString(), ex, requestRepresentation); 
     req.getRequestDispatcher(
       getFilterConfig().getInitParameter("errorPage")).forward(req, resp); 
    } catch (Error er) { 
     errorService.handleError(reqUrl.toString(), er); 
     req.getRequestDispatcher(
       getFilterConfig().getInitParameter("errorPage")).forward(req, resp); 
    } 
} 

Ток errorpage не декорирован плиткой, поэтому я хочу, чтобы украсить его с нормальным заголовок и нижний колонтитул и вызовите это имя вида из фильтра.

Возможно ли это?

Edit: В основном мы хотим, чтобы быть в состоянии сделать что-то подобное контролеру-метод т.е. возврата «имя вида»;

Уже пробовал:

  • httpResponse.sendRedirect ("errorPageView"); не работает, перенаправляется на http://server/fooerrorPageView
  • request.getRequestDispatcher ("errorPageView"). Forward (request, response); также не делает, подобно тому, как выше (не Перенаправление HTTP, но не дает такой же «нет такой ошибки страницы» содержание)

ответ

0

Там должен быть способ сделать это с Spring MVC, но я предполагаю, перенаправлением является достаточно.

try { 
    chain.doFilter(req, resp); 
} catch (Exception ex) { 
    if (response.isCommitted()) { 
     log(ex); // at least a part of the response is already sent to the client, you can't do much about it 
    } else { 
     session.setAttribute("last.exception", ex); 
     response.sendRedirect(request.getContextPath() + getFilterConfig().getInitParameter("errorPage")); 
    } 
} 

P.S. не поймайте ошибку!

+0

_sendRedirect_ будет просто перенаправлять браузер клиента на указанный URL-адрес, минуя любое разрешение имен имен. –

1

Я думаю, что это невозможно, потому что это фильтр сервлета, который будет применяться после того, как будет применен сервлет сервопривода пружины. так что в основном, сервлет сервата запроса считает, что он закончен, и передает запрос обратно в контейнер сервлета.

посмотреть имена только работают ВНУТРИ весны - вне весны, в контейнере сервлетов, вам придется говорить о URL-адресах, а не о названиях.

перенаправление на определенный URL-адрес будет работать. для этого вам нужно знать различия между перенаправлением и переходом.

перенаправлением посылает следующий заголовок к клиенту:

Расположение: http://server/new/location

вместе с кодом состояния 301 (постоянный редирект, чтобы позволить клиенту знать, что он может кэшировать эту информацию) или 307 (временное перенаправление, чтобы сообщить клиенту, что он должен снова запросить в следующий раз, поскольку перенаправление может быть изменено)

Вперед на диспетчере запросов в основном имитирует новый запрос, и вы можете отправить запрос ЛЮБОЙ сервлет в том же контейнере. это означает, что вы должны также принять контекстный путь во внимание, что означает ответ @iimuhin дал:

response.sendRedirect(
     request.getContextPath() + 
     getFilterConfig().getInitParameter("errorPage")); 

на самом деле правильный путь. вы можете (должны) добавить журнал, чтобы узнать, что на самом деле происходит и какие пути фактически используются.

также - вы должны знать о буферизации. ответ сервлета обычно буферизуется, и ничто не отправляется клиенту до тех пор, пока не будет заполнен буфер или не закончится вся обработка.

, когда он покраснел, заголовки написаны первыми. это означает, что изменение заголовков ПОСЛЕ ответа было сброшено, потому что они уже отправлены.

Это причина, по которой сервлеты могут принудительно промывать, но обычно этого не должно.

в вашем случае, вы можете увеличить размер буфера на ответ:

response.setBufferSize(int size) 

перед вызовом chain.doFilter(), чтобы избежать преждевременной гиперемии.

+0

Большое вам спасибо за подробное объяснение по этому вопросу. +1 для обозначения разницы между перенаправлением и переходом. – yuva

1

Почему вы не используете механизм обработки ошибок весны? здесь хороший пост об этом (с примерами) - https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

Кроме этого, не уверен, что есть чистый способ сделать это. Другие предложения могут заключаться в обращении к вашему приложению, чтобы получить ответ на страницу с ошибкой и заменить ответ на этот результат (в этом случае вам также потребуется использовать «буферизованный» HTTP-ответ, чтобы убедиться, что поток еще не очищен) или сделать перенаправить на URL-адрес ошибки.

+0

Ваше предложение работает, если запрашивающий хочет показать страницу ошибки с контроллера. Он хочет построить страницу ошибки из Сервлета, который до того, как запрос будет передан контроллеру. Таким образом, обработка исключений не может работать здесь. Ваше второе предложение стоит отметить. – yuva

+1

Благодарим вас за ответ и оценку, но почему вы думаете, что фильтр сервлетов не способен поймать исключение, возникшее в контроллере пружины или после выполнения весеннего контроллера (другими словами, на обратном пути после выполнения контроллера)? – Maks

+0

Весь смысл моего ответа был: - использовать функцию sring, если вы можете - если вы (по какой-либо причине) не можете его использовать, перенаправление или разбор ответов (в фильтре) по-прежнему является опцией. Но это может работать только в том случае, если ответ еще не завершен. Имеет ли смысл? – Maks

1

Фильтр подходит к весне. Весенние бобы могут быть введены в Фильтр с использованием механизма ApplicationContextAware, но формирование Spring MVC-просмотра означает, что вам нужно будет получить всю масляную структуру MVC в вашем Фильтре. Я думаю, что это невозможно, и вам придется пересылать запрос с помощью RequestDispatcher, а не на весенний вид, а на свой собственный вид.

0

Просто проверьте URL-адрес перенаправления. вы можете получить доступ к странице с URL-адресом.

public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) 
     throws IOException { 
    String redirectUrl = request.getContextPath() + url; 
    redirectUrl = response.encodeRedirectURL(redirectUrl); 

    if (logger.isDebugEnabled()) { 
     logger.debug("Redirecting to '" + redirectUrl + "'"); 
    } 

    response.sendRedirect(redirectUrl); 
}