Spring MVC: общий параметр во всех запросах

У меня есть много контроллеров в моем веб-приложении Spring MVC, и есть параметр mandatoryParam, скажем, который должен присутствовать во всех запросах к веб-приложению.

Теперь я хочу сделать это значение параметра доступным для всех методов моего веб-уровня и сервисного уровня. Как я могу эффективно справиться с этим сценарием?

Currently I am handling it in this way:

  • ... controllerMethod(@RequestParam String mandatoryParam, ...)
  • and, then passing this param to service layer by calling it's method


  • person Yatendra    schedule 15.07.2014    source источник


    Ответы (2)


    @ControllerAdvice("net.myproject.mypackage")
    public class MyControllerAdvice {
    
        @ModelAttribute
        public void myMethod(@RequestParam String mandatoryParam) {
    
            // Use your mandatoryParam
        }
    }
    

    myMethod() будет вызываться для каждого запроса к любому контроллеру в пакете net.myproject.mypackage. (До Spring 4.0 вы не могли определить пакет. @ControllerAdvice применялось ко всем контроллерам).

    См. Spring. Ссылка для более подробной информации о @ModelAttribute методах.

    person Alexey    schedule 15.07.2014
    comment
    Можно ли использовать этот метод для установки типа содержимого, заголовков кодирования и т. д. контроллера? - person Tobia; 18.12.2015

    Спасибо Алексею за наводку.

    Его решение:

    • Добавьте срабатывание @ControllerAdvice для всех или выбранных контроллеров.
    • Этот @ControllerAdvice имеет @PathVariable (для URL-адреса "/path/{variable}") или @RequestParam (для "?variable=..." в URL-адресе), чтобы получить идентификатор из запроса (стоит упомянуть обе аннотации чтобы избежать слепого "копирования/прошлой ошибки", реальная история ;-))
    • Затем этот @ControllerAdvice заполняет атрибут модели данными, полученными из базы данных (например)
    • Контроллеры с использованием @ModelAttribute в качестве параметров метода для извлечения данных из модели текущего запроса.

    Я хотел бы добавить предупреждение и более полный пример:

    Предупреждение: см. JavaDoc для ModelAttribute.name(), если в аннотации @ModelAttribute не указано имя (лучше не загромождать код):

    Имя атрибута модели по умолчанию выводится из объявленного типа атрибута (т. е. типа параметра метода или типа возвращаемого значения метода) на основе неполного имени класса: например. «orderAddress» для класса «mypackage.OrderAddress» или «orderAddressList» для «List‹mypackage.OrderAddress›».

    Полный пример:

    @ControllerAdvice
    public class ParentInjector {
    
        @ModelAttribute
        public void injectParent(@PathVariable long parentId, Model model) {
            model.addAttribute("parentDTO", new ParentDTO(parentId, "A faked parent"));
        }
    
    }
    
    @RestController
    @RequestMapping("/api/parents/{parentId:[0-9]+}/childs")
    public class ChildResource {
    
        @GetMapping("/{childId:[0-9]+}")
        public ChildDTO getOne(@ModelAttribute ParentDTO parent, long childId) {
            return new ChildDTO(parent, childId, "A faked child");
        }
    
    }
    

    Чтобы продолжить предупреждение, запросы объявляют параметр «@ModelAttribute ParentDTO parent»: имя атрибута модели — это не имя переменной («parent») и не исходный «parentId», а имя класса с заниженной первой буквой: "parentDTO", поэтому мы должны быть осторожны при использовании model.addAttribute("parentDTO"...)

    Изменить: более простой, менее подверженный ошибкам и более полный пример:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @RestController
    public @interface ProjectDependantRestController {
    
        /**
         * The value may indicate a suggestion for a logical component name,
         * to be turned into a Spring bean in case of an autodetected component.
         *
         * @return the suggested component name, if any
         */
        String value() default "";
    
    }
    
    @ControllerAdvice(annotations = ParentDependantRestController.class)
    public class ParentInjector {
    
        @ModelAttribute
        public ParentDTO injectParent(@PathVariable long parentId) {
            return new ParentDTO(parentId, "A faked parent");
        }
    
    }
    
    @ParentDependantRestController
    @RequestMapping("/api/parents/{parentId:[0-9]+}/childs")
    public class ChildResource {
    
        @GetMapping("/{childId:[0-9]+}")
        public ChildDTO getOne(@ModelAttribute ParentDTO parent, long childId) {
            return new ChildDTO(parent, childId, "A faked child");
        }
    
    }
    
    person Sebien    schedule 30.08.2018
    comment
    Теперь возникает проблема с документированием этого Swagger. Не выполнимо. Я создал задачу: github.com/springfox/springfox/issues/2653 - person Sebien; 31.08.2018