Using Spring MVC, is there any way to factorize the org.springframework.ui.Model
, in order to not to have to specify it in the method parameters within any controller?
In other words, I'm currently doing it like this:
public abstract class AbstractController {
@Autowired
protected MultipartHttpServletRequest request;
}
@Controller
public class SigninController extends AbstractController {
@RequestMapping(value = "/signin", method = RequestMethod.GET)
public String signin(@ModelAttribute User user, Model model) {
// do stuff with user (parameter)
// do stuff with model (parameter) <--
// do stuff with request (attribute)
return "/signin/index";
}
}
And I would like to do like that:
public abstract class AbstractController {
@Autowired
protected MultipartHttpServletRequest request;
@Autowired
protected Model model;
}
@Controller
public class SigninController extends AbstractController {
@RequestMapping(value = "/signin", method = RequestMethod.GET)
public String signin(@ModelAttribute User user) {
// do stuff with user (parameter)
// do stuff with model (attribute) <--
// do stuff with request (attribute)
return "/signin/index";
}
}
But when calling the URL, an exception is thrown:
...Could not autowire field: protected org.springframework.ui.Model...
...No matching bean of type [org.springframework.ui.Model] found for dependency...
I got the same error when using org.springframework.ui.ModelMap
.
Any solution of genious?
Thanks for helping :)
I finally found a solution. I'm not sure the game is worth it, but it works :)
First, add those stuff in your AbstractController
:
public abstract class AbstractController {
@Autowired
protected MultipartHttpServletRequest request;
protected ModelMap model;
public void setModel(ModelMap model) {
this.model = model;
}
public ModelMap getModel() {
return model;
}
}
Then, create an interceptor implementing org.springframework.web.servlet.HandlerInterceptor
like this one:
public class UserContextInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {
if (handler instanceof AbstractController) {
AbstractController controller = (AbstractController) handler;
controller.setModel(new ModelMap());
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
if (handler instanceof AbstractController && modelAndView != null) {
AbstractController controller = (AbstractController) handler;
modelAndView.addAllObjects(controller.getModel());
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
Finally, add these lines in your applicationContext.xml
:
<mvc:interceptors>
<bean class="path.to.my.just.created.UserContextInterceptor" />
</mvc:interceptors>
And of course, make your controllers implementing your AbstractController
.
Here it is! You need to specify neither your request
nor your model
within your controllers methods parameters anymore :) I'm not really convinced of the usefulness of that trick though, but yeah. If it can make maniacal developers happier :)
Still open to easier solutions though.