how to handle both XmlHttpRequest(AJAX) and regular http requests in one spring mvc method?
currently my solution is
For AJAX:
@RequestMapping(value = "/verify", method = {RequestMethod.GET},
headers = "x-requested-with=XMLHttpRequest")
public
@ResponseBody userTO
void verifyForXHR(@RequestParam(required = true) String code,
HttpServletRequest request, HttpServletResponse response) {
try {
UserTO userTO = new SomeService().verifyEmail(code);
return userTO;
} catch (ExceptionABC ex) {
response.setStatus(response.SC_BAD_REQUEST);
return null;
} catch (RuntimeException ex) {
response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
return null;
}
}
For regular http requests:
@RequestMapping(value = "/verify", method = {RequestMethod.GET})
public ModelAndView verify(@RequestParam(required = true) String code) {
//get user to
try {
ModelAndView mav = new ModelAndView();
UserTO userTO = new SomeService().verifyEmail code);
mav.setViewName("somegoodpage");
mav.addObject("user", userTO);
return mav;
} catch (ExceptionAB开发者_高级运维C ex) {
logger.error(ex, ex);
ModelAndView mav = new ModelAndView("error page);
return mav;
}
} catch (RuntimeException ex) {
logger.error(ex.toString(), ex);
ModelAndView mav = new ModelAndView("another error page");
return mav;
}
}
It would be super if I can merge them into one method. Please note they have different return type. The caller for AJAX requests are JavaScript so it needs JSON as http response body media type. For regular http requests, it needs a view(page) to be returned. Any suggestions would be greatly appreciated!
To have it all in one method, you can differentiate between the two by taking one extra parameter @RequestHeader(value = "x-requested-with:XMLHttpRequest", required = false) String ajax
. Then you can check if (ajax == null)
or not and take action accordingly.
Just don't handle exceptions in such way in your controller. Build a proper ajax-aware exception resolver, then your controller methods would be one liners. I subclassed the AbstractHandlerExceptionResolver doing basically this:
@Override
public ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception exception) {
int code = getResponseCode(exception);
applyStatusCodeIfPossible(request, response, code);
ExceptionInfo info = createErrorInfo(exception);
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
return new ModelAndView(jsonView, MODEL_KEY, info);
}
else if ((code == 403 || code == 401) && SecurityContextHolder.getContext().getAuthentication().getAuthorities().contains(ANONYMOUS) == false) {
return new ModelAndView(LOGIN_REDIRECT);
}
else {
return new ModelAndView(getViewName(code), MODEL_KEY, info);
}
}
after that you only need
@RequestMapping(value = "/verify", method = {RequestMethod.GET}, headers = "x-requested-with=XMLHttpRequest")
@ResponseBody public userTO verifyForXHR(@RequestParam String code) {
return new SomeService().verifyEmail(code);
}
@RequestMapping(value = "/verify", method = {RequestMethod.GET})
public ModelAndView verify(@RequestParam String code) {
return new ModelAndView("somegoodpage", "user", new SomeService().verifyEmail(code));
}
精彩评论