栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaWeb书城项目(四)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaWeb书城项目(四)

JavaWeb书城项目(四)
  • 9、使用 Filter 过滤器
    • 9.1、使用 Filter 过滤器拦截/pages/manager/所有内容,实现权限检查
    • 9.2、使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完成
    • 9.3、使用 Filter 过滤器对上面进行优化
    • 9.4、将所有异常都统一交给 Tomcat,让 Tomcat 展示友好的错误信息页面

9、使用 Filter 过滤器 9.1、使用 Filter 过滤器拦截/pages/manager/所有内容,实现权限检查 9.2、使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完成

以下仅对 生成订单 的部分进行演示

原理分析图:

在 orderServiceImpl.createOrder() 方法里面,调用到了 orderDAOImpl.saveOrder()、orderItemDAOImpl.saveOrderItem()、bookServiceImpl.updateBook() 三个方法

如果在生成订单之后,生成订单详情和销量库存变更的 for 循环之前出现了异常,就会导致数据库里面只有订单,但是没有订单商品内容
【如图】

数据库里面有订单

但是没有订单商品内容

所以要保证 createOrder() 方法在一个事务中,要么都执行,要么都不执行

回忆 JDBC 里的事务部分,代码如下:
【代码如下】

建立连接——开启事务——一系列操作——如没有异常就提交事务——如有异常就回滚事务——最后关闭连接

那么在 OrderServlet.createOrder() 方法里面,首先要保证该方法里面所有调用到的操作都是一个连接里面,就使用 ThreadLocal 来存放连接,那么对 JdbcUtils 工具类进行修改,代码如下:
【代码如下】

存放连接的同时可以开启事务,这样非首次获取连接的时候,就已经开启了事务

最后关闭连接之后还需要释放连接,因为 Tomcat 底层也是使用数据库连接池,如果不及时释放,那么到一定数量时,就再也拿不到连接了

public class JdbcUtils {
	private static ThreadLocal conns = new ThreadLocal();
	
	public static Connection getConnection(){
		Connection conn = conns.get();
		if (conn == null) {
			try {
				conn = dataSource.getConnection();//从数据库连接池中获取连接
				conns.set(conn); // 保存到 ThreadLocal 对象中,供后面的 jdbc 操作使用
				conn.setAutoCommit(false); // 设置为手动管理事务
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return conn;
	}
	
	public static void commitAndClose(){
		Connection connection = conns.get();
		if (connection != null) { // 如果不等于 null,说明 之前使用过连接,操作过数据库
			try {
				connection.commit(); // 提交 事务
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				try {
					connection.close(); // 关闭连接,资源资源
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		// 一定要执行 remove 操作,否则就会出错。(因为 Tomcat 服务器底层使用了线程池技术)
		conns.remove();
	}
	
	public static void rollbackAndClose(){
		Connection connection = conns.get();
		if (connection != null) { // 如果不等于 null,说明 之前使用过连接,操作过数据库
			try {
				connection.rollback();//回滚事务
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				try {
					connection.close(); // 关闭连接,资源资源
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		// 一定要执行 remove 操作,否则就会出错。(因为 Tomcat 服务器底层使用了线程池技术)
		conns.remove();
	}
}

在 orderServiceImpl.createOrder() 方法里面,调用到了 orderDAOImpl.saveOrder()、orderItemDAOImpl.saveOrderItem()、bookServiceImpl.updateBook() 三个方法

那么这些方法传入的连接就都使用 ThreadLocal 里面存放的那个连接,并且不可以有关闭操作,也不可以捕获异常,必须抛出异常,否则回滚事务的地方就无法捕获异常,代码如下:
【代码如下】

修改 baseDao
编写代码的时候都对异常进行捕获了,这里就需要抛出异常,可以将 try-catch 改为 throws ,这里为了方便,直接加一句 throw new RuntimeException(e);

因为抛出了异常,最下面的 return -1; 就没作用了

修改 baseServlet
不可以捕获异常

修改 OrderItemDAOImpl
不可以有关闭操作

修改 OrderDAOImpl
不可以有关闭操作

修改 OrderServiceImpl

修改 OrderServlet

如此在 Servlet 程序里面,对业务语句进行 try-catch 操作,即可实现生成订单、生产订单详情位于同一个事务中

做到发生异常的时候实现回滚

9.3、使用 Filter 过滤器对上面进行优化

其实就是使用 Filter 过滤器统一给所有的 Service 方法都加上 try-catch,来进行实现的管理

原理分析图:

上面说到要对业务 Servlet 程序进行 try-catch 操作,由于业务较多,会比较麻烦

不妨将所有 Servlet 程序放入 Filter 过滤器中

因为在 Filter 过滤器中,执行到 filterChain.doFilter()的时候才会执行所有 Servlet 程序

所以对 filterChain.doFilter()方法进行 try-catch 操作,就相当于对所有 Servlet 程序进行 try-catch 操作

Filter 类代码:

在 web.xml 中的配置:


	TransactionFilter
	com.atguigu.filter.TransactionFilter


	TransactionFilter
	
	/*

一定要记得把 把 baseServlet 中的异常往外抛给 Filter 过滤器

public abstract class baseServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
		doPost(req, resp);
	}
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
		// 解决 post 请求中文乱码问题
		// 一定要在获取请求参数之前调用才有效
		req.setCharacterEncoding("UTF-8");
		String action = req.getParameter("action");
		try {
			// 获取 action 业务鉴别字符串,获取相应的业务 方法反射对象
			Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class,HttpServletResponse.class);
			// System.out.println(method);
			// 调用目标业务 方法
			method.invoke(this, req, resp);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);// 把异常抛给 Filter 过滤器
		}
	}
}
9.4、将所有异常都统一交给 Tomcat,让 Tomcat 展示友好的错误信息页面

因为对于用户的角度,只知道点击后显示空白页面,不知道出了什么问题

在 web.xml 中我们可以通过错误页面配置来进行管理

将要显示的页面信息地址放在里面


	
	500
	
	/pages/error/error500.jsp




	
	404
	
	/pages/error/error404.jsp

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/694655.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号