Spring MVC 自定义converter疑虑

1.SpringMVC自定义的converter的触发时机是什么时候?换句话说Spring是怎么知道某个参数该进入到自定义的converter里的?

2.
如下,我定义一个简单的Person类,

import lombok.Data;

@Data
public class Person {
    private String username;
    private String passwd;
}

定义一个自定义conventer,

public class StringToPersonConverter implements Converter<String,Person> {
    public Person convert(String source) {
        Person p1 = new Person();
        if(source != null){
            String[] items = source.split(":");
            p1.setUsername(items[0]);
            p1.setPasswd(items[1]);
        }
        return p1;
    }
}

controller这样写:

@Controller
    @CrossOrigin(origins = "*", maxAge = 3600)
    @RequestMapping("/customer")
    public class CustomerController {
        @Autowired
        private CustomerRepository repository;
    
        /**
         * 初始化数据
         */
        @RequestMapping("/index")
        public void index(Person person) {
            System.out.println(person);
        }
    }

然后前端发起这样的请求,http://localhost:8080/customer/index?person=tom:111,
能够成功走到conventer的逻辑,将对应的字符串转成person对象,现在我将controller里的index方法的参数:
Person person变成String person,发现就不会走自定义converter的逻辑,Spring是怎么判断该不该进入我的自定义的converter中的,根据Person这个类型吗? 源码是在哪里? 类似于自定义的Resolver,我可以在:

clipboard.png
这里很清晰的看到,SpringMVC是怎么去调用我们的自定义的Resolver的。那么对应的converter呢

阅读 3.2k
1 个回答
新手上路,请多包涵

解析方法入参的位置:org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues
稍微解释下:当前对象为ServletInvocableHandlerMethod,其argumentResolvers也就是RequestMappingHandlerAdapter的argumentResolvers. 你说的判断支持Person 、不支持String,是因为有这样一个方法入参分析器ServletModelAttributeMethodProcessor,你看下他父类的supportsParameter方法,String他是不支持的. Spring所默认注册的argumentResolvers也只有ServletModelAttributeMethodProcessor可以解析自定义的Java类型(不包括StringDate这些). 判断支持之后才会调用解析器去执行resolveArgument方法 至于解析是怎么走到converter,org.springframework.beans.TypeConverterDelegate#convertIfNecessary这个是核心方法,简单来说是调用ConversionService的converter进行转换,这里的conversionService就是RequestMappingHandlerAdapter的conversionService.
一两句说不清楚,希望博客可以帮到你 https://www.cnblogs.com/lvbin...

private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
            Object... providedArgs) throws Exception {

        MethodParameter[] parameters = getMethodParameters();
        Object[] args = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            MethodParameter parameter = parameters[i];
            parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
            GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
            args[i] = resolveProvidedArgument(parameter, providedArgs);
            if (args[i] != null) {
                continue;
            }
            if (this.argumentResolvers.supportsParameter(parameter)) {
                try {
                    args[i] = this.argumentResolvers.resolveArgument(
                            parameter, mavContainer, request, this.dataBinderFactory);
                    continue;
                }
                catch (Exception ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
                    }
                    throw ex;
                }
            }
            if (args[i] == null) {
                String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
                throw new IllegalStateException(msg);
            }
        }
        return args;
    }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题