常用的SSM整合方式
看见网上这么多的整合方法,实在是眼花缭乱,看不过来,有些资料仅仅是整合某个部分,或者是整合的方式太过简陋,在实际开发中根本不会使用。接下来我页也来写一篇我平时写项目用的整合方式,一是将我的整合模板记录下来,二是提供给大家一个借鉴的思路。
在讲解整合思路之前,我们先搭建好一个项目工程,以便我们进行后面的操作
一、创建项目
我们先创建好要整合项目的环境,然后再讲如何讲这三个框架整合起来。
创建项目
绑定maven
点击finish后,我们将项目的pom文件修改至结构如下:
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<name>SSM_Template</name>
<groupId>example</groupId>
<artifactId>SSM_Template</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
</dependencies>
</project>
然后将web.xml文件内容修改为如下
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
到这里我们的项目结构暂时如下所示
二、搭建SpringMVC环境
整合这三个框架,我从SpringMVC开始,也就是先搭建SpringMVC的环境。其实也有人是从搭建Spring开始的,这两者没多大区别,整合思路大体一致。
1、导入springmvc相关依赖
首先我们想要使用springmvc的相关功能,必定要先导入跟springmvc相关的jar包,要不然就玩不起来了。
在pom.xml文件中添加如下依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
2、配置跟springmvc相关的组件
2.1、web.xml文件
前端控制器
我们都知道springmvc工作的核心就是在客户端浏览器发起的所有请求到达服务器之前,由一个前端控制器来控制所有的请求,并由其决定该请求转发给哪个控制器中的请求方法。所以我们要使用springmvc,首先得在web.xml文件中配置这个前端控制器。如果你要问为什么是在web.xml文件中配置它,这个前端控制器叫DispatcherServlet,它是一个Servlet,既然是一个Servlet,那么它就跟我门之前学习javaweb的时候配置Servlet一样在web.xml中一样的。
在web.xml中加入如下内容配置前端控制器
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
springmvc的配置文件
注意,因为我在配置这个前端控制器的时候并没有指定它的springmvc的配置文件在哪,所以这个springmvc的配置文件默认是放在WEB-INF目录下的,而且它的名字是前端控制器的名字再加上-servlet , 为了降低出错率,我们现在就在WEB-INF目录下创建springmvc的配置文件且文件名就叫 [ springDispatcherServlet-servlet.xml ] 。
里面的内容我门先不添加
中文乱码过滤器
乱码过滤几乎是必须的,为什么要配置它我想不需要过多的啰嗦,唯一要注意的一点是,这个过滤器必须放在所有的filter之前,否则就不能达到过滤的效果。
在web.xml文件中加入如下内容
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
支持resful风格请求
若是有小伙伴的i项目开发需要用到resful风格的请求方式,那么就必须在web.xml文件中配置一个resful风格的支持组件HiddenHttpMethodFilter ,内容如下
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
还记得我们刚才说过什么吗?中文乱码过滤器必须放在第一个Filter的位置,所以这个支持resfull风格的过滤器需要放在中文乱码过滤器之后。
2.3、配置springmvc的文件的相应内容
扫描Controller
在Springmvc中我们已不再使用Servlet进行请求的处理,而是用到一个叫控制器的Controller,在这里写上相应的请求方法以及请求映射,浏览器的请求就能被前端控制器正确派发到相应的请求方法。但是这些控制器Controller要想能前端控制器找到,那就必须得加入到容器中才能被识别。所以我们要在springmvc的配置文件中使用 </context:component-scan>将这些控制器扫描进去,但是要注意了,若果我们扫描Controller的时候使用的是下面的配置方式
<context:component-scan base-package="SSM.Template">
</context:component-scan>
这样配置确实能够将Controller扫描进入容器,目前也能够正确使用,但是不要忘了,我们现在是要将SSM这三个框架进行整合,现在我们使用上面的方式将组件扫描进入容器,是将Template包下的所有组件,包括service、bean等组件也扫描进去了,到时候再配置spring容器的时候,也同样使用同样的方式扫描组件,那么容器中就会有两个一样的组件,在我们开发的时候使用的组件就不是同一个组件,也就不是单实例组件,会带来很多不必要的麻烦,比如说会导致我们的事务控制失败…
所以很自然地应该让spring来管理与业务有关的组件bean,而springmvc来管理跟控制器有关的bean.也就是在扫描的时候使用过滤器. 简单点来说就是在springmvc的配置文件中只扫描控制器Controller,而在spring的配置文件中扫描除过Controller的所有组件。也就是在springmvc的配置文件中应该写如下内容
<context:component-scan base-package="SSM.Template" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
放行静态资源
前面我们配置前端控制器的时候,设置它的过滤规则是一个斜杠 / , 这样代表的意思是拦截所有的资源除过.jsp后缀的资源,也就是说,除了jsp页面,其他资源的请求比如 .html ,.png 等静态资源都会被前端控制器所拦截到,而这些静态资源本来是由tomcat进行处理的,现在这个前端控制器拦截到了这些静态资源的请求,导致tomcat不能接收这些静态请求,所以我们就不能够访问这些静态资源,所以我们要在springmvc的配置文件中添加如下内容来告诉tomcat,前端控制器不能处理的资源有tomcat进行处理
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
视图解析器
这个是啥玩意我就不过多进行解释了,只是一个便利工具罢了,配置它之后我们在请求方法中进行转发的路径就不需要每次都全部的前缀后缀了,但是注意,有forward、redirect等修饰的请求转发路径是要写全路径的。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
3、页面测试
Springmvc的配置文件内容已经写的差不多了,现在我们来写一点页面以及请求方法来测试一下环境是否搭建完成吧!
3.1、编写一个HelloController
@Controller
public class HelloController {
@RequestMapping("hello")
public String hello(
Model model
){
model.addAttribute("msg" ,"你好啊,赶潮人");
return "success";
}
}
3.2、编写页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>成功页面</title>
</head>
<body>
服务器传来的信息: <br/>
<h1>${msg}</h1>
</body>
</html>
文件位置
3.3、配置tomcat
启动服务器,因为我们没有写一个index.jsp首页,所以启动后的默认界面是这样的
不用管他,当然你想有一个默认界面就自己创建一个index.jsp页面即可,这里我直接发起请求,
http://localhost:8080/SSM_Template/hello
显示如下内容,表明我们的springmvc环境已经搭建好了
三、整合Spring环境
好,搞完springmvc的相关配置,我们来让它跟spring整合在一起。
3.1、导入spring依赖
因为之前我们导入了下面这个坐标,相应的spring包也会被导入
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
所以这里我们不导包了
3.2、创建相应的JavaBean、Service等
为了跟之后整合mybatis用的JavaBean一致,现在我创建一个与我的数据库表字段相关的JavaBean
JavaBean
@Component
public class Book {
private Integer id;
private String name;
private String author;
private String price;
private String sales;
private String stock;
private String img_path;
//相应的get / set 方法以及有参无参构造器
}
BookUservice
public interface BookService {
public void deleteById(Integer id);
}
BookServiceImpl
@Service
public class BookServiceImpl implements BookService {
/**
* 模拟删除图书
* @param id 图书id
*/
@Override
public void deleteById(Integer id) {
System.out.println("id 为" + id +" 的图书已被删除.....");
}
}
3.3、spring的配置文件
相应的业务代码也写的差不多了,现在我们开始写spring的配置文件
在类路径下(resources目录下)创建spring的配置文件,名为spring.xml
在写springmvc的配置文件的时候我们就说过,spring的配置文件不用扫描Controller,所以在配置包扫描的时候,在spring.xml文件添加如下内容
<context:component-scan base-package="SSM.Template">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
3.4、测试spring环境
引用测试依赖,写一个测试方法来看看我们的组件是否已经被扫描进了spring的容器中
测试依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
测试方法
@Test
public void test1(){
ClassPathXmlApplicationContext ioc =new ClassPathXmlApplicationContext("spring.xml");
String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
for (String name :
beanDefinitionNames) {
System.out.println(name);
}
}
显示测试结果如下,说明我门的spring.xml文件中的配置内容生效了,而且Controller并没有被扫描进来,正是我们想要的
3.5、spring与springmvc整合
即然spring与springmvc的环境都搭建好了,那么我们现在就开始着手将他们两个组合起来。那么怎样才算整合成功呢?明确这一点将对我们产生很大的作用,首先spring作用是降低耦合,反转控制;而我们的springmvc的作用在这里是代替servlet提供一种更便利的方式去处理请求。说的通俗一点就是,spring容器中配置的组件要能够在springmvc组件中使用,也就是说,BookService要能够在Controller中完成DI注入。
因为我们的项目是在tomcat下部署的,也就是说,我门的服务器是tomcat。而在我们启动tomcat服务器的时候,只会启动我们的springmvc容器,而 不会启动我们 的spring容器,因为我门在web.xml文件中配置前端控制器的时候,这个前端控制器会默认去加载默认位置的springmvc文件,而没有去加载我们的spring配置文件,所以也就是说我们的spring容器没有启动。所以怎样能够像springmvc配置文件一样,在启动tomcat容器的时候就能够被加载呢?我们的spring中又没有像mvc中的前端控制器一样的东西?
虽然spring中么有,但是我们可以利用tomcat中的lisenter监听器来初始化加载我们的spring容器,也就是说,在webx.xml文件中除了配置springmvc的内容除外,还要在里面加入如下内容去加载我们的spring容器。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
3.6、测试springmvc与spring整合后的环境
在控制器中添加如下的请求方法
@Autowired
BookService bookService;
@RequestMapping("hello2")
public String hello2(
Model model
){
bookService.deleteById(5);
model.addAttribute("msg","你好哇,李银河!");
return "success";
}
启动服务器后,发起请求
http://localhost:8080/SSM_Template/hello2
成功跳转页面
而且服务器端输出如下内容,表明我们的Controller能够正常DI注入我们spring容器中的组件。整合成功!
四、整合Mybatis
整合Mybatis之前,我们先来说一下将会用到的数据库以及数据表
这里我直接用之前创建好的Book作为测试的JavaBean
1、导入依赖坐标
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
同样我们整合mybatis的目标是能够使用spring反转控制实现DI注入相应的Mapper接口,也就是直接在ServiceImpl中直接使用Mapper。
2、创建dao层文件
BookDao接口
import SSM.Template.bean.Book;
import org.springframework.stereotype.Repository;
@Repository
public interface BookDao {
public Book getBookById(Integer id);
}
对应的mapper映射文件
<?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="SSM.Template.dao.BookDao">
<select id="getBookById" resultType="SSM.Template.bean.Book">
select * from t_book where id=#{id}
</select>
</mapper>
之前我们学习mybatis的时候都知道,mybatis可以帮我们使用的dao接口生成一个代理对象,是这个代理对象帮我们进行的增删改查。我们可以把这个代理对象也放进IOC容器,那么service就可以拿到这个对象进行DI注入。而将mybatis整合进spring容器中,其实就是将mybatis的配置内容转移到spring的配置文件中,这样容器才能拿到mybatis的组件,实现DI注入。
3、在spring配置文件中配置与(mybatis框架)数据库有关的组件
类路径下创建dbconfig.properties文件
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/blog
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=xxxxx
在spring的配置文件中加入如下内容
<content:property-placeholder location="classpath:dbconfig.properties"/>
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="pooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<!-- 指定mybatis全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="pooledDataSource"></property>
<!-- <!– 指定mybatis,mapper文件的位置 –>-->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" id="mapperScanner">
<property name="basePackage" value="com.mdy.blog.dao"/>
</bean>
4、测试
Service接口添加方法
import SSM.Template.bean.Book;
public interface BookService {
public void deleteById(Integer id);
public Book getBookById(Integer id);
}
BookServiceImpl实现类
package SSM.Template.service.impl;
import SSM.Template.bean.Book;
import SSM.Template.dao.BookDao;
import SSM.Template.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookServiceImpl implements BookService {
/**
* 模拟删除图书
* @param id 图书id
*/
@Override
public void deleteById(Integer id) {
System.out.println("id 为" + id +" 的图书已被删除.....");
}
@Autowired
BookDao bookDao;
@Override
public Book getBookById(Integer id) {
return bookDao.getBookById(id);
}
}
Controller添加请求方法
@Autowired
BookService bookService;
@RequestMapping("hello2")
public String hello2(
Model model
){
Book bookById = bookService.getBookById(5);
System.out.println(bookById);
model.addAttribute("msg","你好哇,李银河!");
return "success";
}
启动服务器,访问请求
http://localhost:8080/SSM_Template/hello2
页面跳转成功
服务器输出相应的数据库信息
说明spring简单整合mybatis成功!!!