Spring+SpringMVC+MyBatis 整合(+拦截器) 详:

2024-08-06 13:17:26 浏览数 (2)

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 一般我取的名字;

代码语言:javascript复制
<?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
代码语言:javascript复制
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 配置拦截器:

代码语言:javascript复制
!--配置拦截器, 多个拦截器,顺序执行 -->
    <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>

0 人点赞