190317-Spring MVC之基於java config無xml配置的web應用構建
前一篇博文講了SpringMVC+web.xml的方式建立web應用,用過SpringBoot的童鞋都知道,早就沒有xml什麼事情了,其實Spring 3+, Servlet 3+的版本,就已經支援java config,不用再寫xml;本篇將介紹下,如何利用java config取代xml配置
本篇博文,建議和上一篇對比看,貼出上一篇地址
I. Web構建
1. 專案依賴
對於依賴這一塊,和前面一樣,不同的在於java config 取代 xml
<artifactId>200-mvc-annotation</artifactId> <packaging>war</packaging> <properties> <spring.version>5.1.5.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty.aggregate</groupId> <artifactId>jetty-all</artifactId> <version>9.2.19.v20160908</version> </dependency> </dependencies> <build> <finalName>web-mvc</finalName> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.12.RC2</version> <configuration> <httpConnector> <port>8080</port> </httpConnector> </configuration> </plugin> </plugins> </build>
細心的童鞋會看到,依賴中多了一個jetty-all,後面測試篇幅會說到用法
2. 專案結構
第二節依然放上專案結構,在這裡把xml的結構也截進來了,對於我們的示例demo而言,最大的區別就是沒有了webapp,更沒有webapp下面的幾個xml配置檔案
3. 配置設定
現在沒有了配置檔案,我們的配置還是得有,不然web容器(如tomcat)怎麼找到DispatchServlet呢
a. DispatchServlet 宣告
同樣我們需要乾的第一件事情及時宣告DispatchServlet,並設定它的應用上下文;可以怎麼用呢?從官方找到教程
The DispatcherServlet, as any Servlet, needs to be declared and mapped according to the Servlet specification by using Java configuration or in web.xml. In turn, the DispatcherServlet uses Spring configuration to discover the delegate components it needs for request mapping, view resolution, exception handling
上面的解釋,就是說下面的程式碼和web.xml的效果是一樣一樣的
public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletCxt) { // Load Spring web application configuration AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext(); ac.register(AppConfig.class); ac.refresh(); // Create and register the DispatcherServlet DispatcherServlet servlet = new DispatcherServlet(ac); ServletRegistration.Dynamic registration = servletCxt.addServlet("mvc-dispatcher", servlet); registration.setLoadOnStartup(1); registration.addMapping("/*"); } }
當然直接實現介面的方式有點粗暴,但是好理解,上面的程式碼和我們前面的web.xml效果一樣,建立了一個DispatchServlet, 並且綁定了url命中規則;設定了應用上下文 AnnotationConfigWebApplicationContext
這個上下文,和我們前面的配置檔案 mvc-dispatcher-servlet
有點像了;如果有興趣看到專案原始碼的同學,會發現用的不是上面這個方式,而是及基礎介面 AbstractDispatcherServletInitializer
public class MyWebApplicationInitializer extends AbstractDispatcherServletInitializer { @Override protected WebApplicationContext createRootApplicationContext() { return null; } @Override protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); //applicationContext.setConfigLocation("com.git.hui.spring"); applicationContext.register(RootConfig.class); applicationContext.register(WebConfig.class); return applicationContext; } @Override protected String[] getServletMappings() { return new String[]{"/*"}; } @Override protected Filter[] getServletFilters() { return new Filter[]{new HiddenHttpMethodFilter(), new CharacterEncodingFilter()}; } }
看到上面這段程式碼,這個感覺就和xml的方式更像了,比如Servlet應用上下文和根應用上下文
說明
上面程式碼中增加的Filter先無視,後續會有專文講什麼是Filter以及Filter可以怎麼用
b. java config
前面定義了DispatchServlet,接下來對比web.xml就是需要配置掃描並註冊bean了,本文基於JavaConfig的方式,則主要是藉助 @Configuration
註解來宣告配置類(這個可以等同於一個xml檔案)
前面的程式碼也可以看到,上下文中註冊了兩個Config類
RootConfig定義如下,注意下註解 @ComponentScan
,這個等同於 <context:component-sca/>
,指定了掃描並註冊啟用的bean的包路徑
@Configuration @ComponentScan(value = "com.git.hui.spring") public class RootConfig { }
另外一個WebConfig的作用則主要在於開啟WebMVC
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { }
4. 例項程式碼
例項和上一篇一樣,一個普通的Server Bean和一個Controller
@Component public class PrintServer { public void print() { System.out.println(System.currentTimeMillis()); } }
一個提供rest服務的HelloRest
@RestController public class HelloRest { @Autowired private PrintServer printServer; @GetMapping(path = "hello", produces="text/html;charset=UTF-8") public String sayHello(HttpServletRequest request) { printServer.print(); return "hello, " + request.getParameter("name"); } @GetMapping({"/", ""}) public String index() { return UUID.randomUUID().toString(); } }
5. 測試
測試依然可以和前面一樣,使用jetty來啟動,此外,介紹另外一種測試方式,也是jetty,但是不同的是我們直接寫main方法來啟動服務
public class SpringApplication { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler handler = new ServletContextHandler(); // 伺服器根目錄,類似於tomcat部署的專案。 完整的訪問路徑為ip:port/contextPath/realRequestMapping //ip:port/專案路徑/api請求路徑 handler.setContextPath("/"); AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(); applicationContext.register(WebConfig.class); applicationContext.register(RootConfig.class); //相當於web.xml中配置的ContextLoaderListener handler.addEventListener(new ContextLoaderListener(applicationContext)); //springmvc攔截規則 相當於web.xml中配置的DispatcherServlet handler.addServlet(new ServletHolder(new DispatcherServlet(applicationContext)), "/*"); server.setHandler(handler); server.start(); server.join(); } }
測試示意圖如下
6. 小結
簡單對比下xml的方式,會發現java config方式會清爽很多,不需要多個xml配置檔案,維持幾個配置類,加幾個註解即可;當然再後面的SpringBoot就更簡單了,幾個註解了事,連上面的兩個Config檔案, ServletConfig都可以省略掉
另外一個需要注意的點就是java config的執行方式,在servlet3之後才支援的,也就是說如果用比較老的jetty是起不來的(或者無法正常訪問web服務)
II. 其他
- 系列博文
web系列:
mvc應用搭建篇:
0. 專案
- 工程: spring-boot-demo
- 專案: https://github.com/liuyueyi/spring-boot-demo/blob/master/spring/200-mvc-annotation
1. 一灰灰Blog
- 一灰灰Blog個人部落格 https://blog.hhui.top
- 一灰灰Blog-Spring專題部落格 http://spring.hhui.top
一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 宣告
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址:小灰灰Blog
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰blog
知識星球
打賞 如果覺得我的文章對您有幫助,請隨意打賞。