-
Notifications
You must be signed in to change notification settings - Fork 38.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spring MVC custom argument resolvers order #23043
Comments
The Javadoc is addressing that bit:
I don't know if we should update the doc or slightly change the registration order. Before doing any of that, I'd like to know what type of argument resolver you're registering and to what types it's supposed to react to. This would help us figure out how specific it is and if it should be done via the configurer or the handler adapter directly. Could you provide some background? (what are you trying to achieve, a code snippet showing your custom resolver). Thanks! |
I have a subclass of javax.servlet.http.HttpServletRequestWrapper public class YJJHttpRequest extends HttpRequestWrapper {
public YJJHttpRequest(HttpServletRequest request) {
super(request);
}
public KdUser getKdUser() throws ValidateTokenException {
.....
return kdUser;
} there is a HandlerMethodArgumentResolver Implementation class public class HttpRequestHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver,{
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
return (AdminHttpRequest.class.isAssignableFrom(paramType) ||
YJJHttpRequest .class.isAssignableFrom(paramType)
|| CommonHttpRequest.class.isAssignableFrom(paramType));
}
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
Class<?> paramType = parameter.getParameterType();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
if (AdminHttpRequest.class.isAssignableFrom(paramType)) {
return new AdminHttpRequest(request);
} else if (YJJHttpRequest.class.isAssignableFrom(paramType)) {
return new YJJHttpRequest(request);
} else {
return new CommonHttpRequest(request);
}
} finally I want to define this parameter type in Controller's method like this @RequestMapping(value = "cancelFavorPriFund")
public void cancelFavorPriFund(YJJHttpRequest request, HttpResponseWrapper response) {
KdUser kdUser = request.getKdUser();
JSONArray crmCodeArray = request.getJSONArrayQuietly("crmCode");
.....
response.outputSuccess();
} In fact wil caught a exception : ,I found that ServletRequestMethodArgumentResolver have a high priority to handle it ,and thus mine HttpRequestHandlerMethodArgumentResolver have no chance to executed ,so throwed this exception from ServletRequestMethodArgumentResolver ,because ServletRequestMethodArgumentResolver and HttpRequestHandlerMethodArgumentResolver supports the same Parameter Type . in other words: when default Argument Resolvers and custom Argument Resolvers supports same parameter type , custom argument resolver always no chance to executed .
|
Similar request and discussion under #21874. Changing the order isn't an option but we can check explicitly that the request is either |
In the end, I found an workaround. But I don't think it's the best public class HttpRequestHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver, InitializingBean {
@Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
public void afterPropertiesSet() throws Exception {
List<HandlerMethodArgumentResolver> argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();
List<HandlerMethodArgumentResolver> newArgumentResolvers = new LinkedList<>();
newArgumentResolvers.add(this);
newArgumentResolvers.addAll(argumentResolvers);
requestMappingHandlerAdapter.setArgumentResolvers(Collections.unmodifiableList(newArgumentResovers));
} |
Okay but just to be clear, the change I suggested in |
A little bit more info in which cases this might be usefull. I use the same techinque(upper sample, with MockMvc will still suffer from same ordering problem even if initialized as @Bean
MockMvc mockMvc(SampleController sampleController, CustomResponseReturnValueHandler customResponseReturnValueHandler) {
return MockMvcBuilders.standaloneSetup(sampleController)
.setCustomReturnValueHandlers(customResponseReturnValueHandler)
.build();
} I may miss something, it sounds like common problem but I didn't find builtin/existing solution. What could be done in such case is ability to change order or to intoduce customization of |
When I want to custom one argument Resolver in :
WebMvcConfigurerAdapter#addArgumentResolvers,and try to override parameter type of ServletRequest ; but I found it that caught low priority after ServletRequestMethodArgumentResolver (same parameter type of ServletRequest) ;
review source RequestMappingHandlerAdapter#getDefaultArgumentResolvers discover below :
I think that custom arguments resolver should be before the default argument ,so that can get highly priority to handle my logic;
Thanks .
The text was updated successfully, but these errors were encountered: