【Mybatis】Spring MVC 框架中整合 MyBatis 环境搭建

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/shaotaiban1097/article/details/91127308


关于 Spring MVC 框架的搭建。欢迎参考上一篇文章:SpringMVC 环境搭建
本文代码 Github 地址

Spring MVC + MyBatis环境搭建

1.准备工作

  • Eclipse IDE
  • JDK 1.8
  • Tomcat 7.0
  • MySQL

2.下载MyBatis框架

  • 下载地址:https://blog.mybatis.org/http://www.mybatis.org/https://github.com/mybatis/mybatis-3/releases
    选择对应的版本进行下载。这里从 github 上下载 mybatis-3.4.1 为例。
    为什么不以目前最新的3.5.1为例呢?
    因为最新版的 3.5.1 版本中有部分包(如:asm-7.0.jar等)可能依赖于 JDK1.9 的新语法。
    启动可能回报 "Invalid byte tag in constant pool: 19"的错误

    3.4.1
    下载完成后,解压,该文件夹下包含:

    • libs:Mybatis 依赖包
    • mybatis-3.4.1:Mybatis核心类库
    • mybatis.3.4.1:pdf、mybatis3.4.1.javadoc.jar 等:Mybatis说明文档及参考文档
      mb3.4.1
  • 将解压后文件夹中的 mybatis-3.4.1.jar 包和 lib 文件夹下的所有依赖包 Copy 到 Java 项目 WEB-INF 文件夹下的 lib 文件夹中
    copytolib
    如果之前已经引入了Spring相关的jar包,这里可能会有部分包重复,直接覆盖掉即可(覆盖时注意版本)。

3.下载其他所需 Jar 包

  • Mybatis-Spring。下载地址:https://mvnrepository.com/artifact/org.mybatis/mybatis-spring/1.3.1
    因为 MyBatis 3 发布在 Spring 3 之后,Spring 3 并未提供对 MyBatis 3 的支持,所以,如果使用的是Spring 3 和 MyBatis 3 整合,该中间包是必须的。
    本文使用的是Spring5+MyBatis3,理论上来说是不需要该中间包的。但为了避免以后使用 Spring3 + Mybatis3 时忘记该步骤,所以配置中也加入了该包的引入。
    如果是 Spring5+Mybatis3 的组合,自行配置时可以不下载该包,但后面与之相关的 xml 配置也需要移除,否则会报错"
    Unable to locate Spring NamespaceHandler for XML schema"
  • mysql-connector-java。下载地址:MySql官网GitHub
    注意源码版本与发布版本的区别,发布版可以直接引入,源码版需要编译后引入
    数据库驱动包。连接数据库,数据库驱动包是必不可少的,本文以 mysql 数据库为例。当然,如果需要连接 Oracle 或其他数据库,更换其驱动包即可。
    据MySQL官网描述,mysql-connector-java 8.0 版本已经完全支持 MySQL5.5及以后的版本,虽然官方强烈建议使用8.0版本,但是本文依然以 5.1 版本为例(因为我自己MySQL版本有点低)
  • c3p0。下载地址:https://sourceforge.net/projects/c3p0/files/c3p0-bin/c3p0-0.9.5.3/c3p0-0.9.5.3.bin.zip/download
    MyBatis 的底层依然基于 JDBC,因此在使用 MyBatis 执行持久化时 JDBC 驱动也是必不可少的。c3p0 则是最常用的开源 JDBC 连接池。

4.建议下载的 jar 包(后面第 6 步测试中用到)

  • Aspectj。下载地址:http://www.eclipse.org/aspectj/downloads.php
    这是一个面向切面框架,定义了AOP语法,扩展了Java语言。
    Spring 拥有自己的 AOP,而且功能已经足够,只不过某些功能上实现比较复杂。 Aspectj 提供了注解方式去实现功能,极大的方便了使用,省去了许多繁琐的配置操作,尤其在数据库事物处理方面,优势更为明显。
    本文以 aspectj-1.8.14 版本为例
  • JSTL。下载地址:JSTL 1.2standard 1.1.2
    作为JSP的标准标签库。JSTL实现Web应用程序中许多常见的标记库集,包括循环、判断、格式化以及数据库访问等。最大程度的提高了Web应用在各个应用服务器之间的移植,简化了 JSP 页面和 Web 程序的开发。
    本文以当前最新版 JSTL1.2.5 为例

