【问题标题】:Spring MVC : Common param in all requestsSpring MVC:所有请求中的公共参数
【发布时间】:2014-07-15 13:04:31
【问题描述】:

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

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

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

  • ... controllerMethod(@RequestParam String 强制参数, ...)
  • 然后通过调用它的方法将此参数传递给服务层
  • 【问题讨论】:

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


      【解决方案1】:
      @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

      【讨论】:

      • 是否可以使用该方法设置控制器的content-type、encoding header等?
      【解决方案2】:

      感谢 Alexey 带路。

      他的解决办法是:

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

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

      警告:如果没有为 @ModelAttribute 注释提供名称,请​​参阅 JavaDoc for 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”,而是带有 first 的类名字母小写:“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");
          }
      
      }
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      相关资源
      最近更新 更多