Как факторизовать модель в контроллерах?

Используя 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 в ваших параметрах методов контроллеров больше:) Я не совсем уверен в полезности этого трюка, но да. Если это может сделать маниакальных разработчиков счастливее:)

Тем не менее, открыт для более простых решений.

Другие вопросы по тегам