5.修改配置文件

  • 先将 3、4 步所下载的 jar 包(压缩包 jar 包在的 lib 文件夹下)Copy 到项目 WEB-INF 的 lib 目录下。
  • 配置文件 applicationContext.xml
    该配置文件位于 WEB-INF 根目录下。如果没有,需要手动创建新 xml 文件。配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	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/mvc
		http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx.xsd
		http://mybatis.org/schema/mybatis-spring
		http://mybatis.org/schema/mybatis-spring.xsd" >
		
	<!-- mybatis:scan 会自动将 base-package 下的包里的所有接口当做 mapper 配置,自动引入 mapper 类 -->
	<!-- base-package 的值为项目中需要扫描的接口所在的完整路径,结合自己项目路径与包名自行修改 -->
	<mybatis:scan base-package="com.foxconn.mapper"/>
	<!-- 扫描base-package下的所有java文件,若有 Spring 相关注解的类,则把这些类注册为 Spring 的 bean -->
	<!-- base-package 的值为需要被 Spring 扫描注解的完整路径,一般刚开始可以扫描所有,后面项目较大时根据实际情况再做修改 -->
	<context:component-scan base-package="com.foxconn" />
	<!-- 使用 PropertyOverrideConfigurer 后处理器加载数据源参数文件 -->
	<!-- location 中 classpath 的值为数据库的配置文件,包含连接驱动、用户名、密码等信息,稍后会手动创建 -->
	<context:property-override location="classpath:db.properties" />
	<!-- 配置 c3p0 数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"/>
	<!-- 配置 SqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="dataSource"/>
	<!-- JDBC 事物管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/>
	<!-- 启动支持 annotation 注解方式事物管理 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
  • 配置文件 springmvc-config.xml
    该配置文件位于 WEB-INF 根目录下。上一篇文章搭建 SpringMVC 环境时已经创建,如果没有,可以手动创建或参考上一篇文章:SpringMVC环境搭建。配置内容如下:
<?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:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	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">
	<!-- Spring 自动扫描  base-package 所配置的包及其子包下的 Java 文件 -->
	<context:component-scan base-package="com.foxconn.controller" />
	
	<!-- 配置 annotation 类型的处理器适配器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
	
	<!-- 配置视图解析器 -->
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/" p:suffix=".jsp"/>
</beans>

相对于之前搭建 SpringMVC 时,该配置文件除了多加入了几个引用之外,还优化了一下视图解析器的配置。
对视图解析器添加了前后缀信息。添加 p:prefix 属性需要在beans中引入 xmlns:p=“http://www.springframework.org/schema/p

其优点非常明显:
之前:Controller 中设置视图名如下

@RequestMapping(value="/hello")
	public ModelAndView hello() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("message", "HelloWorld");
		mv.setViewName("/WEB-INF/test/demo.jsp");
		return mv;
	}

现在:配置了前后缀,Controller 中设置视图名可以如下:

@RequestMapping(value="/hello")
	public ModelAndView hello() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("message", "HelloWorld");
		mv.setViewName("test/demo");//这里只需要写文件夹名和视图名,不必写完整的长路径了。
		return mv;
	}
  • 配置文件 web.xml
    该配置文件位于 WEB-INF 的根目录下,创建项目时可以选择自动创建,也可以后期手动创建。配置内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>HelloSpring</display-name>
  <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>
  
  <!-- 配置 spring 核心监听器。默认以 WEB-INF/applicationContext.xml为配置文件 -->
  <listener>
  	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>/WEB-INF/applicationContext*.xml</param-value>
  </context-param>
  
  <!-- 定义SpringMVC的前端控制器 -->
	<servlet>
	<servlet-name>springmvc</servlet-name>
	<servlet-class>
	org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	<init-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/springmvc-config.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
	</servlet>
	<!-- 让 SpringMVC 的前端控制器拦截所有请求 -->
	<servlet-mapping>
	<servlet-name>springmvc</servlet-name>
	<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- 定义过滤器 -->
	<!-- 编码过滤器 -->
	<filter>
		<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>
  • 配置文件 db.properties
    该配置文件建议放在 src 根目录下,因为它是数据库的配置文件而不是网页的配置。
    文件名称一定要与 applicationContext.xml 中配置的文件名相符
    其配置内容示例如下(根据自己的数据库自行调整):
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
dataSource.user=root
dataSource.password=root

至此,环境配置完成,接下来为测试步骤

6.功能实现及测试

  • 数据表构建
    MySQL 的安装及其可视化程序的安装不在赘述。本文使用的是 MySQL 5.5 + Navicat 10。
    ~~ 今天才突然想起来好久没有给MySQL升级了,版本太落后了,搭完这个环境后该去更新一下MySQL了
    下面是我之前学习身份证号码算法时用到的一张数据表,就顺便拿过来用,这里只贴几条示例数据。
