Spring MVC:所有请求中的公共参数

时间:2014-07-15 13:04:32

标签: spring spring-mvc http-request-parameters

我的Spring MVC Web应用程序中有很多控制器,并且有一个参数mandatoryParam让我们说它必须存在于Web应用程序的所有请求中。

现在我想让这个param-value可用于我的web层和服务层中的所有方法。我该如何有效地处理这种情况?

目前我正以这种方式处理它:

  • ... controllerMethod( @RequestParam String mandatoryParam ,...)
  • 然后通过调用它的方法将该参数传递给服务层

  • 2 个答案:

    答案 0 :(得分:6)

    @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应用于所有控制器。)

    有关@ModelAttribute方法的详细信息,请参阅Spring Reference

    答案 1 :(得分:1)

    感谢Alexey的带领。

    他的解决方案是:

    • 为所有控制器或选定的控制器添加@ControllerAdvice触发器
    • 此@ControllerAdvice具有@PathVariable(用于“ / path / {variable}” URL)或@RequestParam(用于URL中的“?variable = ...”),以从请求中获取ID(值提及这两个注释以避免盲目的“复制/粘贴错误”,真实的故事;-))
    • 然后,此@ControllerAdvice使用从数据库中获取的数据填充模型属性(例如)
    • 使用@ModelAttribute作为方法参数的控制器从当前请求的模型中检索数据

    我想添加警告和更完整的示例:

    警告:如果没有为@ModelAttribute批注提供名称(最好不要使代码混乱),请参见JavaDoc中的ModelAttribute.name():

      

    默认模型属性名称是从声明的   属性类型(即方法参数类型或方法返回类型),   基于不合格的类名:   例如类“ mypackage.OrderAddress”的“ orderAddress”,   或“ List ”的“ orderAddressList”。

    完整的示例:

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