spring中的事务管理分为:
编程式事务
需要在业务代码中,显示的提交事务 ,使用TransactionTemplate transactionTemplate;
transactionTemplate.execute() 在此方法中执行业务代码
声明式事务(注解)(主要)
就是使用注解标签对需要添加事务的方法进行声明即可,这样次方法就会在事务管理中执行
声明式事务不生效的场景
1.调用同一个类中被 @Transactional修饰的方法
2.注解@Transactional 所在类非 Spring 容器管理的bean 自己new的,没有添加注解表@Service
3.异常被 catch 捕获导致@Transactional 失效
4.数据库引擎不支持事务 mysql有好几种存储引擎,但只有InnoDB支持事务,其他均不支持事务
5.@Transactional 注解属性 propagation 设置错误(事务传播行为错误)
可能存在的面试问题
1.spring中是如何事务管理的?
声明式事务
编程式事务
2.事务管理实现原理是什么?
aop面向切面,不用在业务代码中显示的提交,就可以实现事务增强
3.aop实现原理什么?
动态代理
4.动态代理有哪几种?
jdk
cglib等(以后会讲)
Spring 事务传播行为
什么叫事务传播行为?
即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事
务方法调用时,这个事务方法应该如何进行。
就是A方法 调用B方法 那么B方法应该如何执行(看例如)
事务传播行为是 Spring 框架独有 的事务增强特性,他不属于的事务实际提供方数据库行为.
例如:methodA 事务方法调用 methodB 事务方法时,methodB 是继续在调 用者 methodA 的事务中运行呢
还是为自己开启一个新事务运行,这就是由 methodB 的事务传播行为决定的。
Spring 定义了七种传播行为:
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事 务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NE W | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事 务,则执行与 PROPAGATION_REQUIRED 类似的操作。 |
springMVC
SpringMVC 概述
springMVC 是 spring 框架的一个模块,springMVC 和 spring 无需通过中间整合层进行整合。
springmvc 是一个基于 mvc 的 web 框架,方便前后端数据的传输.
Spring MVC 拥有控制器,接收外部请求,解析参数传给服务层.
springmvc是spring框架中的一个模块,是一个web层模块,在servlet的基础上进行封装,功能更加强大,
作用接收请求数据
调用业务逻辑层
向前端响应数据
SpringMVC 运行流程
1.用 户 向 服 务 器 发 送 请 求 , 请 求 被 Spring 前 端 控 制 Servelt DispatcherServlet 捕获;
2.前端控制器DispatcherServlet接收请求后,调用处理器映射 HandlerMapping。
处理器映射器 HandlerMapping 根据请求的 url 找到处理该请求的处理器
Handler ( 即 Controller ) , 将 处 理 器 Handler 返 回 给 前 端 控 制 器DispatcherServlet。
3.DispatcherServlet 根 据 获 得 的 Handler , 选 择 一 个 合 适 的 HandlerAdapter。 在填充 Handler 的入参过程中,根据你的配置,Spring 将 帮你做一些额外的工作: HttpMessageConveter: 将请求消息(如 Json、xml 等数据)转换成一 个对象,将对象转换为指定的响应信息数据转换:对请求消息进行数据转换。如 String 转换成 Integer、Double 等
数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字 或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult 或 Error 中
4.Handler(自己的控制器)执行完成后,向 DispatcherServlet 返回一个ModelAndView 对象;
5.根据返回的 ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到 Spring 容器中的 ViewResolver)返回给 DispatcherServlet ;
6.ViewResolver 结合 Model 和 View,来渲染视图
7.将渲染结果返回给客户端。
接收请求 @RequestMapping
它的作用就是与请求相匹配,如果匹配上了,所修饰的方法才会被执行。这里我们只需要关注两个属性:
value :请求的路径,这个路径相对于应用的上下文,它是 path 的别名。类型是一个 String[] ,也就是说它可以匹配多个请求路径
method: 请求的方法。我们知道 HTTP 协议的请求方式有 GET 和 POST.
或者使用@GetMapping, @PostMapping
当前的请求只有与@RequestMapping 上指定的属性都匹配的时候,才会执行
它 标 注 的 方 法 。 下 面 分 析 几 个 例 子 , 假 设 应 用 的 上 下 文 路 径 为
“http://localhost:9090/”@RequestMapping(“/users”)请求的路径为 “http://localhost:9090/users” ,
请求方式没有限制,即可以是 GET 也可以是 POST,还能是其它的几个
@RequestMapping(value=“/users”, method= RequestMethod.GET) 请求
路径为"http://localhost:9090/users", 请求方式只能是 GET。
@RequestMapping(value=“/users”, method={ RequestMethod.GET ,
RequestMethod.POST}) 请求路径为“http://localhost:9090/users”, 请求
方式只能是 GET 或者 POST。
方法映射地址配置
为方法配置映射地址,此时get/post请求均可访问此方法
@RequestMapping(value = "/login")
表示此方法能是post方式提交
@RequestMapping(value = "/login",method = RequestMethod.POST)
@PostMapping(value = "/login")
表示此方法能是get方式提交
@RequestMapping(value = "/login",method = RequestMethod.GET)
@GetMapping(value = "/login")
获取请求数据
我们编写处理器方法的目的,就是为了处理客户端提交的数据,而客户端的提交
是按照 HTTP 协议报文格式来提交的,下面我们分析一段常见的 HTTP POST 提
交的报文来理解报文的各个部分与处理器方法参数的对应关系:
请求方法:对应到@RequestMapping 中的 method
请求 URI:中的"/students/create" 对应到@RequestMapping 中的 value 或者 path
请求头:比如获取 User-Agent 中的值则使用@RequestHeader(“User-Agent”) 来获取
请求参数:比如获取 name 参数的值,则使用@RequestParam(“name”)来获取。
@Controller
@RequestMapping("/students")
publicclassStudentController{
@RequestMapping(value="/create",method=RequestMethod.POST)
public String create(
@RequestParam("name") String name,
@RequestParam("age") Integer age,
@RequestHeader("User-Agent") String userAgent){
return null;
}
}
如 果 请 求 参 数 的 名 称 与 处 理 器 方 法 中 的 参 数 名 称 相 同 , 那 么 在 使 用
@RequestParam 绑定的时候,可以省略参数,甚至连@RequestParam 都可以省略。对于上面的例子,可以写成:
@Controller
@RequestMapping("/students")
public class StudentController{
@RequestMapping(value="/create",method=RequestMethod.POST)
public String create(String name, Integer age){
return null;
}
}
参数列表中还可以直接内置
HttpServletRequest,HttpSession,HttpServletResponse 等对象.
使用 request 对象也可以接收
接收请求中的数据@RequestParam("account")
将请求中的参数数据,绑定到参数列表中@RequestHeader("User-Agent")
用来绑定获得请求头中的数据
@PostMapping(value = "/login")
public void login(@RequestParam("account") String acc,
@RequestParam("password") String pass,
@RequestHeader("User-Agent") String useragent){
System.out.println("login"+":"+acc+":"+pass+":"+useragent);
}
中文乱码处理
我们发现在提交请求的时候,如果输入的是中文,处理器方法获取到之后是
乱码。乱码产生的原因在 Java Web 课程中已经讲解过了,解决的方法就是添加
一个过滤器,为 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
@responseBody 注解的作用是将 controller 的方法返回的对象通过适当的转
换器转换为指定的格式之后,写入到 response 对象的 body 区,通常用来向异
步请求返回 JSON 数据。
注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,
他的效果等同于通过 response 对象输出指定格式的数据。
添加 gson jar 包
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
拦截器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yID5CAwe-1649761647341)(H:\非凡英才\日常上课\封校\3.11\2022-3-11\课件\过滤器_拦截器.png)]
SpringMVC 定义了拦截器接口 HandlerInterceptor
该接口中定义了三个方法,这三个方法的调用时在 SpringMVC 框架内部完成的,
调用这个三个方法的时候,其参数的值也是从框架内部传递进来的。
boolean preHandle 预处理方法
实现处理器方法的预处理,就是在处理器方法执行之前这个方法会
被执行,相当于拦截了处理器方法,框架会传递请求和响应对象给该方法,
第三个参数为被拦截的处理器方法。如果 preHandle 方法返回 true 表示继续流程(如
调用下一个拦截器或处理器方法),返回 false 表示流程中断,不会继续调用其他的拦截器或处理器方法,此时我们需要通过 response 来产生响应;
void postHandle 后处理方法
实现处理器方法的后处理,就是在处理器方法调用完成,但在渲染
视图之前,该方法被调用,此时我们可以通过 modelAndView(模型和视图对
象)对模型数据进行处理或对视图进行处理。
afterCompletion 整个请求处理完毕
即在视图渲染完毕时该方法被执行。
配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/><!--表示所有的请求,都会进入到拦截器-->
<mvc:exclude-mapping path="/loginCtl/login"/><!--配置哪些请求不进入到拦截器--> <bean id="islogin" class="com.ffyc.ssm.filter.IsLoginInterceptor"></bean> </mvc:interceptor><!--多个拦截器-->
</mvc:interceptors>