简介:
是于2003年兴起的一款轻量级的,非侵入式的IOC和AOP的一站式的java开发框架,为简化企
业级应用开发而生。
轻量级的: 指定是spring核心功能的jar包不大 非侵入式的: 我们的业务代码不需要继承或实现
spring中任何的类或接口 IOC: 控制反转 以前项目都是在哪儿用到对象,在哪儿new, 把生成对象的
权利反转给spring框架 AOP: 面向切面编程 一站式框架: 提供核心功能,主要是IOC,创建管理对象
提供面向切面编程,增强程序扩展 对数据访问层进行了封装(重点在于事务管理) 对web层进行封
装,使得请求更加便捷 体系结构 提供核心功能,主要是IOC,创建管理对象. 提供面向切面编程,增强
程序扩展 对数据访问层进行了封装(重点在于事务管理) 对web层进行封装,使得请求更加便捷
spring可以用来管理对象(创建,存储),可以把spring认为是一个容器. 也可以从IOC容器,spring容器。
环境搭建:
1.Maven 导入 spring 核心基础 jar
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.编写 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">
<bean id="user" class="com.ff.spring.bean.User"> </bean>
</beans>
控制反转 Inverse of Control
spring中的bean的管理:
1.xml配置方式
<bean id="admin" name="admin2" class="com.ffyc.ssm.model.Admin" scope="prototype">
<!--<property name="id" value="10"></property>
<property name="account" value="admin"></property>-->
<constructor-arg name="id" value="100"></constructor-arg>
<constructor-arg name="account" value="admins"></constructor-arg>
</bean>
在spring创建对象(控制反转)时,还需要为我们的对象属性进行初始化赋值,
这个过程称为依赖注入
注入方式:
1.属性get set方法注入
2.构造方法注入
spring注解管理bean:
开启注解扫描:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--
开启注解扫描
-->
<context:component-scan base-package="com.ffyc.ssm"></context:component-scan>
<!--开启自动代理-->
<aop:aspectj-autoproxy/>
<import resource="classpath:db.xml"></import>
<!-- <import resource="classpath:aopdemo.xml"></import>-->
</beans>
注解创建对象
注解方式注入属性
@Autowired 是 Spring 提供的注解,可以写在字段和 setter 方法上。如果写在字段上,那么就
不需要再写 setter 方法。默认情况下它要求依赖对象必须存在,如果允许 null 值,可以设置它的
required 属性为 false。
byType 自动注入该注解默认使用按当前类型自动装配 Bean 的方式。
byName 自动注入如果我们想使用按照名称(byName)来查找,可以结合@Qualifier 注解一
起使用。需要在引用属性上联合使用注解@Autowired 与@Qualifier。@Qualifier 的value 属性用
于指定要匹配的 Bean 的 id 值。
JDK 注解@Resource 自动注入Spring 提供了对 jdk 中@Resource 注解的支持。@Resource
注解既可以按名称匹配 Bean,也可以按类型匹配 Bean。默认按照 ByName 自动注入
byName 注入引用类型属性@Resource 注解指定其 name 属性,则 name 的值即为按照名称
进行匹配的 Bean 的 id。
注解与 XML 的对比
spring框架中的JDBC功能
1.jdbc封装: JdbcTemplate(了解即可 后面常用mybatis) 事务管理(重点)
2.ioc实际的应用
搭建
<!-- 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>
2.导入属性文件
<context:property-placeholder location="config.properties"/>
3.管理数据源对象
spring 管理与数据库链接 (数据源)
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
<propertyname="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pwd}"></property>
<property name="initialSize" value="10"></property>
<property name="minIdle" value="5"></property>
<property name="maxActive" value="20"></property>
</bean>
4.在配置文件中创建 JdbcTemplate
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
AOP 设计模式
简述:
将程序中一些非业务代码进行提取,在不需要修改原来的代码情况下,为程序添加额外的功
能。非业务代码(验证功能,打印日志,提交事务,统一异常功能等)。
通过一个代理对象,帮助我们调用某个方法。底层实现: 使用的是动态代理模式。AOP思想不是spring框架特有的,知识Spring框
架使用了这个思想。
开发好一个版本后,后期如果需要添加新的功能,就需要修改原来的代码, 加入调用新功能的代
码. 这样开发就很麻烦,会存在大量的冗余代码.
AOP-->AOP为Aspect Oriented Programming的缩写 面向切面编程
AOP是一种编程技巧,不是代替OOP的,可以使的业务逻辑和非业务逻辑代码进行隔离, 使得各个部
分之间的耦合度降低了. 提高程序的复用性,提高开发效率。
具体实现
Spring中引入了一个叫AspectJ的aop框架。AspectJ 是一个基于 Java 语言的 AOP 框架,它
提供了强大的 AOP 功能,且其实 现方式更为简捷,使用更为方便,而且还支持注解式开发。所以,
Spring 又将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中。
1.下载 AOP 相关 jar
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.有两种实现方式:
1)xml配置方式
<bean id="myutil" class="com.ffyc.ssm.util.MyUtil"></bean>
<aop:config>
<!--配置切入点-->
<aop:pointcut id="saveAdmin" expression="execution(* com.ffyc.ssm.dao.AdminDao.saveAdmin(..))"/>
<!--将通知与切入点进行配置,生成的代理对象就知道如何调用-->
<aop:aspect ref="myutil">
<!--<aop:before method="printLog" pointcut-ref="saveAdmin"></aop:before>
<aop:after-returning method="printLog" pointcut-ref="saveAdmin"></aop:after-returning>
<aop:after method="printLog" pointcut-ref="saveAdmin"></aop:after>
<aop:after-throwing method="exceptionAdvice" pointcut-ref="saveAdmin" throwing="e"></aop:after-throwing>-->
<aop:around method="aroundAdvice" pointcut-ref="saveAdmin"></aop:around>
</aop:aspect>
</aop:config>
2)注解方式
启动 AspectJ 支持:<aop:aspectj-autoproxy />
@Component
@Aspect
public class AOPDemo {
@Before("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void before(){
System.out.println("before");
}
@After("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void after(){
System.out.println("after");
}
@Around("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void around(ProceedingJoinPoint point) throws Throwable {
System.out.println("start");
point.proceed();
System.out.println("end");
}
@AfterThrowing(value = "execution(* com.ff.spring.demo1.dao.UserDao.*(..))",throwing = "e")
public void afterthrow(Throwable){
System.out.println("afterthrow");
}
@AfterReturning("execution(* com.ff.spring.demo1.dao.UserDao.*(..))")
public void afterreturn(){
System.out.println("afterreturn");
}
}
spring事务管理
事务管理是数据库提供得一种功能,为了保证数据在执行过程中得准确性。事务管理是管理一组中有多个执行单元,事务可以看作是由对数据库若干操作组成的一个单元。
一个事务就是一个执行单元,一个单元中可以包含多条sql,事务的基本特征是原子性特征,就是保障一个事务中的多条sql要么都执行,要么都不执行Process terminated
数据库事务? 数据事务,本身是属于数据库自己所有的特性,事务是数据库自身提供的保障数据一致性的功能,一个事务就是一个执行单元,一个单元中可以包含多条sql, 事务的基本特征是原子性特征,就是保障一个事务中的多条sql要么都执行,要么都不执行jdbc自动事务提交,
mybatis里面,事务默认不自动提交,需要我们在程序中手动提sqlsession.commit()
spring框架里面提供事务管理功能: 就是spring框架把提交事务的功能帮助我们管理起来了,封装好了. 实现本质,使用了AOP的思想,代理我们来对事务进行管理.
关系型数据库事务基本特征:
1.原子性特性
2.隔离性
3.持久性
4.一致性
spring框架里面提供事务管理功能:
就是spring框架把提交事务的功能帮助我们管理起来,封装好。
spring中的事务管理有两种:
1.编程式事务管理:
这 种 方 式 需 要 注 入 一 个 事 务 管 理 对 象TransactionTemplate ,然后在我们代码中需要
提交事务或回滚事务时自己写代码实现。
transactionTemplate.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
jdbcTemplate.update("insert into admin(account,password)value(?,?)","cccc","2222");
int i = 10/0;
jdbcTemplate.update("insert into admin(account,password)value(?,?)","aaaa","1111");
return null;
}
});
2.声明式事务管理:
声明式事务管理建立在 AOP 基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。
使用注解标签管理,底层实现的原理就是AOP的思想,是方法级别的,在执行某一个方法
时,添加额外的事务管理功能。
声明式事务管理有两种方式:
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启注解事务功能-->
<tx:annotation-driven transaction-manager="transactionManager"/>
1)基于 xml 配置
2)基于注解实现
@Transactional标签用法:声明式注解管理事务: 一般把 @Transactional标签添加在service中,
@Transactional可以添加在service层中类上,类中所有的方法都会添加事务管理功能
@Transactional如果只添加在某个方法上,那么表示此方法在事务管理中进行
@Transactional 声明式注解事务管理,有以下情况会失效:
1.修饰一个非public的方法,底层权限只针对public修饰的方法
2.方法中的异常被catch捕获处理了
3.默认情况下出现编译期异常,事务不生效 默认情况下只对运行期异常进行捕获
@Transactional(rollbackFor = RuntimeException.class) 我们可以把其修改为
@Transactional(rollbackFor = Exception.class),这样就可以处理任意的异常
4.@Transactional事务传播行为设置错误
5.数据库引擎不支持事务, 数据库引擎是mysql底层具体的一种数据处理实现的机制 常用的两
个引擎: innodb(支持事务功能),myisam(不支持事务)
6.在一个非事务方法中使用this(原始的对象==自己new出来的对象)
Spring事务传播行为
1.事务功能本质上属于mysql数据库
2.spring事务管理,指的是spring框架,可以帮助我们进行事务开启,提交,回滚
Spring事务传播行为(了解)
一个方法调用另一个方法,之间会产生传播 A方法中 调用了B方法 B方法事务应该如何去执行 B事务是一个独立的事务呢 (独立的 就表示B出现了问题,不影响A) 还是B事务合并到A方法事务中呢
spring事务传播行为,是spring框架自己额外增加的功能.不属于事务实际提供者mysql.
spring为了在更复杂的业务逻辑调用时,提供的一个功能. 要么多个事务嵌套在一个中, 要么多个事务相互独立运行.
spring中的事务传播行为总共有7种:
PROPAGATION_REQUIRED 没有事务就新建一个事务,如果有,就加入到当前事务中 PROPAGATION_REQUIRES_NEW 无论是否有事务存在,都会创建新的事务,把当前事务挂起 PROPAGATION_SUPPORTS 支持当前事务,如果没有事务,就以非事务方式执行 PROPAGATION_NEVER 不需要事务,如果有事务会报异常
事务传播行为不能是同一个类中的方法相互调用. 必须是一个类中的方法,调用另一个类中的方法
Spring集成MyBatis
ssm(早期指的是spring+struts2+mybatis)
ssm(现在指的是spring+springMVC(springWeb)+mybatis) spring+mybatis
1.新建一个javaEE web项目
2.加入相关依赖的坐标
<dependencies>
<!--mybatis,mysql,druid数据源,junit-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit 单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>provided</scope>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--Spring context aop jdbc-->
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
</dependencies>
3.创建相应的包和类 以登录为例
4.创建并配置spring和mybatis配置文件 复制mybatis配置文件,并删除其中不需要的内容
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--mybatis核心配置文件-->
<!--常用设置-->
<settings>
<!--启用日志功能,在运行时,可以将实际执行的sql细节打印到控制台-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--<setting name="autoMappingBehavior" value="FULL"/>-->
<!--<setting name="cacheEnabled" value="false"/>-->
</settings>
<!--配置类型简称-->
<typeAliases>
<package name="com.ffyc.ssm.model"/>
</typeAliases>
</configuration>
创建spring配置文件
Spring.xml
<!--开启注解扫描-->
<context:component-scan base-package="com.ffyc.ssm"></context:component-scan>
<!--开启自动代理-->
<aop:aspectj-autoproxy/>
数据库连接配置
集成mybatis配置
1)导入相关jar包
<!--Spring集成MyBatis框架-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
2)配置 sqlSessionFactory
<!--让Spring框架生成SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--配置Mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--扫描sql映射文件-->
<property name="mapperLocations" value="classpath:mappers/*Mapper.xml">
</property>
</bean>
3)指定生成接口代理
<!--让Spring框架生成接口代理对象-->
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ffyc.ssm.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
SpringWeb
spring框架中的模块之一
SpringMVC:
1.用户发起请求 ip:端口/项目名/类地址/方法地址
<url-pattern>/</url-pattern>
所有的请求都可以到达DispatcherServlet
2.DispatcherServlet请求分发 核心的 springweb底层用的就是一个servlet接收用户所有请求,并分发给对应的映射处理器,适配器
3.HandlerMappering映射处理器,用来解析请求中的地址,有没有对应的处理器类,如果本次又对应的拦截器,会执行相应的拦截器
4.HandlerAdapter 处理适配器:封装请求中的参数
5.到达自己创建的处理器,接收参数,处理,响应
SpringWeb层搭建:
1.导入jar
<!--SpringWeb-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.在web.xml文件中配置DispatcherServlet
1)配置 spring 核心请求分发器
<servlet>
<servlet-name>application</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--配置读取spring配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
<!--控制servlet创建,初始化的时间,-1第一次访问时创建,>=0是服务器启动时创建-->
<load-on-startup>0</load-on-startup>
</servlet>
<!-- 请求映射,配置映射地址 -->
<servlet-mapping>
<servlet-name>application</servlet-name>
<url-pattern>/</url-pattern> <!--表示所有请求都会进去到DispatcherServlet-->
</servlet-mapping>
2)开启 springmvc 注解
<mvc:annotation-driven></mvc:annotation-driven>
3.添加spring配置文件,开启springweb的注解
@RequestMapping(path = "/loginCtl")
可以在类和方法上使用:
在类上面使用,整个项目中必须是唯一的,不能重复;
在方法上定义,同一个类中地址也必须是唯一的;
@RequestMapping(path = "/test",)没有指定请求方式get/post请求都可以访问
@GetMapping(path = "/test") get请求
@PostMapping(path = "/test") post请求
4.创建自己的处理器,为类,方法定义地址
5.将ssm项目发布到tomcat中访问
SpringWeb层的控制器类中如何使用
web层:接收 处理 响应
1.@RestController修饰控制器类
2.@RequestMapping(path = "/loginCtl")
@RequestMapping(path = "/loginCtl")
可以在类和方法上使用:
在类上面使用,整个项目中必须是唯一的,不能重复;
在方法上定义,同一个类中地址也必须是唯一的;
@RequestMapping(path = "/test",)没有指定请求方式get/post请求都可以访问
@GetMapping(path = "/test") get请求
@PostMapping(path = "/test") post请求
3.如何接收请求中的数据
3.1使用request对象接收 rrequest.getParameter()
@GetMapping(path = "/test")
public String test(HttpServletRequest request, HttpServletResponse response){ System.out.println(request.getParameter("num"));
return "springweb";
}
3.2直接再参数列表中定义形参接收,还可以帮助我们进行数据类型转换
@GetMapping(path = "/test")
public String test(Integer num,@RequestParam("user-name") String userName,@RequestHeader("User-Agent") String userAgent){
System.out.println(num);
System.out.println(userName);
System.out.println(userAgent);
return "springweb";
}
请求中的键名称与形参名一致,直接接收;
不一致需要通过注解标签进行绑定
3.3直接使用对象接收
400:请求数据类型转换有问题
lombock自动在类中生成get set方法
@GetMapping(path = "/login")
public String login(Admin admin){
System.out.println(admin);
return "springweb";
}
4.post请求方式 中文乱码问题
Springu框架中提供了一个编码过滤器
我们发现在提交请求的时候,如果输入的是中文,处理器方法获取到之后是乱码。解决的方法就是添加一个过滤器,为 request 对象设置编码集。SpringMVC 中已经为我们提供了这个过滤器,只需要在 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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Ajax返回JSON:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
5.控制器中返回结果
由于使用@RestController ,里面包含@ResponseBody的注解标签,所以方法的返回结果默认是json格式,并将json字符串写入到响应体中;
返回一个对象时,必须加入一个转json的第三方组件;
6.跨域配置
添加依赖
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.5</version>
</dependency>
添加跨域过滤器,在web.xm中配置
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
7.拦截器
拦截器-->过滤器 功能类似但有区别
过滤器时java Servlet规范中定义的,是当请求进入到servlet之前,可以对请求进行拦截,可以加入一些逻辑处理;
拦截器与过滤器是有区别的,拦截是spring框架中自己定义的功能,和过滤器的位置不同;
拦截器之拦截进入到自己控制器中的请求,其余的不拦截。
搭建拦截器:
1.创建一个类,实现HandlerInterceptor接口
public class TokenInterceptor implements HandlerInterceptor {
/*
预处理:当请求经过映射处理器对应的控制器是存在的
判断该请求可以进入该拦截器,执行调用
返回true 请求继续向下执行
返回false 请求不再向下执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
}
2.重写接口中的preHandle()
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
3.配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!--配置哪些请求进拦截器-->
<mvc:exclude-mapping path="/loginCtl/login"/> <!--配置哪些请求不进拦截器-->
<bean class="com.ffyc.ssm.Common.TokenInterceptor"></bean> <!--配置拦截器实现类-->
</mvc:interceptor>
</mvc:interceptors>