爲了在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啓動成功