Как факторизовать модель в контроллерах?
Используя Spring MVC, есть ли способ разложить org.springframework.ui.Model
, чтобы не приходилось указывать его в параметрах метода внутри какого-либо контроллера?
Другими словами, я сейчас делаю это так:
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";
}
}
И я хотел бы сделать так:
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";
}
}
Но при вызове URL выдается исключение:
...Could not autowire field: protected org.springframework.ui.Model...
...No matching bean of type [org.springframework.ui.Model] found for dependency...
Я получил ту же ошибку при использовании org.springframework.ui.ModelMap
,
Любое решение гениально?
Спасибо за помощь:)
1 ответ
Я наконец нашел решение. Я не уверен, что игра того стоит, но она работает:)
Во-первых, добавьте эти вещи в свой 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;
}
}
Затем создайте перехватчик, реализующий org.springframework.web.servlet.HandlerInterceptor
как этот:
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 {
}
}
Наконец, добавьте эти строки в свой applicationContext.xml
:
<mvc:interceptors>
<bean class="path.to.my.just.created.UserContextInterceptor" />
</mvc:interceptors>
И, конечно же, заставьте ваши контроллеры реализовывать ваши AbstractController
,
Вот! Вам не нужно указывать ни request
ни ваш model
в ваших параметрах методов контроллеров больше:) Я не совсем уверен в полезности этого трюка, но да. Если это может сделать маниакальных разработчиков счастливее:)
Тем не менее, открыт для более простых решений.