Может ли Spring MVC вызывать @ModelAttribute после @RequestMapping?

У меня есть такой контроллер:

@Controller
public class HomeController {

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String update(@RequestParam("user") User user, ModelMap model){
        SaveUserToDatabase(user);
        return "index";
    }

    @ModelAttribute("user")
    String getUser() {
        return LoadCurrentUserFromDataBase();
    }
}

Короче говоря, мои представления будут отображать user почти в каждом действии в HomeController, но я не хочу кодировать:

model.addAttribute("user", LoadCurrentUserFromDataBase())

во всех действиях, вместо этого я ищу способ, как @ModelAttribute, чтобы показать user все мои взгляды.

Однако, согласно документации, методы @ModelAttribute в контроллере вызываются до методов @RequestMapping в том же контроллере.

Что касается моего кода, то getUser вызывается перед update, но я хотел бы получить обновленного пользователя.

Есть ли способ показать атрибут user после действий без явного вызова model.addAttribute в каждом действии?


person marstone    schedule 26.07.2013    source источник


Ответы (2)


Каждый раз, когда вы делаете POST, делайте перенаправление. Таким образом, ваш метод POST будет отвечать только за обновление данных, а обновленные данные будут загружены целевым контроллером.

Таким образом, в этом случае метод update() будет перенаправлять на другой контроллер, который вызовет метод getUser() перед своим методом GET.

person WilQu    schedule 26.07.2013

Решение Post/redirect/GET допустимо, если оно работает для вас.

Однако у меня была аналогичная ситуация, когда у меня были атрибуты модели, которые должны были быть записаны всеми моими контроллерами после обработки запроса (в основном информация об отслеживании). Что я сделал, так это зарегистрировал пользовательский интерфейс (например, AdditionalModelDataSupplier), который я применяю ко всем контроллерам, которым необходимо предоставить дополнительные данные. Интерфейс будет иметь такой метод:

void provideAdditionalData(Model model, HttpServletRequest request);

Теперь я написал перехватчик, который в методе postHandle проверяет бин Controller на наличие этого интерфейса и вызывает этот метод:

@Override
public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler,
        final ModelAndView modelAndView) throws Exception {

    AdditionalModelDataSupplier modelDataSupplier = findAdditionalModelDataSupplier(handler);
    if (modelDataSupplier != null) {
        final ModelMap modelMap = modelAndView.getModelMap();
        final Model targetModel;
        if (modelMap instanceof Model) {
            targetModel = (Model) modelMap;
        } else {

            // the modelmap doesn't implement model, so we need to provide a wrapper view
            targetModel = new ForwardingModel(modelMap);
        }

        modelDataSupplier.provideAdditionalData(targetModel, request);
    }
}
@Nullable
private static AdditionalModelDataSupplier findAdditionalModelDataSupplier(final Object handler) {
    if (handler instanceof AdditionalModelDataSupplier) {
        return (AdditionalModelDataSupplier) handler;
    }

    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Object bean = handlerMethod.getBean();
        if (bean instanceof AdditionalModelDataSupplier) {
            return (AdditionalModelDataSupplier) bean;
        }
    }

    return null;
}

(упомянутый выше класс ForwardingModel создать просто, он просто делегирует все ModelMap)

person Sean Patrick Floyd    schedule 26.07.2013