久沒有寫博客了, 今年事情太多了, 也沒了心思. 去深圳出差, 轉java, 更重要的結婚的事情, 一茬接一茬. 好在最近閑暇一些, 就想記錄一些曾經困擾過我的問題(現在用spring boot真是太方便了, 很多問題, 都不會再是問題).
SSM(spring + springmvc + mybatis), 是一款非常流行的框架. 所以把這款框架搭建起來, 也是開發的一項基本功.
SSM的整合, 分為兩部分:
一部分是 spring與springmvc間的整合,
一部分是 spring與mybatis間的整合.
其實, 也應該是這樣, 因為 springmvc與mybatis間, 沒有任何關系. 都只是與spring有關系.
初步的目錄結構:
不管是用eclipse還是用idea, 都是使用maven來管理jar包, 且把引用放在pom.xml文件中, 可以告別繁瑣的jar包引入.
ssh, ssm 框架的 pom.xml文件, 網上都是能搜得到的, 大把大把, 真的要去搭框架的時候, 可以去網上直接下一個就行了. 沒必要這么麻煩.
一. jar包引入
<properties> <spring.version>4.3.5.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- spring核心包 --> <dependency> <groupId>org.springframework</groupId> <!--包含Spring 框架基本的核心工具類--> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <!--所有應用都用到,包含訪問配置文件,創建和管理bean等,是Spring IOC的基礎實現--> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <!--提供在基礎IOC功能上的擴展服務--> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <!--Spring提供的對AspectJ框架的整合--> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <!--Spring的面向切面編程,提供AOP(面向切面編程)的實現--> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <!-- springmvc相關的spring包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!--spring數據庫相關包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <!--對象的XML映射,可以讓Java與XML之間來回切換--> <artifactId>spring-oxm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <!--用于在Spring 中集成AspectJ AspectJ LTW織入器--> <artifactId>aspectjweaver</artifactId> <version>1.8.10</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.10</version> </dependency> <!-- mybatis/spring包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <!-- mysql數據庫鏈接包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <!-- 日志包 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.20</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.20</version> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.18</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.11</version> </dependency> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.5</version> </dependency> <!--jackson包是springmvc返回json數據時用到的--> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-core-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.5.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.12.1.GA</version> </dependency> </dependencies> <build> <finalName>ssm</finalName> <plugins> <!--解決idea中java compile 和 language level在更新pom文件后,重置到5的版本--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
上面的包, 還包含了mybatis的包, 到整合mybatis的時候, 就不會再寫一遍pom.xml文件了
二. web.xml文件配置spring和springmvc入口
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:conf/application.xml</param-value> </context-param> <!-- 加載log4j的配置文件log4j.properties --> <!--<context-param> <param-name>log4jConfigLocation</param-name> <param-value> classpath:conf/log4j.properties </param-value> </context-param>--> <!-- 設定刷新日志配置文件的時間間隔,這里設置為10s --> <!-- <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>10000</param-value> </context-param>--> <!--解決post亂碼問題--> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置spring啟動listener入口 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener>--> <!--springmvc入口servlet--> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--contextConfigLocation如果不配置, 則會按照默認的方式去找文件, 如果找不到, 則會拋出異常, 所以這里推薦還是要寫一下. 我這里配置的空, 因為在前面application.xml中, 已經import了這里需要的xml文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value> <!--classpath:conf/spring-mvc.xml--> </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
在application.xml文件中, 我引入了spring-mvc.xml文件, 這樣 在web.xml 文件中, 配置 DispatcherServlet 的時候, 就可以將xml文件路徑配置為空. 否則, 程序會按照特定的規則去查找xml文件. 如果找不到, 則會拋出異常.
<?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" xmlns:mvc="http://www.springframework.org/schema/mvc" 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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" default-lazy-init="true"> <!-- 自動搜索bean --> <context:annotation-config /> <!-- 開啟注解 --> <mvc:annotation-driven/> <context:component-scan base-package="org.elvin.ssm" /> <import resource="classpath:conf/spring-mvc.xml" />
<!--在進行mybatis的整合的時候, 這句話要注釋回去--> <!--<import resource="classpath:conf/spring-mybatis.xml"/>--> </beans>
三. springmvc配置文件: spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 注解掃描包 --> <context:component-scan base-package="org.elvin.ssm.controller" > <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan> <!-- 開啟注解 --> <!--<mvc:annotation-driven/>--> <!--靜態資源訪問--> <mvc:default-servlet-handler /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp" /> </bean> <!-- 避免IE在ajax請求時,返回json出現下載 --> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> </beans>
配置文件就暫時到這里了, 接下來看一下java代碼
四. java代碼
在controller文件夾下, 加入一個控制器: HelloController.java
package org.elvin.ssm.controller; import org.elvin.ssm.pojo.*; import org.elvin.ssm.utils.CollectionUtilsLocal; import org.joda.time.DateTime; import org.springframework.stereotype.Controller; import org.springframework.ui.*; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * author: Elvin * datetime: 2017/11/29 20:06 * description: */ @Controller @RequestMapping("hello") public class HelloController { @GetMapping("index") public String index(ModelMap model){ List<Book> bookList = getBookList(); model.put("bookList",bookList); return "index"; } @RequestMapping(value = "book", method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody public Book book(@RequestParam("id") Integer id){ List<Book> bookList = getBookList(); Book b = CollectionUtilsLocal.findOneBy(bookList, n -> n.getId().equals(id)); return b; } //region private method private List<Book> getBookList(){ List<Book> bookList = new ArrayList<>(); String[] nameStrs = {"吳", "一", "雪", "動", "額", "阿", "前", "里", "排"}; Random r = new Random(); String timeStr = new DateTime().toString("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < 10 ; i++){ Book b = new Book(); b.setId(i+1); b.setName(nameStrs[r.nextInt(5)] + nameStrs[r.nextInt(9)]); b.setPublishTime(timeStr); b.setPrice(r.nextInt(100)); bookList.add(b); } return bookList; } //endregion }
這里有個幫助類, 順手也貼出來, 期望達到的目的就是, 拷貝下來, 就能直接跑起來, 不需要調試
CollectionUtilsLocal.java
package org.elvin.ssm.utils; import java.util.*; import java.util.function.Predicate; /** * author: Elvin * Date: 2017/11/30 9:33 * Description: */ public class CollectionUtilsLocal { /** * 功能描述:list去重 **/ public static void removeDuplicateWithOrder(List list) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = list.iterator(); iter.hasNext(); ) { Object element = iter.next(); if (set.add(element)){ newList.add(element); } } list.clear(); list.addAll(newList); } /** * 判斷list是否為空,包括對象為null,內容為空 * * @param list * @return true 代表不為空,false代表為空*/ @SuppressWarnings("rawtypes") public static boolean isNotNullList(List list) { if (null != list && (!list.isEmpty())) { return true; } return false; } /** * 判斷集合是否是null或者空集合 * @param list * @return */ public static boolean isNullOrEmptyList(List list){ if(list == null || list.isEmpty()){ return true; } return false; } /** * @param map * @return true 代表不為空,false代表為空 * @Title: isNotNullMap * @Description: 校驗map是否為空 * @Since: 2017年6月12日下午1:15:31 */ @SuppressWarnings("rawtypes") public static boolean isNotNullMap(Map map) { if (null != map && !map.isEmpty()) { return true; } return false; } /** * 根據條件刪除集合中的元素 * @param list 待刪除元素的集合 * @param predicate 條件 * @param <T> * @return */ public static <T> List<T> removeAll(List<T> list, Predicate<T> predicate){ if (!isNotNullList(list)) { return null; } List<T> resList = new ArrayList<>(); for (T item : list) { if (!predicate.test(item)) { resList.add(item); } } return resList; } /** * 根據查詢條件查找滿足條件的數據,并返回 * * @param list 要查找的集合 * @param predicate 查找的條件 * @param <T> * @return */ public static <T> T findOneBy(List<T> list, Predicate<T> predicate) { if (!isNotNullList(list)) { return null; } for (T item : list) { if (predicate.test(item)) { return item; } } return null; } /** * 根據條件查找集合中所有的數據 * @param list 待查找集合 * @param predicate 條件 * @param <T> * @return */ public static <T> List<T> findAllBy(List<T> list, Predicate<T> predicate) { if (!isNotNullList(list)) { return null; } List<T> resList = new ArrayList<>(); for (T item : list) { if (predicate.test(item)) { resList.add(item); } } return resList; } }
在pojo文件夾下, 加入一個實體文件: Book.java
package org.elvin.ssm.pojo; /** * author: Elvin * datetime: 2017/11/29 20:46 * description: */ public class Book { private Integer id; private String name; private Integer price; private String publishTime; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } public String getPublishTime() { return publishTime; } public void setPublishTime(String publishTime) { this.publishTime = publishTime; } }
五. 前臺代碼
在jsp文件夾下加入一個index.jsp文件
<%-- Created by IntelliJ IDEA. User: Elvin Date: 2017/11/30 Time: 9:17 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>Title</title> </head> <body> <h1>ssm</h1> <table> <thead> <tr> <td>id</td> <td>name</td> <td>price</td> <td>publishTime</td> </tr> </thead> <tbody> <c:if test="${bookList!=null && bookList.size()>0}"> <c:forEach var="item" items="${bookList}"> <tr> <td>${item.id}</td> <td>${item.name}</td> <td>${item.price}</td> <td>${item.publishTime}</td> </tr> </c:forEach> </c:if> </tbody> </table> </body> </html>
六. 結果展示
1. 訪問頁面:
2. 訪問數據
如果想讓springmvc直接返回數據, 要注意幾點
1. 要引入 jackson 的jar包, springmvc沒有提object to json 的功能
2. 在springmvc的配置文件中, 要加上 <mvc:annotation-driven/>
3. 在controller控制器的action方法上面加上 @ResponseBody 注解
3. 訪問靜態資源
想要訪問靜態資源, 需要加上 <mvc:default-servlet-handler /> , 或者自己配置一些資源, 否則是不能訪問到的.
文章列表