create table ID_CARD_AREABASE
(
  id         int primary key auto_increment,
  provinceno VARCHAR(2),
  province   VARCHAR(50),
  cityno     VARCHAR(4),
  city       VARCHAR(50),
  districtno VARCHAR(6),
  district   VARCHAR(50),
  rank       INT(2),
  isenable   INT(2) default 1,
  createdate TIMESTAMP default CURRENT_TIMESTAMP,
  updatedate TIMESTAMP
);
INSERT INTO `id_card_areabase` VALUES (2, '14', '山西省', '1411', '吕梁市', '141182', '汾阳市', 2, 1, '2019-06-08 10:02:15', '0000-00-00 00:00:00');
INSERT INTO `id_card_areabase` VALUES (3, '15', '内蒙古自治区', NULL, NULL, '150000', '内蒙古自治区', 0, 1, '2019-06-08 10:02:15', '0000-00-00 00:00:00');
INSERT INTO `id_card_areabase` VALUES (4, '15', '内蒙古自治区', '1501', '呼和浩特市', '150100', '呼和浩特市', 1, 1, '2019-06-08 10:02:15', '0000-00-00 00:00:00');
INSERT INTO `id_card_areabase` VALUES (5, '15', '内蒙古自治区', '1501', '呼和浩特市', '150102', '新城区', 2, 1, '2019-06-08 10:02:15', '0000-00-00 00:00:00');

db

  • 持久层实现 – JavaBean
    在项目 src 目录下,存放代码的包文件下,再新建一个包,命名为 domain,用来存放持久层POJO文件
    新建一个 java 类,命名为 IdCard.java,实现 Serializable 接口,内容如下:
package com.foxconn.domain;

import java.io.Serializable;
import java.util.Date;

public class IdCard implements Serializable{
	private Integer id;//id
	private String provinceno;//省级代码
	private String province;
	private String cityno;//市级代码
	private String city;
	private String districtno;//县级代码
	private String district;
	private Integer rank;
	private Integer isenable;//是否可用
	private Date createdate;
	private Date updatedate;
	/*Setter & Getter*/
}
  • 持久层实现 – Mapper
    在项目 src 目录下,存放代码的包文件下,再新建一个包,命名为 mapper,用来持久层映射文件
    新建一个 java 接口,命名为 IdCardMapper.java,内容如下:
package com.foxconn.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.foxconn.domain.IdCard;
public interface IdCardMapper {
	/**
	 * 查询所有信息(这里使用了 MyBatis 的注解映射对应了SQL语句)
	 * @return
	 */
	@Select("select * from id_card_areabase")
	List<IdCard> findAll();
}
  • 服务层实现
    在项目 src 目录下,存放代码的包文件下,再新建一个包,命名为 service,用来存放服务层接口文件,
    再在 service 包下新建一个包,命名为 impl,为 implement 的缩写,用来存放服务器实现类文件。
    在 service 包下新建一个 Java 接口,命名 IdCardService.java,同时,在 service 下的 impl 包下新建一个 java 类,命名 IdCardServiceImpl.java,并实现 IdCardService 接口。内容如下:
package com.foxconn.service;

import java.util.List;
import com.foxconn.domain.IdCard;

public interface IdCardService {
	List<IdCard> findAll();
}
package com.foxconn.service.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.foxconn.domain.IdCard;
import com.foxconn.mapper.IdCardMapper;
import com.foxconn.service.IdCardService;

//@Service 注解将当前类标记为一个 Spring 的 bean。名为 idCardService
@Service("idCardService")
public class IdCardServiceImpl implements IdCardService {
	//@Autowired 注解自动注入指定的持久层 Mapper 对象
	@Autowired
	private IdCardMapper idCardMapper;

	@Override
	public List<IdCard> findAll() {
		return idCardMapper.findAll();
	}
}
  • 控制层实现
    在项目 src 目录下,存放代码的包文件下,再新建一个包,命名为 controller,用来存放控制层文件(该包与搭建SpringMVC环境时已经创建过)
    新建一个 java 类文件,命名 IdCardController.java,内容如下:
package com.foxconn.controller;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import com.foxconn.domain.IdCard;
import com.foxconn.service.IdCardService;

