Spring MVC : Common param in all requests

£可爱£侵袭症+ 提交于 2020-04-09 18:24:46

问题


I have many controllers in my Spring MVC web application and there is a param mandatoryParam let's say which has to be present in all the requests to the web application.

Now I want to make that param-value available to all the methods in my web-layer and service-layer. How can I handle this scenario effectively?

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

    回答1:


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

    myMethod() will be called for every request to any controller in the net.myproject.mypackage package. (Before Spring 4.0, you could not define a package. @ControllerAdvice applied to all controllers).

    See the Spring Reference for more details on @ModelAttribute methods.




    回答2:


    Thanks Alexey for leading the way.

    His solution is:

    • Add a @ControllerAdvice triggering for all controllers, or selected ones
    • This @ControllerAdvice has a @PathVariable (for a "/path/{variable}" URL) or a @RequestParam (for a "?variable=..." in URL) to get the ID from the request (worth mentioning both annotations to avoid blind-"copy/past bug", true story ;-) )
    • This @ControllerAdvice then populates a model attribute with the data fetched from database (for instance)
    • The controllers with uses @ModelAttribute as method parameters to retrieve the data from the current request's model

    I'd like to add a warning and a more complete example:

    Warning: see JavaDoc for ModelAttribute.name() if no name is provided to the @ModelAttribute annotation (better to not clutter the code):

    The default model attribute name is inferred from the declared attribute type (i.e. the method parameter type or method return type), based on the non-qualified class name: e.g. "orderAddress" for class "mypackage.OrderAddress", or "orderAddressList" for "List<mypackage.OrderAddress>".

    The complete example:

    @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");
        }
    
    }
    

    To continue about the warning, requests are declaring the parameter "@ModelAttribute ParentDTO parent": the name of the model attribute is not the variable name ("parent"), nor the original "parentId", but the classname with first letter lowerified: "parentDTO", so we have to be careful to use model.addAttribute("parentDTO"...)

    Edit: a simpler, less-error-prone, and more complete example:

    @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");
        }
    
    }
    


    来源:https://stackoverflow.com/questions/24758969/spring-mvc-common-param-in-all-requests

  • 易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!