MyBatis从入门到精通(第9章):Spring集成MyBatis(上)
Spring是一个为了解决企业级Web应用开发过程中面临的复杂性,而被创建的一个非常流行的轻量级框架。
mybatis-spring 可以帮助我们将MyBatis代码无缝整合到Spring中。使用这个类库中的类,Spring将会加载必要的MyBatis工厂类和Session类。
MyBatis Spring Adapter项目地址为: https://github.com/mybatis/spring
master (2.0.x) - Support for Java 8, Spring 5
9.1 创建基本的Maven Web项目
下面开始创建一个空的Web项目。
首先,按照操作步骤创建一个基本的Maven项目,直到添加完所有基础依赖后,再按照下面的步骤进行操作。
1. 在pom.xml中添加 packaging配置
在Maven的pom.xml中,packaging默认的打包方式为jar,即普通的Java项目会被打包成.jar文件。
当我们将packaging设置为war时,就变成了一个Web项目,项目会被打包成.war文件。
<?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>cn.bjut.mybatis</groupId> <artifactId>day01_09mybatis-spring</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging>
2. 增加Web基本目录和配置
完成上述配置后,Maven项目就变成了Web项目,但是项目中还缺少Web项目必要的目录和配置文件。
在 src/main 目录下新建 webapp 目录(文件夹),然后在 webapp目录中创建 WEB-INF目录,
最后在 WEB-INF 目录中添加 web.xml 配置文件, web.xml配置文件如下。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
3. 在pom.xml中添加Web相关依赖
添加基础依赖
<properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.17</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
<build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build>
Web相关依赖
<!--web--> <!--支持 Servlet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!--支持 JSP--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--支持 JSTL--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
通常Web容器都会自带 servlet-api 和 jsp-api 的jar包,为了避免jar包重复引起错误,需要将这两个依赖坐标的 scope 配置为provided
在一般的以JSP作为视图的项目中,使用 jstl可以在视图中处理复杂的逻辑,所以一般的Web项目中都会添加jstl依赖。
4. 添加一个简单页面 index.jsp
在webapp目录中新建 JSP页面,文件名为 index.jsp ,文件内容如下。
<%@ page import="java.util.Date" %> <%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF8"> <title>Index</title> </head> <body> <p> Hello Web! </p> <p> <% Date now = new Date(); %> 服务器时间:<fmt:formatDate value="<%=now%>" pattern="yyyy-MM-dd HH:mm:ss"/> </p> </body> </html>
完成上面4步后,一个基本的 Maven Web项目就完成了。
接下来部署这个Web项目并查看效果。
JDK环境: jdk1.8.0_211
Web容器: Tomcat 8.5.43
IDE环境: IntelliJ IDEA 2018.3.6
这里可以参考黑马程序员2018年录制的视频课: javaweb部分\2-8Tomcat\第3节 tomcat_部署项目
07_tomcat_部署项目的方式 、09_tomcat_与IDEA集成&创建web项目 、08_tomcat_动态java项目的目录结构
选中小锤子图标右侧的 Tomcat 8.5.43 选项卡后,再点击debug小虫子按钮左侧的 运行 按钮启动。
9.2 集成Spring和Spring MVC
为了方便控制层的开发还会集成最流行的 Spring MVC ,
集成Spring和Spring MVC 的步骤如下。
1. 添加 spring-framework-bom 用于管理Spring依赖
在pom.xml文件中的dependencies后面添加如下配置。
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>5.0.15.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
为了避免使用不同版本的Spring组件导致意外情况发生,可以使用
spring-framework-bom 。 添加 spring-framework-bom 后 , 在使用 Spring 依赖时就不需要再配置每
个依赖的版本号了,Spring 组件的版本 由 spring-framework-bom 统一管理 。 可以很方便地升级Spring的版本。
2. 添加Spring依赖
下面这些依赖是集成Spring时的常用依赖,各个依赖的作用可以参考注释 内容 。
<!--Spring 上下文,核心依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <!--Spring JDBC--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <!--Spring 事务--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> <!--Spring 面向切面编程--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </dependency> <!--spring-aop 依赖--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency>
3. 添加 Spring MVC 依赖
<!--Spring Web 核心--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <!--Spring MVC--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <!--spring mvc-json依赖--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.4</version> </dependency>
前两个依赖为 SpringMVC 必备的依赖, 后面的 jackson-databind 是 SpringMVC 转换为 JSON
时需要使用的依赖。
4. 添加Spring XML配置文件
在 src/main/resources 中新增 applicationContext.xml 文件,内容如下。
base-package 属性来设置要自动扫描类的包名,包名中的*匹配 0 或者任意数量的字符。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="cn.bjut.mybatis.*.service.impl"/> <bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis2019 ?serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> </beans>
注意:自动扫描包配置,原书此处忘记添加9.2小节测试必须用到的一行代码如下:
<context:component-scan base-package="cn.bjut.mybatis.*.controller"/>
5. 添加Spring MVC 的配置文件
在 src/main/resources 中新增 mybatis-servlet.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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <mvc:annotation-driven/> <mvc:resources mapping="/static/**" location="static/"/> <context:component-scan base-package="cn.bjut.mybatis.*.controller"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
这是一个最简单的配置,各项配置简单说明如下。
mvc:annotation-driven 启用Controller注解支持。
mvc:resources 配置了一个简单的静态资源映射规则。
context:component -scan 扫描controller包下的类。
InternalResourceViewResolver 将视图名映射为 URL文件。
6. 配置web.xml
集成Spring和Spring MVC后,需要在web.xml中进行相应的配置。
对于Spring来说,需要增加如下配置。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
这个配置用于在 Web 容器启动时根据 contextConfigLocation 配置的路径读取 Spring
的配置文件,然后启动 Spring。
针对 Spring MVC,需要增加如下配置。
<servlet> <servlet-name>mybatis</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:mybatis-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mybatis</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
<!--为了避免编码不一致,通常还需要增加如下的编码过滤器配置。-->
<filter> <filter-name>SpringEncodingFilter</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpringEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
结合淘淘商城那个项目练习的注释给出最终的 web.xml配置代码:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <!--对于Spring来说,需要增加如下配置。--> <!-- 加载Spring容器bean.xml配置文件,修改通配符 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--针对Spring MVC,需要增加如下配置--> <!-- Spring MVC的前端控制器 --> <servlet> <servlet-name>mybatis</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, Spring MVC的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml"--> <param-value>classpath:mybatis-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mybatis</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--为了避免编码不一致,通常还需要增加如下的编码过滤器配置。--> <!-- 解决post乱码 --> <filter> <filter-name>SpringEncodingFilter</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpringEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
注意: applicationContext.xml 被我放到了resources/spring目录下测试运行效果。XML的配置还支持如下这种带*通配符的呢:
classpath:spring/applicationContext-*.xml
7. 增加一个简单的 Controller示例
将 index.jsp 移动到 src/main/webapp/WEB-INF/jsp 目录中。再对index.jsp页面中的body部分做如下修改。
<%@ page import="java.util.Date" %> <%@ page language="java" contentType="text/html; charset=UTF8" pageEncoding="UTF8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF8"> <title>Index</title> </head> <body> <p> Hello Spring MVC! </p> <p> 服务器时间:<fmt:formatDate value="${now}" pattern="yyyy-MM-dd HH:mm:ss"/> </p> </body> </html>
增加一个package包:cn.bjut.mybatis.web.controller
然后新建IndexController类,该类的代码如下。
package cn.bjut.mybatis.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import java.util.Date; @Controller public class IndexController { @RequestMapping(value = {"index"}) public ModelAndView dicts(){ //创建一个模型视图对象 ModelAndView mav = new ModelAndView(); //获取到查询的数据对象 Date date = new Date(); //将数据放置到ModelAndView的实例化对象中,第二个参数可以是任何java类型 mav.addObject("now",date ) ; //放入jsp路径 mav.setViewName("index"); //返回ModelAndView对象mav return mav; } }
经过 以上这么多步的操作后 , 基本的 Spring 和 Spring MVC 就集成完了。重启 Tomcat 然后
访问地址 http://localhost:8080/day01/index ,浏览器就会显示内容 。
ModelAndView的实例是需要我们手动new的,而且ModelAndView可以自己寻址,只需要return 返回其对象即可。
注意: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/exc/InvalidDefinitionException
解决: 此信息为spring和jackson相关版本不兼容,这个项目使用的是Spring5.0.15版本,把本地jsckson版本升到2.9.9版本即可。
附录:原书本章节中并未介绍spring管理事务AOP相关的配置内容, applicationContext.xml 的完整代码如下。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="cn.bjut.mybatis.*.service.impl"/> <bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis ?serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations"> <array> <value>classpath:cn/bjut/mybatis/**/mapper/*.xml</value> </array> </property> <property name="typeAliasesPackage" value="cn.mybatis.web.model"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="addToConfig" value="true"/> <property name="basePackage" value="cn.bjut.mybatis.**.mapper"/> </bean> <aop:aspectj-autoproxy/> <aop:config> <aop:pointcut id="appService" expression="execution(* cn.bjut.mybatis.*.service..*Service*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="appService"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="select*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="get*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
spring框架的AOP配置内容详解,请见我的CSDN博客。
04 Spring: 10.Spring中事务控制(上)
04 Spring: 10.Spring中事务控制(中)
================
end