原本是爲了探究一些功能性問題,須要一套完整的項目架構,本覺得SSM用過那麼多了,輕鬆搭建不在話下,可是過程當中仍是遇到一些問題,踩到一些不曾料想的坑。博文以搭建極簡架構爲目的,附帶一些關鍵闡述,既是備忘,也是分享。html
IDEA中用 Maven 的方式搭建 web 項目的時候若是你選擇了 web 項目骨架,那麼最終生成的項目目錄結構是很不標準的一個目錄結構,而若是不選擇 web 項目骨架,產生的項目目錄標準但卻少了 web 目錄。固然,基於IDEA的強大,確定不至於讓你手動去整理包結構,請按如下簡單步驟操做便可:前端
沒有選擇骨架的Maven項目結構以下——java
而後項目右鍵 Add Frameworks Support 添加 web 支持——mysql
一般的作法是須要在 web.xml 中配置 Spring 初始化上下文的監聽器 ContextLoaderListener 和 Spring MVC的核心 DispatcherServlet,它們會加載各自路徑中的xml配置文件來產生各自的上下文對象。不過博主並不想這麼作,而是採用純 Java 配置的方式,因此本項目示例中沒有 web.xml的存在。經過Java配置的方式,咱們須要兩個配置類,一個配置類擴展 WebApplicationInitializer 接口的派生類 AbstractAnnotationConfigDispatcherServletInitializer ,其會同時建立 ContextLoaderListener 和 DispatcherServlet 的上下文,並根據須要配置 DispatcherServlet 的映射路徑和相關配置類:web
public class BluesInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { //給定的Java 配置類將定義 ContextLoaderListener 上下文中的 bean 實例 本示例中沒有給出根配置類 protected Class<?>[] getRootConfigClasses() { return new Class[0]; } // 給定的Java 配置類將定義 DispatcherServlet 上下文的bean 實例 protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } // 配置一個或多個 映射路徑 protected String[] getServletMappings() { return new String[]{"/"}; } }
另外一個就是MVC的基礎配置類——spring
@Configuration @ComponentScan(basePackages = {"net"}) @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { //配置視圖解析器 @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/pages/"); resolver.setSuffix(".jsp"); return resolver; } /** * 經過繼承 WebMvcConfigurerAdapter 類的方式配置靜態資源請求 * 將對靜態資源的訪問交由容器中默認的 Servlet 處理 */ @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { /** 至關於 xml 配置中的 <mvc:default-servlet-handler /> 配置 */ configurer.enable(); } }
完成兩個配置類後其實Spring和Spring MVC就已經配置完了,你能夠編寫控制器作頁面跳轉測試,這裏限於篇幅博主再也不貼出。想要知道爲何能用以上的Java配置取代常常用的 web.xml中的配置 ,首先你必須得清楚 web.xml 中的 ContextLoaderListener 和 DispatcherServlet 的做用。關於這二者的深層理解,可參考一位博友的源碼分析,這裏博主仍是按照己的理解來敘述: sql
ContextLoaderListener 是Spring的一個監聽器,當其監聽到容器啓動會根據定義文件(能夠理解爲建立 bean 實例及維護bean依賴關係的圖紙,默認是WEB-INF下的applicationContext.xml文件)建立Spring的上行下對象,也即容器對象,有了該容器對象程序運行時才能從容器中獲取到bean; DispatcherServlet 本質就是一個Servlet ,因此,Servlet容器啓動時天然會將其初始化(<load-on-startup>配置爲正數),關鍵這傢伙是 Spring 的,功能很強大,也可以根據本身的 xml定義文件(默認 WEB-INF下的【servlet-name】-servlet.xml)產生一個上下文對象,這個上下文容器對象負責管理維護Spring MVC生態體系中的 控制器啊,視圖解析器,處理映射器等bean;這兩個容器對象有關係嗎,固然有關係,能夠粗淺的理解爲父子關係,前者是整個應用的根容器對象,是全局的,後者只是管理應用於Servlet相關組件。數據庫
而爲何擴展了AbstractAnnotationConfigDispatcherServletInitializer 類就能完成上述相同的功能呢?由於在Servlet 3.0 規範中,爲第三方組件提供了一個叫 ServletContainerInitializer 的接口用來作一些初始化相關的工做,第三方組件只要實現此接口就能夠完成本身的一些初始化操做。在Spring中提供的實現類叫 SpringServletContainerInitializer ,追蹤源碼,你能夠發現,真正的初始化配置實際上是交給 WebApplicationInitializer 接口的子類來完成的,而上面代碼中的 AbstractAnnotationConfigDispatcherServletInitializer 就是WebApplicationInitializer 接口的子類,因此,咱們能夠繼承該類,根據業務需求重寫相應的方法,來完成咱們初始化Spring 和Spring MVC 上下文的相關配置。至此,我想你應該能看懂上面的配置是什麼意思以及和web.xml中的配置的對應關係了。apache
持久層的整合無需多說,在資源文件夾下新建 spring-mybatis.xml 和 db.properties文件,依次配置鏈接數據庫的數據源(應該從 db.properties中獲取數據庫鏈接信息 )、生成SqlSession 的 SqlSessionFactory定義(其依賴於數據源和mapper.xml文件路徑)以及映射器配置類 MapperScannerConfigurer。db.propertie和spring-mybatis.xml 配置文件以下:json
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/sql_eve?useUnicode=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=123456
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!--加載數據庫配置文件 --> <context:property-placeholder location="classpath:db.properties"/> <!--配置數據源 這裏是配置的druid 鏈接池--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <!-- 配置初始化鏈接池大小設置 --> <property name="initialSize" value="1" /> <!--最小空閒鏈接數量,設 0 沒有限制 --> <property name="minIdle" value="1" /> <!--最大活動鏈接數量,設 0 沒有限制--> <property name="maxActive" value="5" /> <!--從池中獲取鏈接的最大等待時間,單位ms--> <property name="maxWait" value="10000" /> </bean> <!--配置 SqlSessionFactory 全局單例 一個數據庫應該只對應一個 SqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:mapper/*.xml"/> </bean> <!--配置 MapperScannerConfigurer 來配置映射器,經過掃描相應包下的接口生成動態代理對象交由Spring 管理--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="net.dao"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> </beans>
如今這個配置文件Spring容器是不知道的,須要在上面的Java配置類WebConfig上標註 @ImportResource("classpath:spring-mybatis.xml") 進行引入。而後,來一個mapper.xml配置示例:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="net.dao.ProductDao"> <select id="queryProducts" resultType="net.entity.Product"> select * from products </select> </mapper>
有時候咱們可能會將mapper.xml文件寫在dao下面的mapper包裏,可是在IDEA的Maven項目中,編譯器只會對java包下面.java文件進行編譯處理,而忽略掉其中的資源文件,在運行時就會找不到相應的配置文件。因此資源文件最好直接放在resources目錄中,若是確實須要放在java目錄中,需在pom.xml中配置(配置連接)。
附 pom.xml 依賴:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.buyi</groupId> <artifactId>blues</artifactId> <version>1.0-SNAPSHOT</version> <properties> <spring.version>4.3.7.RELEASE</spring.version> </properties> <dependencies> <!--spring mvc 依賴引入,由於相互依賴的關係,實際上也就引入了 Spring 的幾大核心包,不須要單獨的引入 core beans之類的依賴--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!--spring-jdbc 支持--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!--json支持 缺乏會致使返回前端json格式數據的時候出錯 java.lang.IllegalArgumentException: No converter found for return value of type: class ...--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.4</version> </dependency>
<!--Mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.2</version> </dependency> <!--spring-mybatis整合包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <!--數據庫驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.25</version> <scope>runtime</scope> </dependency> <!--數據庫鏈接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.12</version> </dependency> <!--測試支持--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!--websocket 支持--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </project>