开发者

Setting view name in spring filter

I've an ErrorFilter which extends the spring GenericFilterBean. I want to show an error page decorated with tiles if some error happens.

Is there any way to set a view name from the filter?

<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>

This is the configuration in web.xml and the doFilter method in errorfilter is the following:

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)开发者_StackOverflow社区;
        req.getRequestDispatcher(
                getFilterConfig().getInitParameter("errorPage")).forward(req, resp);
    }
}

The current errorpage is not decorated with tiles, so I want to decorate it with normal header and footer and call that view name from the filter.

Is it possible ?

Edit: Basically we want to be able to do something similar to Controller-method i.e. return "view name";

Already tried:

  • httpResponse.sendRedirect("errorPageView"); does not work, it redirects to http://server/fooerrorPageView
  • request.getRequestDispatcher("errorPageView").forward(request, response); also doesn't, similar as above (no http redirect, but gives the same "no such page error" content)


i think this is not possible, because this is a servlet filter, which would be applied after the spring request mapper servlet was applied. so basically, the request mapper servlet thinks it is finished, and passes the request back to the servlet container.

view names only work INSIDE of spring - outside of spring, in the servlet container, you will have to talk about urls, not view names.

a redirect to specific url would work. for this, you have to be aware of the differences between a redirect and a forward.

a redirect sends the following header to the client:

Location: http://server/new/location

along with the status code 301 (permanent redirect, to let the client know that it can cache this information) or 307 (temporary redirect, to tell the client it should ask again next time, because the redirect may change)

the forward on the request dispatcher basically mimics a new request, and you can send the request to ANY servlet in the same container. this means, you have to ALSO take the context path into consideration, meaning the answer @iimuhin gave:

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

is actually the right way to go. you can (should) add logging to see what actually happens and what paths are actually used.

also - you have to be aware of buffering. a servlet response is usually buffered, and nothing is sent to the client until either the buffer is full or the entire processing has finished.

when it is flushed, the headers are written first. this means that changing the headers AFTER the response has been flushed is not possible, because they're already sent out.

this is the reason why servlets can force flushing, but usually shouldn't.

in your case, you may want to increase the buffer size on the response:

    response.setBufferSize(int size) 

before calling chain.doFilter() to avoid premature flushing.


Why don't you use spring's error handling mechanism? here the good post about it (with examples) - https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

Other than that, not sure if there is a clean way of doing that. Other suggestions might be making a call to your application to get error page response and substitute response output with that (in that case you'll also need to use "buffered" http response to be sure that stream is not flushed yet) or make a redirect to the error url.


Filter comes before Spring. Spring beans can be injected in Filter using ApplicationContextAware mechanism, but forming a Spring MVC view means you will have to get hold of entire spring MVC framework in your Filter. I think this is not possible and you will have to forward request using RequestDispatcher not to a spring view but to your own custom view.


There must be a way to do it with Spring MVC, but i suppose a redirect is enough.

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. don't catch an Error!


Just check your redirect url. you are able to access page with the 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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