如何将 HttpServletRequest 参数添加到复杂的 RestController bean?
How to add HttpServletRequest param to complex RestController bean?
我有一个包含其余参数的复杂 bean,例如:
public class MyRestParams {
private HttpServletRequest req;
private @NotBlank String name;
//getter, setter
}
用法:
@RestController
@RequestMapping("/xml")
public class MyServlet {
@RequestMapping(value = "/")
public void getTest(@Valid MyRestParams p) {
Sysout(p.getName()); //works when invoked with /xml?name=test
Sysout(p.getReq()); //always null
}
}
问题:HttpServletRequest
始终为空。不能在 bean 本身中添加此参数吗?
您可以为 HandlerMethodArgumentResolver
提供一个实现来解决您的 MyRestParams
:
public class MyRestParamsArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(MyRestParams.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
MyRestParams restParam = new MyRestParams();
restParam.setReq((HttpServletRequest) webRequest.getNativeRequest());
return restParam;
}
}
然后在您的WebMvcConfigurerAdapter
中注册:
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new MyRestParamsArgumentResolver());
}
}
当使用那种形式的方法签名时 Spring 将使用您的 bean 作为模型属性。 Spring 将使用 WebDataBinder(例如 ServletRequestDataBinder)将您的请求参数绑定到匹配名称的 bean 属性。
因为没有与您的 bean 匹配的请求参数 属性 req 永远不会设置该字段。即使您的请求中存在名为 req 的请求参数,它也不会转换为 HttpServletRequest。
要接收实际请求,请将 HttpServletRequest 类型的参数添加到您的处理程序方法
@RequestMapping(value = "/")
public void getTest(@Valid MyRestParams p , HttpServletRequest request) {
Sysout(p.getName()); //works when invoked with /xml?name=test
Sysout(request); //always null
}
如果您不想将自己绑定到 Servlet,则可以使用 WebRequest 类型的参数 API。
我有一个包含其余参数的复杂 bean,例如:
public class MyRestParams {
private HttpServletRequest req;
private @NotBlank String name;
//getter, setter
}
用法:
@RestController
@RequestMapping("/xml")
public class MyServlet {
@RequestMapping(value = "/")
public void getTest(@Valid MyRestParams p) {
Sysout(p.getName()); //works when invoked with /xml?name=test
Sysout(p.getReq()); //always null
}
}
问题:HttpServletRequest
始终为空。不能在 bean 本身中添加此参数吗?
您可以为 HandlerMethodArgumentResolver
提供一个实现来解决您的 MyRestParams
:
public class MyRestParamsArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(MyRestParams.class);
}
@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
MyRestParams restParam = new MyRestParams();
restParam.setReq((HttpServletRequest) webRequest.getNativeRequest());
return restParam;
}
}
然后在您的WebMvcConfigurerAdapter
中注册:
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new MyRestParamsArgumentResolver());
}
}
当使用那种形式的方法签名时 Spring 将使用您的 bean 作为模型属性。 Spring 将使用 WebDataBinder(例如 ServletRequestDataBinder)将您的请求参数绑定到匹配名称的 bean 属性。
因为没有与您的 bean 匹配的请求参数 属性 req 永远不会设置该字段。即使您的请求中存在名为 req 的请求参数,它也不会转换为 HttpServletRequest。
要接收实际请求,请将 HttpServletRequest 类型的参数添加到您的处理程序方法
@RequestMapping(value = "/")
public void getTest(@Valid MyRestParams p , HttpServletRequest request) {
Sysout(p.getName()); //works when invoked with /xml?name=test
Sysout(request); //always null
}
如果您不想将自己绑定到 Servlet,则可以使用 WebRequest 类型的参数 API。