我正在研究JSP MVC Web应用程序。我对Thread-Safe Servlet概念感到困惑。以下是我的代码,请告诉我线程安全与否。另外,请告诉我它为什么是线程安全的或不是线程安全的原因。
JSP代码;
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Personal Profile</title>
</head>
<body>
<form id="PersonalData" method="post" action="PersonalDataServlet">
First Name:<input type="input" name="FirstNameField"><br>
Last Name:<input type="input" name="LastNameField"><br>
Email:<input type="input" name="EmailField">Without @ part<br>
<input type="Submit" value="Submit Data">
</form>
<br>
<br>
<br>
<%
out.print(request.getAttribute("FullName") + "\n");
out.print(request.getAttribute("EmailAddress"));
%>
</body>
</html>
Servlet代码;
package Servlets;
import java.io.IOException;
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 Model.WelcomeName;
@WebServlet("/PersonalDataServlet")
public class PersonalDataServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String FirstNameServlet;
String LastNameServlet;
String EmailServlet;
FirstNameServlet = request.getParameter("FirstNameField");
LastNameServlet = request.getParameter("LastNameField");
EmailServlet = request.getParameter("EmailField");
System.out.println(FirstNameServlet + "\n" + LastNameServlet + "\n" + EmailServlet);
WelcomeName WelcomeNameObject = new WelcomeName();
WelcomeNameObject.Fullname(FirstNameServlet, LastNameServlet, EmailServlet);
request.setAttribute("FullName", WelcomeNameObject.FullName);
request.setAttribute("EmailAddress", WelcomeNameObject.EmailAddress);
request.getRequestDispatcher("Profile.jsp").forward(request, response);
}
}
其他类用于实际计算或业务逻辑
package Model;
public class WelcomeName {
public String FullName;
public String EmailAddress;
public void Fullname(String FirstName, String LastName, String Email) {
FullName = (FirstName + " " + LastName);
EmailAddress = (Email + "@gmail.com");
}
}
答案 0 :(得分:0)
我看到您提供的代码中没有线程安全问题。线程安全主要取决于代码如何使用共享数据,因此我寻找
servlet类的实例变量,如果servlet容器使用相同的servlet实例为多个线程中的请求提供服务,则在线程之间共享;
通过servlet上下文或会话对象共享的对象;以及
servlet或JSP访问的任何类的静态变量。
这些不是共享数据可以采用的唯一形式,但它们可能适用于您的Web应用程序,就像您提供的那样。您没有通过任何这些机制共享任何数据,因此您提供的servlet和JSP是线程安全的。
如果您 访问共享对象,那么这不会自动使您的代码非线程安全,但您需要通过适当的同步来保护您的访问,以确保其线程安全。作为一个功能问题,您还需要注意同步,以避免在任何相当长的时间内阻塞线程。
答案 1 :(得分:0)
每个方法调用都有自己的堆栈帧,没有其他线程访问它。所有局部变量都在此堆栈帧上分配。对于WelcomeNameObject,它是在堆上创建的,但是对它的唯一引用是在创建它的方法调用的堆栈框架上,以及在请求对象上(即使请求对象在welcomeNameObject上发生了某些变化,那么方法调用就完成了,所以没有冲突)。其他线程没有机会获得对它的引用并进行更改,因此它是线程安全的。
如果移动welcomeName变量的声明,使其成为servlet中的实例变量:
@WebServlet("/PersonalDataServlet")
public class PersonalDataServlet extends HttpServlet {
private WelcomeName WelcomeNameObject;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
然后结果将是不安全的。 servlet容器保留一个线程池来执行请求,它将这些请求发送到servlet的同一个实例,因此并发请求可以修改servlet的实例变量的内容。例如,一个线程可能进入方法,创建对象的新实例并将其分配给实例变量,然后填充它,然后另一个线程可以调用该方法并创建该对象的新实例并指定 < / em>到同一个实例变量,这样第一次调用就会返回一个与刚刚创建的对象完全不同的对象。
答案 2 :(得分:-1)
您可以使用SingleThreadModel。你的servlet类实现了这个接口,之后你的servlet是线程安全的。