@Controller()
@RequestMapping("IdCard")
public class IdCardController {
	@Autowired
	private IdCardService idCardService;
	@RequestMapping("index")
	public String index(Model model) {
		List<IdCard> list = idCardService.findAll();
		model.addAttribute("idCardList", list);
		return "idCard/index";
	}
}
  • 视图层实现
    在项目 WEB-INF 目录下,根据刚才 Controller 中返回的视图路径,建立对应的文件夹和 jsp 页面。
    如上面返回的是 idCard/index,视图解析器中的默认前缀是 WEB-INF,所以就需要再 WEB-INF 目录下新建一个 idCard 文件夹,再在该文件夹内,新建一个 index.jsp 文件。内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IdCardList</title>
</head>
<body>
	<h1>Show List</h1>
	<table>
		<c:forEach items="${requestScope.idCardList }" var="idCard">
			<tr>
				<td>${idCard.id }</td>
				<td>${idCard.provinceno }</td>
				<td>${idCard.cityno }</td>
				<td>${idCard.districtno }</td>
				<td>${idCard.createdate }</td>
			</tr>
		</c:forEach>
	</table>
</body>
</html>

OK

7.框架整体结构

mybatis

附:期间遇到的问题及解决方法

  • Invalid byte tag in constant pool: 19

    • 问题原因:
      MyBatis3.5.1中有部分包依赖于JDK1.9语法,而本地环境使用了JDK1.8
    • 解决方法:
      降低 MyBatis 3.5.1 版本至 3.4.1。(或提升JDK版本到1.9+)
  • Unable to locate Spring NamespaceHandler for XML schema(未找到 XML 中的 Spring 命名空间处理程序)

    • 问题原因:
      XML 中配置了MyBatis3整合Spring3的中间包,却未导入对应的 jar 文件
    • 解决方法:
      下载中间包 mybatis-spring.jar 包并导入。
  • JDBC Driver class not found: com.mysql.jdbc.Driver(未找到 JDBC 驱动)

    • 问题原因:
      复制 jar 包到 lib 目录时,遗漏了 mysql 驱动包
    • 解决方法:
      下载驱动包 mysql-connector-java.jar 并复制到项目 WEB-INF 的 lib 目录下
  • Connections could not be acquired from the underlying database(无法从基础数据库获取连接)

    • 问题原因:
      数据库配置有误。驱动名称、数据库连接名、用户名、密码等配置信息错误
    • 解决方法:
      修改 db.properties 文件下的配置信息
    • 参考文章:
      https://www.jianshu.com/p/73557fde5ab8
  • The server time zone value ‘XXX’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.

    • 问题原因:
      起初因为MySQL官方强烈建议使用 8.0 以上驱动,且 8.0 以上驱动已完全支持 MySQL 5.5 以上的版本,所以引用了最新版的 8.0 驱动。但是 8.0 的驱动会对时区进行判断,由于数据库时区与系统时区差异,导致该报错。
    • 解决方法:
      使用 mysql-connector-java-5.1 驱动。
      或者在连接配置db.properties文件的 jdbcUrl 的值后加上 serverTimezone=GMT%2B8 来指定时区。如:dataSource.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8。
    • 说明:
      以上两种方式都已经测试过。但因本机MySQL许久未升级,仅为5.5版本,为避免后面出现更多其他问题,本文选择了第一种方式作为最终的解决方式。
  • Zero date value prohibited(日期值进制为 0)

    • 问题原因:
      数据库中的 updatedata 一栏值为 0,但 mysql 不允许 0000-00-00 这种无效日期
    • 解决方法:
      在连接配置文件 db.properties文件的 jdbcUrl 的值后面加上 zeroDateTimeBehavior=convertToNull 属性。将 0000-00-00 这种日期转换为 null 值。(需要注意的是,url 后跟多个参数时连接符为 &)
    • 参考链接:
      https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-installing-upgrading-3-0-to-3-1.html
  • java.sql.SQLException: Value ‘0000-00-00 00:00:00’ can not be represented as java.sql.Timestamp

    • 问题原因:
      日期 0000-00-00 00:00:00 无法转换为 Java 的 TimeStamp
    • 解决方法:
      同上 Zero date value prohibited 错误的解决方法
  • java.lang.NoClassDefFoundError: org/apache/taglibs/standard/tlv/JstlCoreTLV
    Multiple annotations found at this line:
    isValid() == false
    Undefined attribute name
    "item"

  • attribute items does not accept any expressions (items 不支持表达式)

    • 问题原因:
      <%@taglib prefix="c" uri="http://java.sun.com/jstl/core" %>					JSTL 1.1 版本
      <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>				JSTL 1.2 版本
      
    • 解决方法:
      将JSP文件中使用标签库的语句修改为 1.2 版本对应的语句即可。

猜你喜欢

转载自blog.csdn.net/shaotaiban1097/article/details/91127308