简体   繁体   English

Spring PathVariable在外部使用

[英]Spring PathVariable used outside

I have Spring rest controller that provides operations on Project entity. 我有Spring Rest控制器,可提供对Project实体的操作。 All methods use same entity accessing code. 所有方法都使用相同的实体访问代码。 I don't want to copy&paste @PathVariable parameters in all methods, so I've made something like this. 我不想在所有方法中都复制并粘贴@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()

}

Is it possible to autowire path variables into controller by annotation so I don't have to split request path and get parts of it from request string for project() method? 是否可以通过注释将路径变量自动连接到控制器中,所以我不必拆分请求路径并从project()方法的请求字符串中获取部分内容?

In order to do custom binding from request you've got to implement your own HandlerMethodArgumentResolver (it's a trivial example without checking if path variables actually exist and it's also global, so every time you will try to bind to Project class this argument resolver will be used): 为了从请求中进行自定义绑定,您必须实现自己的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;
    }
}

and register it using WebMvcConfigurerAdapter : 并使用WebMvcConfigurerAdapter进行注册:

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

In your controller you have to put Project as a method argument, but do not annotate it with @PathVariable: 在你的控制器,你必须把项目作为方法的参数,但 @PathVariable标注为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM