【问题标题】:Spring PathVariable used outside外部使用的 Spring PathVariable
【发布时间】:2014-11-17 18:19:11
【问题描述】:

我有提供对Project 实体的操作的 Spring 休息控制器。所有方法都使用相同的实体访问代码。我不想在所有方法中复制和粘贴@PathVariable 参数,所以我做了这样的事情。

@RestController
@RequestMapping("/projects/{userName}/{projectName}")
public class ProjectController {


  @Autowired
  ProjectService projectService;
  @Autowired
  protected HttpServletRequest context;


  protected Project project() {
    // get {userName} and {projectName} path variables from request string
    String[] split = context.getPathInfo().split("/");
    return projectService.getProject(split[2], split[3]);
  }


  @RequestMapping(method = GET)
  public Project get() {
    return project();
  }


  @RequestMapping(method = GET, value = "/doSomething")
  public void doSomething() {
    Project project = project();
    // do something with project
  }

  // more @RequestMapping methods using project()

}

是否可以通过注释将路径变量自动连接到控制器中,这样我就不必拆分请求路径并从project() 方法的请求字符串中获取其中的一部分?

【问题讨论】:

标签: java spring spring-mvc controller annotations


【解决方案1】:

为了从请求中进行自定义绑定,您必须实现自己的HandlerMethodArgumentResolver(这是一个简单的示例,无需检查路径变量是否实际存在并且它也是全局的,因此每次您都会尝试绑定到 Project 类将使用此参数解析器):

class ProjectArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType().equals(Project.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Map<String, String> uriTemplateVars = (Map<String, String>) webRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);

        return getProject(uriTemplateVars.get("userName"), uriTemplateVars.get("projectName"));
    }

    private Project getProject(String userName, String projectName) {
        // replace with your custom Project loading logic 
        Project project = new Project(userName, projectName); 

        return project;
    }
}

并使用WebMvcConfigurerAdapter注册它:

@Component
public class CustomWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new ProjectArgumentResolver());
    }
}

在您的控制器中,您必须将 Project 作为方法参数,但请不要使用 @PathVariable 对其进行注释:

@Controller
@RequestMapping("/projects/{userName}/{projectName}")
public class HomeController {
    @RequestMapping(method = RequestMethod.GET)
    public void index(Project project){
        // do something
    }
}

【讨论】:

  • 我创建了很多 ArgumentResolver,我知道如何使用它们。但问题是是否可以使用 PathVariable 省略方法的参数。
  • 但是你为什么要这样做呢?项目是您的方法参数,为什么要隐藏它?
  • 我很确定你会这样问。 :) 我的 SO 问题不是“我应该怎么做”,而是“有可能”。将其命名为实验或学习问题。示例只是为了说明我在想什么样的事情。
猜你喜欢
  • 2015-08-28
  • 2013-11-17
  • 1970-01-01
  • 2012-02-23
  • 2012-01-07
  • 2014-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多