1、BaseServet
愿景:在一个Servlet中可以有多个请求处理方法。并完成转发或重定向。
做法:
1)客户端发送请求时,必须多给出一个参数,指明要调用的方法
要求: 1)请求处理方法的签名必须和service相同。
即:参数类型、返回值、声明的异常 必须相同
2)服务器根据参数调用指定方法
具体步骤:
//通过反射调用方法。
查询当前类的方法,则得到当前类的Class
this.getClass();
1)得到客户端传递过来的方法名,通过方法名再得到Method类的对象
2)需要得到Class文件,然后调用方法查询,得到当前Method
查询当前类的方法,则得到当前类的Class
3)反射调用method表示的方法
public abstract class BaseServlet extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String methodName = req.getParameter("method");
if (methodName == null || methodName.trim().isEmpty()) {
throw new RuntimeException("您没有传参,无法指定调用发个方法");
}
Class c = this.getClass();
Method method = null;
try {
method = c.getMethod(methodName,
HttpServletRequest.class,
HttpServletResponse.class);
} catch (Exception e) {
throw new RuntimeException("您要调用的方法:"+methodName +"不存在");
}
try {
method.invoke(this,req,resp);
if(result == null || result.trim().isEmpty()) {
return;
}
if(result.contains(":")) {
int index = result.indexOf(":");
String s = result.substring(0, index);
String path = result.substring(index+1);
if(s.equalsIgnoreCase("r")) {
resp.sendRedirect(req.getContextPath() + path);
} else if(s.equalsIgnoreCase("f")) {
req.getRequestDispatcher(path).forward(req, resp);
} else {
throw new RuntimeException("你指定的操作:" + s + ",当前版本还不支持!");
}
} else {
req.getRequestDispatcher(result).forward(req, resp);
}
} catch (Exception e) {
System.out.println("您调用的方法:" + methodName + ", 它内部抛出了异常!");
throw new RuntimeException(e);
}
}
}
}
2、Service事务
Service中的方法对应一个业务逻辑。
我们需要在Service中的一方法中调用DAO的多个方法,而这些方法应该在一起事务中
将一个完整的servic设置为事务。
关键点:使DAO的多个方法使用相同的Connection
核心原理:在Service中使用ThreadLocal来完成事务。
public class JdbcUtils {
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
/**
* 使用连接池返回一个连接对象
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
Connection con = tl.get();
if(con != null) return con;
return dataSource.getConnection();
}
/**
* 返回连接池对象!
* @return
*/
public static DataSource getDataSource() {
return dataSource;
}
/**
* 开启事务
* 1. 获取一个Connection,设置它的setAutoComnmit(false)
* 2. 还要保证dao中使用的连接是我们刚刚创建的!
* --------------
* 1. 创建一个Connection,设置为手动提交
* 2. 把这个Connection给dao用!
* 3. 还要让commitTransaction或rollbackTransaction可以获取到!
* @throws SQLException
*/
public static void beginTransaction() throws SQLException {
Connection con = tl.get();
if(con != null) throw new SQLException("已经开启了事务,就不要重复开启了!");
con = getConnection();
con.setAutoCommit(false);
tl.set(con);
}
/**
* 提交事务
* 1. 获取beginTransaction提供的Connection,然后调用commit方法
* @throws SQLException
*/
public static void commitTransaction() throws SQLException {
Connection con = tl.get();
if(con == null) throw new SQLException("还没有开启事务,不能提交!");
con.commit();
con.close();
tl.remove();
}
/**
* 提交事务
* 1. 获取beginTransaction提供的Connection,然后调用rollback方法
* @throws SQLException
*/
public static void rollbackTransaction() throws SQLException {
Connection con = tl.get();
if(con == null) throw new SQLException("还没有开启事务,不能回滚!");
con.rollback();
con.close();
tl.remove();
}
/**
* 释放连接
* @param connection
* @throws SQLException
*/
public static void releaseConnection(Connection connection) throws SQLException {
Connection con = tl.get();
if(con == null) connection.close();
if(con != connection) connection.close();
}
}