Spring简介
概念(是什么)
2003年兴起的一个轻量级的,使用IOC和AOP思想的Java一站式开发框架
为了简化企业级应用开发
名词解释
轻量级
三个字,内存小。
Spring框架使用的 jar 比较小,一般1M甚至更小(几百kb),核心功能所需的jar包加起来也只不过3M左右。
Spring框架运行占用的资源少,运行效率高。
IOC
一种编程思想,即Inversion of Control,控制反转,缩写IOC。就是由Spring IOC容器管理对象,而非传统实现中由程序代码直接控制。
也就是说,将项目中以前自己创建一些对象转而交给Spring框架统一管理(这里Spring框架可以额外对对象进行功能的添加),需要时从框架中获取即可。
在直白一点,把对象的控制权反转给Spring框架。
后面再具体细说。
AOP
全称Aspect Oriented Programming ,即面向切面编程,将一些公共功能进行抽取,不需要在自己的方法中直接显示调用,而是由一个代理对象去调用,然后在调用我们方法时,可以将公共的方法横切进来.
首要先大概有个概念,后面还会说到。
一站式框架
Spring的核心就是统一管理程序中的对象,提供aop,同时支持dao和web层进行封装,还可以集成管理其他框架和组价。
可以把Spring想象成Java的后端管家。
Spring搭建
1.导入核心功能的jar(前提是先创建一个javaee项目)
现在pom.xml文件里面配置依赖
<!--导入核心jar-->
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
为了方便测试,再此导入一个junit的jar包,也就是可以单独测试某一个方法
嫌麻烦的,大家也可以试试。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>provided</scope>
</dependency>
配置完成后一定要记得刷新。
2.创建模型类
这里我之前也有多次展示,这里简单创建一下,定义两个属性以及他们的get,set方法以及有参和满参的构造方法即可。
3.创建spring配置文件,并配置需要让spring管理的类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置需要spring管理的类-->
<!--
bean的作用域scope
singleton 默认作用域 将单个bean定义绑定到单个对象实例
prototype 单个bean可以被绑定到多个对象实例
-->
<bean id="user" name="user2" class="com.ffyc.spring.model.User">
<property name="id" value="100"></property>
<property name="name" value="jia"></property>
</bean>
</beans>
4.启动spring,获取我们需要的对象
这里前面配置的bean的id和name都可以都可以表示Spring管理个这个模型类
import com.ffyc.spring.model.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUser1 {
@Test
//测试spring
public void test(){
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("user",User.class);
User user2 = applicationContext.getBean("user2",User.class);
System.out.println(user);
System.out.println(user2);
}
}
结果如下:
可以看到创建的user对象和user2对象是同一个。
这里又牵扯到一个作用域,默认是一个,后面提到我会细说。
IOC
反转控制
前面我刚简单讲过,就是控制反转。
读作"反转控制",相对正向控制,可能更好理解。一种设计思想,将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。
IOC容器
IOC 容器是具有依赖注入功能的容器,负责对象的实例化、对象的初始化,
对象和对象之间依赖关系配置、对象的销毁、对外提供对象的查找等操作
对象的整个生命周期都是由容器来控制。
实例化:创建对象
ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring.xml");
//该语句已经将对象创建好,放在spring容器中了,需要时就可以直接拿出来用
BeanFactory接口 是spring框架最顶级的接口,定义基本的对象管理的方法
ApplicationContext接口是BeanFactory的子接口,扩展一些其他的功能.
ClassPathXmlApplicationContext("配置文件");负责具体对象管理的实现类
初始化:对象与对象之间的依赖关系
对外提供查找:getbean()
需要使用的对象都由 ioc 容器进行管理时,不需要我们再去手动通过 new 的方式去创建对象,
由 ioc 容器直接帮我们组装好,当我们需要使用的时候直接从 ioc 容器中直接获取就可以了。
工作流程:
POJOs :不限于模型类,在spring中其他别的类也可以是pojo
Configuration Metadata:配置元文件(在spring.xml中需要将哪些类交给spring管理,就在其中将该类配置进来)
TheSpring Container spring容器(spring框架)。
pojo对象在配置元文件后加载到IOC容器反转产生需要的对象。
正控
使用对象时,直接自己负责创建对象。
反控
使用对象时,直接从Spring容器中获取,不关心创建的过程,就是说将创建对象的控制权交给Spring框架。
Spring Bean管理
XML配置
标签
<bean> 配置需要spring管理的类
属性
id 生成的对象名
class 全类名(地址)
name 对象别名(可以多个)
scope 作用域
singleton(默认值) 将单个bean定义绑定到单个对象实例(在 Spring 中只存在一个 bean 实例)
prototype 将单个bean定义绑定到多个对象实例
request
依赖注入
a中需要b就会自动将b注入到a中去。
Spring框架在创建对象时,对象中有属性,以及一些关联的其他对象,Spring为这些属性和关联的对象进行赋值,这个过程就称作依赖注入。
xml实现
set注入,set方法注入到对象中。
<bean id="user" name="user2" class="com.ffyc.springpro.model.User" scope="prototype">
<property name="id" value="100"></property>
<property name="name" value="jim"></property>
</bean>
<bean id="userDao" class="com.ffyc.springpro.dao.UserDao"></bean>
<bean id="userService" class="com.ffyc.springpro.service.UserService">
<property name="userDao" ref="userDao"></property>
</bean>
<!--将userDao注入到userService的userDao属性中-->
构造方法注入
<bean id="user" name="user2" class="com.ffyc.springpro.model.User" scope="prototype">
<constructor-arg name="id" value="100"></constructor-arg>
<constructor-arg name="name" value="tom"></constructor-arg>
</bean>
依赖注入一般伴随控制反转,所以使用了依赖注入一般不直接创建对象调用其中的方法,这里就会报错----空指针异常,控制反转会进行依赖注入,而直接new一个对象则没有初始化。
注解方式
实现
1.配置依赖,导入Spring aop jar
2.配置spring扫描
在xml约束文件中导入
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
3.开启注解扫描
使用时,需要配置包名,Spring对这个包进行扫描
< context :component-scan base-package ="包名" > </ context :component-scan >
4.注解创建对象
@Component model类
@Repository dao类
@Service service类
5.依赖注入
@Autowired 自动注入,默认以类型注入,可以添加到1属性上也可以添加到方法上,添加到属性上可以不写出set方法
@Qualifier 通过名字去找,并注入 通过value去找
@Resource Spring 提供了对 jdk 中@Resource 注解的支持 可以按名字也可以按类型匹配,默认时名字,名字找不到时按类型找。
XML配置与注入方式的对比
注解的优点:方便,直观,高效,简捷
注解缺点:以硬编码的方式写入到java中,修改时得修改源代码并重新编译
xml配置的优点:配置与代码分离,需要修改的时候直接在xml配置中修改,不需要重新编码,直接重启服务器即可。
xml配置的缺点:编写麻烦,如果项目大一点,代码量相对更为庞大。
Spring JDBC搭建
以前获取数据库连接对象
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JDBCUtil {
public static void main(String[] args) throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("");
dataSource.setUsername("");
dataSource.setPassword("");
dataSource.setDriverClassName("");
dataSource.setInitialSize(10);//初始化连接个数
dataSource.setMaxActive(30);//最大连接个数
DruidPooledConnection connection = dataSource.getConnection();
connection.close();//改变属性,一般不会销毁,用完重新推到数据库连接池
DriverManager.getConnection("","","");//
}
}
使用spring框架管理
1.配置依赖,导入相关jar
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
2.导入属性文件
创建一个db.xml专门配置数据库连接,分类管理
导入到spring.xml中
<import resource="classpath:db.xml"></import>
<!--使用注解时,需要配置一个包名,spring对该包进行扫描-->
<context:component-scan base-package="com.ffyc.spring"></context:component-scan>
<!--导入属性文件-->
<context:property-placeholder location="classpath:config.properties"/>
3.配置管理数据源对象
<!--配置阿里巴巴的数据库连接管理对象-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driverName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${upassword}"></property>
<property name="initialSize" value="10"></property>
<property name="minIdle" value="5"></property>
<property name="maxActive" value="20"></property>
<property name="maxWait" value="2000"></property>
</bean>
<!--在配置文件中创建 JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
测试
import com.ffyc.spring.model.User;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Repository
public class UserDao {
@Resource
JdbcTemplate jdbcTemplate;
public void testTemplate(User user){
jdbcTemplate.update("insert into admins(account,password) value (?,?)","aaa","111");
List<User> list = jdbcTemplate.query("select * from admins where id > ?", new RowMapper<User>() {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user1 = new User();
user1.setId(resultSet.getInt("id"));
user1.setName(resultSet.getString("account"));
return user1;
}
},1);
}
}
package com.ffyc.spring.service;
import com.ffyc.spring.dao.UserDao;
import com.ffyc.spring.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service(value = "userService")
public class UserService {
/*
Service(业务处理层)
接收web层数据,判断处理,将最终结果传递到dao层
dao层如果返回数据
*/
@Autowired
UserDao userDao;
public void saveUser(User user){
userDao.testTemplate(user);
}
}
AOP
简介
是什么
aop,全称Aspect Oriented Programming。面向切面编程,是对面向对象编程的补充。
aop是将程序中的非业务代码进行抽取,将非业务代码与业务代码相隔离,降低业务代码与非业务代码的耦合度;然后通过一个代理对象在业务代码中调用非业务代码,提高代码灵活性与开发效率的一种编程思想。
如果说面向对象编程是战略层面,那么面向切面变成就是战术层面。
aop这一思想核心就是使用一个代理对象,在中间帮忙调用,为我们的程序添加功能.
原理
优点
减少代码重复,提高了代码的灵活性,提高了开发效率
实现
在实现前先解释一下几个专业术语
连接点:类中可以被增强的方法,像下面的insertAdmin和updateAdmin 增加了新功能 切入点:类中有很多方法可以被增强,只有被增强的才是切入点 通 知:方法被增强的功能(像日志等) 分前置通知,后置通知,环绕通知最终通知,异常通知 切 面:把通知加到连接点的过程 目 标:代理的目标对象(真正做这件事的类,AdminDao) 代理(Proxy):向目标对象应用通知时创建的代理对象
AspectJ
AspectJ是一个基于aop思想的一个组件,它拥有强大的AOP功能,实现方式更为简捷,操作简单,支持注解开发。本次SpringAOP实现就借助AspectJ框架。
SpringAOPxml配置实现
1.导入aspectJ aop框架的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.把所有的通知抽取到一个类中
实例:
public class CommonUtil{
public void saveLog(){
System.out.println("保存时间" + new Date() );
}
}
3.在spring配置文件中, 配置切入点和通知的关系
<!--配置aop-->
<bean id="CommonUtil" class="com.ffyc.spring.util.CommonUtil"></bean>
<aop:config>
<!--配置切入点-->
<!--
execution是表达式的主体
第一个*是返回的类型*代表所有类型
.就是包下的层级关系
.后面可以跟*表示该包下的
方法也可用*号代替,表示所有的方法
方法括号中为参数 ..表示任意参数
-->
<aop:pointcut id="insertAdmin" expression="execution(* com.ffyc.spring.dao.AdminDao.insertAdmin(..))"/>
<aop:aspect ref="CommonUtil">
<!--前置通知,在方法执行前被调用-->
<!--<aop:before method="saveLog" pointcut-ref="allMethod"/>-->
<!--后置通知,在方法执行完成后被调用 在后置通知前方法出现异常就不再调用-->
<!--<aop:after-returning method="saveLog" pointcut-ref="allMethod"></aop:after-returning>-->
<!--最终通知 无论方法是否出现异常都会在最终调用-->
<!--<aop:after method="saveLog" pointcut-ref="allMethod"></aop:after>-->
<!--异常通知 只有出现异常才会调用-->
<!--<aop:after-throwing method="saveLog" pointcut-ref="allMethod" throwing="e"></aop:after-throwing>-->
<!--<aop:after-throwing method="saveLog" pointcut-ref="allMethod"></aop:after-throwing>-->
<!--环绕通知-->
<aop:around method="saveLog" pointcut-ref="insertAdmin"></aop:around>
</aop:aspect>
</aop:config>
测试环绕通知
//环绕通知
public void saveLog( ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("前置");
try {
Object[] objects = proceedingJoinPoint.getArgs();
System.out.println(Arrays.toString(objects));
//调用目标切入点
System.out.println("保存时间" + new Date() );
proceedingJoinPoint.proceed();
System.out.println("后置");
}catch (Throwable e){
System.out.println(e.getMessage()+ "异常通知");
}
System.out.println("最终通知");
}
public void insertAdmin(int id,int no){
//前置
System.out.println("保存");
System.out.println(1/0);//测最终通知和后置通知
}
SpringAOP注解实现
开启自动代理
<!--开启自动代理-->
<aop:aspectj-autoproxy />
在使用注解方式的类上加入@Aspect 标签
四个通知注解方式实现
//@Before("execution(* com.ffyc.spring.dao.AdminDao.insertAdmin(..))")
//@After("execution(* com.ffyc.spring.dao.AdminDao.insertAdmin(..))")
//@AfterReturning("execution(* com.ffyc.spring.dao.AdminDao.insertAdmin(..))")
//@AfterThrowing(value = "execution(* com.ffyc.spring.dao.AdminDao.insertAdmin(..))",throwing = "e")
public void saveLog(Throwable e){
System.out.println("保存时间"+new Date()+"异常信息:"+e.getMessage());
}
环绕通知
@Around(value = "execution(* com.ffyc.spring.dao.AdminDao.insertAdmin(..))")
public void saveLog(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("前置通知");
try{
Object [] objects =proceedingJoinPoint.getArgs();//获取参数
System.out.println("保存时间" + new Date() );
proceedingJoinPoint.proceed();
System.out.println("后置通知");
}catch (Throwable e) {
System.out.println("异常通知 "+"异常信息:"+e.getMessage());
}
System.out.println("最终通知");
}
可以自己可是一下是否与想象的结果相同
小结:
aop:就是使用代理对象方式将非业务代码抽取出来,通过代理对象来进行调用,这样就可以将业务代码与非业务代码隔离开,降低代码的耦合度。
aop两种实现方式:xml配置方法与注解方式
Spring 事物管理
事物
即数据库事物,属于数据库的功能。就是数据库中多条sql语句操作做成的单元,在执行时,要么都执行成功,要么都不成功,保证数据库事物的一致性。
举个例子:
两个银行帐户A和B要进行转账操作
A:-500
B:+500
一次性要执行俩个sql语句,那么要么A-500,同时B+500,要么都不加不减,来保证一致性原则。
Spring事物
spring如何进行事务管理呢,有两种方式分别为编程式事物和声明式事物。
编程式事物管理
在代码中手动提交和回滚(现在很少使用)
声明式事物管理
建立在aop基础上,在事物管理中运行的方法添加注解标签声明
Spring声明式事物管理
xml配置
注解
1.配置spring 事务管理器
<!-- 配置 spring 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2.添加xml约束规则条件
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
只有成功添加约束规则才能开启事物管理
3.开启事物管理
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional标签
添加到类上,该类中所有方法都会添加事物管理
添加到方法上,只有该方法进行事物管理
如果这个方法中出现异常,那么该方法中的事物都不会提交。
事物管理一般加到service层。
声明式事物管理不生效的场景
1.注解@Transaction在非public 标签上
2.使用try{}catch(){}处理了
3.默认情况下出现编译器异常
解决方法:修改配置@Transaction(roolbackFor =Exception.class)
*4.@Transaction事物行为配置错误
5.数据库引擎不支持事物管理
6.使用非代理对象调用一个有事物管理的方法
Spring事物传播行为
首先要有两个方法,并且相互调用
例如:A调用B,B创建一个新事物,还是加入到A中运行,取决于B事物的传播行为
Spring事物传播行为是spring框架提供的特有的控制
spring中有七种事物传播行为
1.propagation-Required
A没有事物调用有事物的B,B会创建一个对象。在事务中运行,B异常不会影响A;
A有事物时,两个事物合二为一,一个出现异常,会相互影响。
2.PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
3.PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
4.PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
5.PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
6.PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED
Spring集成Mybatis
SpringWeb
简介
SpringWeb 是 spring 框架中的一个模块,基于 Servlet API 构建的原始web 框架;
是spring框架中的一部分,是对java后端web层进行的封装,和spring框架可以无缝对接,是基于servletAPI的实现
历史
以前 ssm(spring strust2 mybatis) ssh(spring strust2 hibernate)
现在ssm(spring springweb mybatis)
特点
1.SpringWEB 是 spring 家族原生产品,与 IOC 容器等基础设施无缝对接.
2.基于原生的 Servlet,提供了一个前端控制器 DispatcherServlet ,开发者无须额外开发控制器对象
3.可以自动绑定用户输入,并正确地转换数据类型.
4.代码清新简洁,大幅度提升开发效率.
5.内部组件化程度高,可插拔式组件即插即用
6.性能卓著,尤其适合现代大型、超大型互联网项目要求.
搭建SpringWeb
1.配置依赖
<!--SpringWeb-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.配置DispatcherServlet
配置spring核心请求分发器
请求映射
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.开启springMVC注解
开启springWeb注解
修改约束条件
开启springMVC注解
<!--开启springmvc注解-->
<mvc:annotation-driven></mvc:annotation-driven>
4.处理器类的搭建
@RestController 用于标记在一个类上,使用它标记的类就是一个 SpringWEB
控制器类
@RequestMapping 配置请求地址
method = "RequestMethod.Post/Get"
@GetMapping(path="/path")
Spring 配置中指定了自动扫描的 basepackage 后,Spring 会扫描这些包以及子包中的使用了
@RestController 标识的类,然后将类加入到 Spring IOC 容器中,注入依赖。
这是一个测试
package com.ffyc.ssm.web;
import com.ffyc.ssm.model.Admin;
import com.ffyc.ssm.service.LoginService;
import com.ffyc.ssm.util.CommonResult;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping(path = "/loginCtl")
public class LoginController {
@Autowired
LoginService loginService;
//封装到Admin对象
@PostMapping(path = "/login")
public CommonResult login(@RequestBody Admin admin){
System.out.println(admin.getAccount());
System.out.println(admin.getPassword());
CommonResult commonResult = new CommonResult(200,admin,"登录成功");
System.out.println(commonResult);
return commonResult;
}
@GetMapping(path = "/test1")
public String test1(){
System.out.println("test1");
return "commonResult1";
}
@GetMapping(path = "/test2")
public String test2(){
System.out.println("test2");
return "commonResult2";
}
/*
//起别名与拿到请求头中的信息
@GetMapping(path = "/login")
public String login(String account,
@RequestParam(value = "pwd",required = true,defaultValue = "258") Integer password,
@RequestHeader("User-Agent") String userAgent){
System.out.println(account);
System.out.println(password);
System.out.println(userAgent);
return "success";
}
*/
/*
//直接接收
@GetMapping(path = "/login")
public String login(String account,Integer password){
System.out.println(account);
System.out.println(password);
return "success";
}
*/
/*
//HttpServletRequest方法
@GetMapping(path = "/login")
public String login(HttpServletRequest request){
System.out.println(request.getParameter("account"));
System.out.println(request.getParameter("password"));
return "success";
}
*/
/*
自动封装,要求形参的名字与请求中的名字一致,类型也一致
*/
//@RequestMapping(path = "/test",method = RequestMethod.GET)
@GetMapping(path = "/test")
public String test(){
System.out.println("请求成功");
return "hello word";
}
/*
//@RequestMapping(path = "/test2",method = RequestMethod.POST)
@PostMapping(path = "/test2")
public String test2(){
System.out.println("请求成功");
return "hello word";
}
*/
}
运行流程
前端控制管理器:接收前端发送的所有请求,调用HandlerMapping解析请求中的地址以及当HandlerMapping解析出有对应的HandlerAdapter时,调用HandlerAdapter去处理请求
处理器映射器:解析请求中的地址,是否有对应的处理器,如果有调用时有拦截器,则进行拦截器相应处理。
拦截器:经过处理器映射器之后可能会进入拦截器,拦截器可以决定请求是否进入处理器适配器
处理器适配器:按照特定规则去执行handler
自定义处理器Handler: 自己写的,处理请求响应数据。
概括:用户请求,先经过过滤器到达前端控制器,在前端控制器调用处理器映射器解析的地址,查询是否有对应的处理器,返回给前端控制器,如果经过拦截器,进行拦截器中操作来决定是否调用处理器适配器对这个请求进行处理,处理器会调用我们自定义的处理器对用户请求进行处理响应。
其他的一些操作处理
1.时间的转换
在需要进行时间转换的属性上使用转换标签
@DateTimeFormat(pattern = "yyyy-MM-dd")
2.中文乱码处理
<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>
3.返回JSON处理
这里我使用了commonResult这么一个类进行封装
package com.ffyc.ssm.util;
/*
用来封装后端数据
*/
public class CommonResult {
private int code;//自定义的状态
private Object data;//数据 对象,集合
private String message;//消息
public CommonResult(int code, Object data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public CommonResult(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "CommonResult{" +
"code=" + code +
", data=" + data +
", message='" + message + '\'' +
'}';
}
}
拦截器
简介
实现
1.创建一个类DemoInterceptor实现HandlerInterceptor接口
重写preHandle方法
2.配置拦截器
在spring.xml中
为test1配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/loginCtl/login"/>
<mvc:exclude-mapping path="/loginCtl/test2"/>
<bean id="demo" class="com.ffyc.ssm.util.DemoInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>