Spring SpringMVC MyBatis 整合( 拦截器) 详:
目前为止博客基本已将掌握SpringMVC 相关的知识点;
终于来到了最终时刻 SSM 三大框架整合;
搭建SSM 框架的程序架构
SSM 框架整合其实就是:Mybatis Spring SpringMVC 的整合; 前面学习我们知道 : Mybatis : 是一个ORM 数据持久层框架; SpringMVC : 是一个优秀的 Web框架 它们是一个独立的框架, 而Spring框架提供 Ioc 和 Aop 相当适用的功能; -------可以将 Mybatis 和 SpringMVC 操作对象交给Spring容器进行解耦管理, 大大增强系统灵活性,便于功能扩展 -------还能通过Spring 提供服务简化编码, 减少开发工作量…提高开发效率. ------- 对于SpringMVC 来说它本来就是 Spring的一部分可以说整合过程就是:“无缝连接~性能卓越”
开始SSM 整合:
1. 新建一个 Web.Project 工程,并导入相关的 Jar
2. 数据库模型对象:
就是实体类:一般我喜欢在src下建一个包:com.wsm.entity包; 存放所有实体类;
3.系统工具:
系统工具就是一般会定义一个包: 存储一些常用的类 方法之类似于工具一样的。随时用随时掉~ Page 泛型分页类~
4. Dao数据访问接口:
Dao 数据持久层, 进行数据操作的…
一般我在src下建一个包:com.wsm.Dao包; 存放所有Dao接口类;每个类型接口描述每一种类型的操作~
applicationContext-mybatis.xml 配置文件 扫描包com.wsm.Dao包实现包所有接口…完成数据库持久化操作~
5. service 业务逻辑层:
看到这儿是不是就眼熟了:service——Dao——entity 很想以前写的经典的三层架构; (不了解记不清也没关系…)
业务逻辑层:
前端控制器接收——客户端请求——内部存储Service类对象, 调用对应方法将参数传给 Service Service业务逻辑层将数据封装处理后——通过Dao实例——调用Dao的方法实现数据库操作 并接收Dao的返回结果——返回值控制器——Model——在到浏览器客户端展示…
总而言之就是, Service 中存在Dao实例, 对前端参数处理给Dao 接收Dao返回结果, 在返回值控制器——页面输出;
详情可结合之前的实例代码:
MyBatis和Spring整合详解:
SpringMVC体系结构
请结合看虽然是分开的并且的控制器输出不过…就这样吧
6. 配置文件:
SSM框架需要两个核心配置文件:
Spring Mybatis 的核心配置文件: applicationContext-mybatis.xml
一般我取的名字;
SpringMVC 的核心配置文件:applicationContext-mvc.xml
一般我取的名字;
与上面的 web.xml 就是针对于这个的处理, 个人一般先写这个… 随便啦, 程序运行时候先执行的是 web.xml
由web.xml 引入Spring核心配置文件的加载…
applicationContext-mybatis.xml
代码语言:javascript复制<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- 引入命名空间:context -->
<context:component-scan base-package="com.wsm." /> <!-- 扫描包下注解:注意对应项目包名~ -->
<!-- 数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/项目名别忘换了" ></property> <!-- 对于url连接,有时候会出现关键子建议使用: <![CDATA[ ... ]]> 包含,避免 < & 等关键字;-->
<property name="username" value="root" ></property>
<property name="password" value="ok" ></property>
</bean>
<!-- 连接工厂: -->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
<property name="dataSource" ref="dataSource" ></property> <!-- 固定name引用数据源bean -->
<property name="configLocation" value="classpath:mybatis-config.xml" ></property> <!-- 引入:mybatis-config.xml个人喜欢起的文件名可换~ -->
</bean>
<!-- MapperScannerConfigurer方式:解决多个Dao映射类,底层实现Dao接口的实例,进行数据库的操作..方法(); -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" >
<property name="sqlSessionFactoryBeanName" value="SqlSessionFactory" ></property> <!-- value="引用上面的连接工厂Id" -->
<property name="basePackage" value="com.wsm.dao" ></property> <!-- 可以包含多个包, value="包1,包2" -->
</bean>
<!-- 还可以进行事务的处理... -->
</beans>
上面文件依赖于:mybatis-config.xml
Mybatis核心配置文件,Mybatis 中引入了 SqlMapper.xml 文件映射
mybatis-config.xml
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "mybatis-3-config.dtd" >
<configuration>
<settings>
<setting name="logImpl" value="LOG4J" /> <!-- 设置MyBatis的log日志实现为LOG4J,即使用log4j实现日志功能。 -->
<!--设置resultMap的自动映射级别,NONE(禁止自动匹配),PARTIAL(默认)自动匹配所有属性,有内部嵌套(association、collection)的除外 且 数据库列与实体类名相同,FULL(自动匹配所有属性)比PARTIAL更强! -->
<setting name="autoMappingBehavior" value="FULL" />
</settings>
<mappers>
<mapper resource="mapper/引入Mapper文件.xml"/>
</mappers>
</configuration>
详情请见:
MyBatis和Spring整合详解:
Spring IOC 和 AOP的扩展
程序运行:web.xml——applicationContext-mybatis.xml——mybatis.config.xml——sql映射文件。- 。 -
applicationContext-mvc.xml
代码语言:javascript复制<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- 引入命名空间:context -->
<context:component-scan base-package="com.wsm.controller" /> <!-- 扫描包下注解:注意对应项目包名,扫描控制器包~ -->
<!-- 使Spring支持mvc注解驱动:别忘了命名空间 mvc -->
<mvc:annotation-driven />
<!-- 配置视图解析器(ViewResolver): -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<!-- <property name="prefix" value="前缀"></property> -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 静态资源的加载:参考下方连接SpringMVC 扩展 -->
<!-- 支持文件上传:参考下方连接 -->
<!-- 配置拦截器: 本篇讲解...请查看目录 -->
<!-- 多视图解析器:不是很清楚... -->
</beans>
SpringMVC 扩展
文件上传
除了这两个主要的核心配置文件还有一些扩展的…)…
log4j.properties
database.properties
…
7. Web.xml 配置
每一个 web项目都有一个 web.xml文件;
部署启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml 进行配置…
SSM框架需要两个核心配置文件:
Spring Mybatis 的核心配置文件: applicationContext-mybatis.xml
一般我取的名字;
SpringMVC 的核心配置文件:applicationContext-mvc.xml
一般我取的名字;
<?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" version="3.0">
<display-name>xxxxxx</display-name> <!-- 描述的项目名 title -->
<!-- 监听器: web项目使用前: 启动对Spring容器加载; -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name> <!-- 指定Spring-mybatis配置文件的位置路径 -->
<param-value>classpath:applicationContext-mybatis.xml</param-value>
</context-param>
<!-- 配置SpringMVC核心控制器:DispatcherServlet
DispatcherServlet:是SpringMVC的核心,负责接收请求 和 响应操作;
-->
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet </servlet-class>
<!-- 初始化参数:通过contextConfigLocation 属性来指定SpringMVC配置文件的位置; -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<!-- 值 1 : 配置标记服务器启动时候加载DispatcherServlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 通过servlet-mapping: 指定对应的Servlet -->
<servlet-mapping>
<servlet-name>mvc</servlet-name> <!-- 指定对于的Servletname -->
<url-pattern>/</url-pattern> <!-- / 匹配所有的请求(不包含.jsp) /* 包含.jsp 即所有的请求都会经过 url-pattern -->
</servlet-mapping>
<!-- 详情请见: -->
<!-- 解决项目中的控制器 中文参数乱码问题:请见下方超链接..(过滤器) -->
</web-app>
详情请参考:
web.xml监听器.
servlet配置详解.
控制器中文参数过滤器.
8.前端控制层 controller
就像以前的Servlet 请参考:SpringMVC体系结构
SpringMVC配置拦截器HandlerInterceptor
:
在介绍SpringMVC拦截器前,先介绍一下SpringMVC的流程
1、 用户发送请求,经过前端控制器Dispacherservlet(Controller的核心)
将请求交给对应的处理器映射HandlerMapping
处理
2、 HandlerMapping
处理请求,返回HandlerExecutionChain
(可能包含拦截器,一定包含自定义的Controller(handler))
上图步骤3: HandlerMapping接口,返回一个HandlerExecutionChain类
HandlerExecutionChain类:由一个handler和若干的HandlerInterceptor构成。
那么这个类的作用就显而易见了,就是将拦截器和handler组合起来执行。就是对handle进行了包装。
上图有关于 HandlerExecutionChain 类方法的说明: 总而言之就是对, 所有拦截器的操作;
3、 前端控制器将Controller
交给处理器适配器HandlerAdapter
处理,处理完成后,返回MV对象(ModelAndView
)
4、 前端控制器将MV交给视图解析器处理ViewResolver
,处理的过程:将MV拆分成Model和view两个对象,并且将model渲染到view视图上,并且将view返回给前端控制器。
5、 最后,前端控制器将视图响应给用户。
springMVC拦截器的实现一般有两种方式
- 第一种方式是要定义的 拦截器的类 ,要实现了Spring的
HandlerInterceptor 接口
- 第二种方式是继承实现了
HandlerInterceptor接口
的类,比如Spring已经提供的实现了HandlerInterceptor接口的抽象类HandlerInterceptorAdapter
继承接口方式实现类要重写所有方法, 考虑到Java单根性 就出现了抽象类, 好处可以选择性重写~
HandlerInterceptor接口方法:
preHandle(): 这个方法在业务处理器处理请求之前被调用,SpringMVC 中的Interceptor 是链式的调用的,参考上图; 该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束; 后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法; 如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。 有点类似于AOP 的前置增强, 每次此请求前都会执行的代码…如果返回false 则后面都不会执行; postHandle(): 这个方法在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用; 所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。 有点类似于AOP 的后置增强, Controller 中代码执行完了 , 都开始返回页面了执行… afterCompletion(): 该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。 有点类似于AOP 的最终增强.
拦截器常用于:
举个例子:
A登录网站查看个人信息消费记录啥啥啥的
B复制了A登录的URL 随便找个电脑,登录之间在URL 中粘贴A的URL; B页面上也看到了A的信息…
是的没错, 不信你可以试试, 而且我听说早期的qq 就可以直接改URL 来进入他人qq空间…(可惜我知道的太晚哎!)
想这种需要事实验证登录状态 而且是否本人的安全性问题…此时就需要拦截器对于每次请求拦截下来检查;
合法了才让你通过~ 不然滚蛋!
实现
- src 中建一个包: com.wsm.interceptors 存放一些拦截器类;
- 包中声明一个拦截器类, 本次使用继承抽象类方式;
PowerInterceptor .Java
package com.zb.interceptors;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.zb.entity.User;
public class PowerInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
//重写抽象类方法preHandle(); 三个参数 request response handler
//登录成功用户都是存在session 中的吧~就直接通过session name形式取到对应的 loginUser用户;
User user = (User)request.getSession().getAttribute("loginUser");
System.out.println("=========" request.getRequestURI());
//这里要注意登录时候 loginUser本就不存在就如果不做判断永远null 永远无法执行下一步了
//对于静态资源也是一种请求, 所以对一些特殊的请求,拦截器是不拦直接放行的~(城门士兵拦将军?)
//request.getRequestURI(); 获取URL中非服务器/域名 即:http://localhost:8080/news/main/list.jsp 返回:/news/main/list.jsp
//startsWith(“”); / startsWith(“”,int); Java String类方法, 检查字符串中是否存在对应的前缀 返回true; int 表示从第几个字符开始与比较参数;
if(request.getRequestURI().startsWith("/myrole/login") || request.getRequestURI().startsWith("/myrole/static")){
return true;
//上述方法显而易见, myrole 就是项目名~ login/static 就是请求名, 注意这里是SpringMVC login也可以是对应控制器注解的 对应名~
}
//user !=null 表示已登录,返回true 放行~
if(user!=null){
System.out.println("用户登录成功");
return true;
}
//如果取不到 loginUser登录用户为null 表示未登录无法访问!返回false;
//并跳转至 login页面使其登录
System.out.println("用户没有登录");
PrintWriter out=response.getWriter();
out.println("<html>");
out.println("<script>");
out.println("window.open ('" request.getContextPath()
"/index.jsp','_self')");
out.println("</script>");
out.println("<html>");
return false;
}
}
applicationContext-mvc.xml
配置拦截器:
!--配置拦截器, 多个拦截器,顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<!--
/**的意思是所有文件夹及里面的子文件夹
/*是所有文件夹,不含子文件夹
/是web项目的根目录
-->
<mvc:mapping path="/**" />
<!-- 需排除拦截的地址:遇到这样的请求并不会拦截验证~直接通过~ -->
<!-- <mvc:exclude-mapping path="/userController/login"/> 有时候因为版本问题失效可按照上了手动Java代码实现..-->
<bean id="commonInterceptor" class="com.wsm.interceptors.PowerInterceptor"></bean> <!--这个类就是我们自定义的Interceptor -->
</mvc:interceptor>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>