多个请求访问同一个servlet

本文介绍如何通过一个Servlet处理JSP页面的多种请求,包括增删改查等操作,利用反射机制实现请求与方法的映射,简化代码管理和提高开发效率。

在我们刚开始编写java web程序时,可能会一个jsp页面功能对应一个服务器的servlet。例如对我们的客户表(Customer)实行增删改查时,每个操作对一个servlet。这样的话,不仅使得代码量很大,而且会使得代码不好管理。那我们想到的是,怎么实现JSP页面的多个请求对应一个servlet呢?通过一个servlet完成增删改查等多个功能呢?

例如我的jsp页面中查询数据库中的表customer时,展现的如下图所示



我们需要实现的是在输入框中输入要查找的名字或者地址或者电话时,可以实现模糊查询,点击submit时,可以在当前页面下面显示查询的数据结果,例如输入数据库中有的用户名rose



再点击submit,页面呈现



当点击upadate和Delete,可是实现对用户的信息修改和删除功能。在我们刚开始的学习中,会将这些功能都分别对应一个servlet,现在实现的就是这些功能都对应一个servlet。

第一:我们可以在jsp页面中对from中的action统一格式为<form action="query.do" method="post"><td><a href="addCustomer.jsp">Add a new customer</a></td><td><a href="edit.do?id=<%=customer.getId() %>">Update</a></td>
    <td><a href="delete.do?id=<%=customer.getId() %>">Delete</a></td>。都以.do结尾。

那么在我们的一个名为CustomerServlet的web.xml配置文件中可以改写为


那么只要页面中以.do结尾的action在提交后,都会去寻找CustomerServlet。那么我们在CustomerServlet中怎么辨别每一个不同的action呢?我们的做法如下:我们在CustomerServlet中的doGet方法中实现

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取servletpath
    String servletPath = request.getServletPath();
    //去除路径后缀名中的.do
         String methodName = servletPath.substring(1);
         methodName = methodName.substring(0, methodName.length()-3);
         
         try {
        //利用反射获取methodName 对应的方法 
Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
HttpServletResponse.class);
//利用反射调用相应的方法
            method.invoke(this, request, response);
} catch (Exception e) {

response.sendRedirect("error.jsp");
}
    }

这样实现可以根据页面的不同请求,截掉.do,得到不同请求名。但注意的是必须页面中的请求名和seevlet中各实现功能的方法名相同。如页面中是delete.do,那么我们的servlet中的方法名就应该写成delete,这样才能该请求获取相应的功能。

### 多个用户请求同一个 Servlet 时 Session 方法的行为及线程安全性 当多个用户同时请求同一个 Servlet 时,`HttpSession` 的行为和线程安全性是一个重要的考虑因素。以下是详细分析: #### 1. `HttpSession` 的作用域 `HttpSession` 是与特定用户的会话绑定的,每个用户在访问应用时都会有一个独立的会话对象[^2]。这意味着即使多个用户同时请求同一个 Servlet,每个用户的操作只会影响其自己的会话对象,而不会影响其他用户的会话。 #### 2. 线程安全性问题 尽管每个用户有自己的 `HttpSession` 对象,但当同一用户打开多个浏览器窗口或标签页时,可能会导致多个线程同时访问同一个 `HttpSession` 对象。这种情况下,`HttpSession` 并不是线程安全的[^2]。例如,如果一个线程正在读取某个会话属性,而另一个线程正在修改该属性,可能会导致数据不一致。 #### 3. 如何解决线程安全问题 为了确保 `HttpSession` 的线程安全性,可以采取以下措施: - **同步代码块**:使用 `synchronized` 关键字对会话属性的读写操作进行同步处理。例如: ```java HttpSession session = request.getSession(); synchronized (session) { String username = (String) session.getAttribute("username"); session.setAttribute("username", "NewValue"); } ``` - **避免共享可变状态**:尽量减少在会话中存储可变对象。如果必须存储可变对象,则应确保这些对象本身是线程安全的[^3]。 - **深度克隆**:对于复杂的对象,可以在读取时对其进行深度克隆,以避免直接修改会话中的对象实例[^2]。 #### 4. 示例代码 以下是一个简单的示例,展示如何在多线程环境下安全地使用 `HttpSession`: ```java import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; @WebServlet("/example") public class ExampleServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); // 使用同步块确保线程安全 synchronized (session) { Integer count = (Integer) session.getAttribute("count"); if (count == null) { count = 0; } count++; session.setAttribute("count", count); } response.getWriter().println("Count: " + session.getAttribute("count")); } } ``` #### 5. 其他注意事项 - **会话超时**:可以通过 `setMaxInactiveInterval(int interval)` 设置会话的超时时间,以避免长时间占用服务器资源[^1]。 - **会话失效**:调用 `invalidate()` 方法可以使会话无效,解除绑定所有会话数据[^1]。 ### 结论 `HttpSession` 在多用户环境中是线程安全的,因为每个用户的会话是独立的。然而,在同一用户的多线程请求下,`HttpSession` 并不是线程安全的,需要通过同步或其他机制来确保数据一致性[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值