家居网购项目实现011
以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git
27.功能25-事务管理
27.1下订单问题思考
在生成订单的功能中,系统会去同时修改数据库中的order,order_item,furn三张表,如果有任意一个表修改失败,就会出现数据不一致问题。因此出现了事务控制问题。
27.2思路分析
之前,我们每次调用底层的dao操作,每次进行的都是独立事务,因此一但在一次业务中调用了多个dao操作,就不能保证多表的事务一致性。
因为JDBC局部事务是控制是由java.sql.Connection来完成的,要保证多个DAO的数据访问处于一个事务中,我们需要保证他们使用的是同一个java.sql.Connection.
要保证数据一致性,就要使用事务。使用事务的前提是保证同一个连接connection。我们的想法是,在进行dao操作的前面就开启事务,然后在进行各种dao操作后,如果没有出现异常,则手动进行事务提交,否则进行回滚。
现在的问题是:
q1. 我们之前使用数据库连接池,无法保证每次进行dao操作都是同一个connection连接对象
q2. 设置开启手动提交事务以及事务回滚的时机
解决方法:
- 使用Filter+ThreadLocal进行事务管理
- 在一次http请求,servlet-service-dao的调用过程,始终是一个线程,这是使用ThreadLocal的前提
- 使用ThreadLocal来确保所有dao操作都在同一个Connection连接对象中完成
- 根据过滤器的机制,在所有代码都走完之后会回来走过滤器的chain.dofilter()的后置代码,这个特性非常适合进行事务管理
27.3代码实现
27.3.1uilts包
重写JDBCUtilsByDruid,修改getConnection方法,同时设置手动提交事务因为现在连接的关闭是在commit或者rollback中发生的,因此BasicDAO中写的关闭连接已经没有意义了,将其删掉即可。
27.3.2filter
配置TransactionFilter- <filter>
- <filter-name>TransactionFilter</filter-name>
- <filter-class>com.li.furns.filter.TransactionFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>TransactionFilter</filter-name>
-
- <url-pattern>/*</url-pattern>
- </filter-mapping>
复制代码 TransactionFilter:- package com.li.furns.filter;
- import com.li.furns.utils.JDBCUtilsByDruid;
- import javax.servlet.*;
- import java.io.IOException;
- /**
- * 管理事务
- *
- * @author 李
- * @version 1.0
- */
- public class TransactionFilter implements Filter {
- public void init(FilterConfig config) throws ServletException {
- }
- public void destroy() {
- }
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
- try {
- //先放行
- chain.doFilter(request, response);
- //统一提交
- JDBCUtilsByDruid.commit();
- } catch (Exception e) {
- //只有在try{}中出现了异常,才会进行catch{}
- //这里想要捕获异常,前提是底层的代码没有将抛出的异常捕获
- JDBCUtilsByDruid.rollback();//回滚
- e.printStackTrace();
- }
- }
- }
复制代码由于之前在BasicServlet中捕获了异常,因此需要修改BasicServlet,将捕获的异常抛出给Filter,否则无法在出现异常时进行回滚。
27.4完成测试
为了测试,在FurnDAOImpl操作中写入错误的sql语句,模拟表操作失败
现在来测试一下,当发生dao操作失败后会产生什么现象。
登录用户,点击添加某个家居,点击购物车生成订单,因为生成订单涉及到furn表的操作,因此可以看到点击后页面没有跳转到正常的显示订单页面
查看后台输出,发现抛出异常
查看数据库:
相关的表没有进行改动,说明事务管理起作用了。
order_item表:
order表:
furn表:(操作前后的sales和stock字段一致)
28.功能26-统一错误提示页面
28.1需求分析/图解
- 如果在访问/操作网站时,出现了内部错误,统一显示 500.jsp
- 如果访问/操作不存在的页面/servlet时,统一显示 404.jsp
28.2思路分析
- 在发生错误/异常时,将错误/异常 抛给tomcat
- 在web.xml配置不同的错误显示不同的页面即可
28.3代码实现
404.jsp用于显示404错误;500.jsp用于显示服务器内部错误。
- 页面代码:略。
- 在web.xml文件中配置错误提示页:
- <error-page>
- <error-code>404</error-code>
- <location>/views/error/404.jsp</location>
- </error-page>
- <error-page>
- <error-code>500</error-code>
- <location>/views/error/500.jsp</location>
- </error-page>
复制代码 如果在代码中捕获了异常,那么将不会起到效果,应该要将异常抛出给tomcat,让tomcat可以根据不同的异常进行页面展示。
TransactionFilter:
28.4完成测试
在浏览器中输入一个项目不存在的资源http://localhost:8080/furniture_mall/abc.jsp,访问结果:
内部发生错误:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |