为了在Spring源码项目中调试SpringMVC代码,使用Tomcat的插件比较方便,那么须要本身模拟编写一个相似SpringBoot的功能:启动Spring应用内嵌Tomcat并作好关联。若是还没构建好一个完整的Spring源码运行环境请参考:Spring5 源码分析--引导片(构建Spring源码运行环境)java
为何要搞这么麻烦喃???由于我是创建的一个普通Java工程,根本web.xml文件,所以须要写代码给Tomcat添加Context\Servlet、与Spring web 上下文绑定。web
要完全弄明白这部分代码,须要对Tomcat和Spring有比较深刻的理解,能够去看看前面的Spring和Tomcat源码分析spring
先在Spring项目中新建一个普通Java工程,注意是用Gradle构建apache
其余步骤省略,只贴出build.gradle文件json
plugins { id 'java' } group 'org.springframework' version '5.2.0.BUILD-SNAPSHOT' sourceCompatibility = 1.8 dependencies { compile project(":spring-context") compile project(":spring-webmvc") testCompile group: 'junit', name: 'junit', version: '4.12' compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: '8.5.49' compile group: 'org.projectlombok', name: 'lombok', version: '1.18.10' compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8' compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.8' }
为何要导入jackson的东西,由于我要将Controller返回的对象转换为json串输出浏览器
上代码:tomcat
模拟Springboot启动自带Tomcat容器mvc
@Configuration @ComponentScan("com.jv.webmvc") public class WebMvcMain{ public static void main(String[] args) { try { //实例化一个Spring web 上下文 AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); ac.register(WebMvcMain.class); ac.refresh(); //实例化Spring的DispatcherServlet DispatcherServlet与上下文绑定 DispatcherServlet dispatcherServlet = new DispatcherServlet(ac); //实例化Tomcat Tomcat tomcat = new Tomcat(); tomcat.setPort(8080); //Tomcat添加Servlet Context context = tomcat.addContext("/", "f:\\data\\spring-tomcat\\app"); Tomcat.addServlet(context, "st", dispatcherServlet); context.addServletMapping("/", "st"); //启动Tomcat tomcat.start(); tomcat.getServer().await(); }catch (Exception e){ e.printStackTrace(); } } }
下面这个类是完成HTTPMessageConverter注册(也许有朋友会问为何不用WebMvcConfigure接口重写它的方法完成自定义Converter添加。。。由于我试了不行,我猜想多是由于没用使用@EnableWebMvc)app
@Component public class MyHttpMessageConverterProcessor implements BeanPostProcessor{ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(beanName.equals("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter")){ List<HttpMessageConverter<?>> messageConverters = ((RequestMappingHandlerAdapter) bean).getMessageConverters(); messageConverters.add(new MappingJackson2HttpMessageConverter()); } return bean; } }
User对象源码分析
@Setter @Getter @ToString public class User { public User(){} public User(String userName,Integer age){ this.userName = userName; this.age = age; } private String userName; private Integer age; }
UserController
@RestController public class UserController { private User user = new User("Messi",33); @RequestMapping("/user") public User queryAllUser(){ System.out.println(user); return user; } }
注意,其余要被扫描到的类必须都在com.jv.webmvc目录及其子目录当中
完成上面的代码,启动SpringMVC应用
Tomcat启动成功
浏览器访问:http://localhost:8080/user