Domanda

I have a Spring MVC application which allows users to add/remove favorites via the following calls:

  • POST /api/users/123/favorites/456 (adds item 456 as a favorite for user 123)
  • DELETE /api/users/123/favorites/456 (removes item 456 as a favorite for user 123)

I'd also like to support the following 2 calls that do the exact same thing (assuming user 123 is logged in):

  • POST /api/users/me/favorites/456
  • DELETE /api/users/me/favorites/456

I've created an interceptor as shown below:

public class UserMeInterceptor extends HandlerInterceptorAdapter{
    public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler ) throws Exception{
        Integer userId = AccessControlUtil.getUserId();
        String redirectUrl = request.getContextPath() + request.getRequestURI().replace( "/me/", "/" + userId + "/" );
        if( redirectUrl.endsWith( "/me" ) ){
            redirectUrl = redirectUrl.replace( "/me", "/" + userId );
        }
        response.sendRedirect( redirectUrl );
        response.flushBuffer();
        return false;
    }
}

This approach works great, but only for GET requests. Any way I can forward/redirect a POST request and maintain all POSTed data and method type? Ideally, I want to reuse the same controller that is already defined to handle the case when the ID is passed in.

È stato utile?

Soluzione

What about this approach:

@RequestMapping("/api/users/{userId}/favorites/{favoriteId}")
public String clientsByGym(@PathVariable("userId") String userId, @PathVariable("favoriteId") Long favoriteId) {
    Integer theUserId = null;
    if("me".equals(userId)) {
        theUserId = AccessControlUtil.getUserId()
    } else {
        theUserId = Integer.valueOf(userId);
    }
    ...
}

Basically, have your method accept String for userId and from there you can figure out if it is 'me' or an actual userId value. This way you don't have to mess with redirects. If you have to do this all the time, you could make a helper method like so:

public Integer getUserId(String userId) { 
    return "me".equals(userId) ? AccessControlUtil.getUserId() : Integer.valueOf(userId);
}

Altri suggerimenti

Spring MVC has two mechanisms for doing property conversion, but these those would not help in this case in a clean way - check this answer. These are not meant to be applied selectivelly only to one String parameter in particular.

The best would be to apply an aspect to the controllers and methods for which you want this functionality, see this answer for an example.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top