3

Is there a way to access the URL resolved from a Spring MVC controller - e.g.

@RequestMapping("/{language}/news/{articleId}")
public String newsPage(...) {

}

Resolves to:

/en/news/63421 

I'd like to store this with the session so I can keep a track of last place visited. The motivation here is if the page is secured the login filter will come into play and we have used

SavedRequestAwareAuthenticationSuccessHandler

to route users back to the page they were trying to access.

However if they are viewing unsecured pages and choose to log in using a form that drops down from the top of the screen (the page's menu bar) the 'last page' seems to be the login form so the success handler drops them back to the root context.

I'd like to intercept controller calls and store a single URL with the session, override SavedRequestAwareAuthenticationSuccessHandler to allow us to modify the RequestCache and then let Spring redirect on login success.

Ideally we'd like a generic way to do this across all controllers but not sure if there is a filter we can use to pick this up - filtering requests gets all sorts of noise like css, js, images and html fragment pages so we're hoping someone knows a way to do this just with the controllers themselves.

user1016765
  • 2,935
  • 2
  • 32
  • 48

2 Answers2

1

To get the URL path you can use the HttpServletRequest - so for example you have:

www.mysite.com/en/news/63421

req.getPathInfo() = /en/news/63421

Storing it in the session though could cause problems if someone is to use your site with multiple tabs open.

Ciaran George
  • 571
  • 5
  • 19
  • We're ok storing in sessions as the behaviour I need only happens when a user chooses to log in, so it'll only affect the login success redirect. Good point though, I'll add some comments to the attribute warning about this, thanks. – user1016765 Jul 19 '13 at 11:08
1

There are two questions:

1) obtain the url in a controller method

@RequestMapping("/{language}/news/{articleId}")
public String newsPage(..., HttpServletRequest request) {
    String uri = request.getRequestUri();
    ...
}

If you need this very often then you can implement a HandlerMethodArgumentResolver. *See this answer https://stackoverflow.com/a/8769670/280244 for an example (it implements a HandlerMethodArgumentResolver for the current user, but you can easyly adapt it for urls)

2.) store the url for each request in the session

You can implement a Servlet Filter or Spring HandlerInterceptor, both get a HttpServletRequest (In a Servlet Filter you need to cast the ServletRequest to an HttpServletRequest first.

Then you can obtain the url and the Session httpServletRequest.getSession() and then store the url in the session.

public class MyFilter implements Filter {

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        //do nothing
    }

    @Override
    public void doFilter(ServletRequest requ, ServletResponse res, FilterChain chain)
                       throws IOException, ServletException {
        if (requ instanceof HttpServletRequest) {
            HttpServletRequest httpServletRequest = (HttpServletRequest) requ;                
            httpServletRequest.getSession().setAttribute(
                                              "myFilter.LAST_URL",
                                               httpServletRequest .getRequestURI());
        } 

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

}
Community
  • 1
  • 1
Ralph
  • 118,862
  • 56
  • 287
  • 383
  • Option 1 means adding boilerplate to every controller/method which I'm trying to avoid. – user1016765 Jul 19 '13 at 10:58
  • Option 2: I already tried but am getting requests for static resources picked up from the filter chain (css, js etc) and not the target URI of the controller only. I'm looking into addInterceptor like here: http://stackoverflow.com/questions/10391988/in-spring-3-1-can-mvcinterceptors-be-used-in-conjunction-with-configuration Problem is I switched off @EnableMvc because we needed to re-order request and resource handler orders (css/news.css was interferring with {language}/news controller mapping)... – user1016765 Jul 19 '13 at 11:04
  • user1016765: if you have a common postfix for the urls that mapped by controllers, then you can use it for the filter mapping. – Ralph Jul 19 '13 at 11:31