11

我的 Spring MVC Web 应用程序中有许多控制器,mandatoryParam假设有一个参数必须存在于对 Web 应用程序的所有请求中。

现在我想让这个参数值可用于我的 web 层和服务层中的所有方法。我怎样才能有效地处理这种情况?

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

  • ... 控制器方法(@RequestParam 字符串强制参数,...)
  • 然后通过调用它的方法将此参数传递给服务层

  • 4

    2 回答 2

    9
    @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

    于 2014-07-15T13:10:56.757 回答
    4

    感谢 Alexey 带路。

    他的解决方案是:

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

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

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

    默认模型属性名称是从声明的属性类型(即方法参数类型或方法返回类型)中推断出来的,基于非限定类名称:例如,类“mypackage.OrderAddress”的“orderAddress”,或“orderAddressList” “列表<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");
        }
    
    }
    
    于 2018-08-30T15:14:56.380 回答