1:servlet定义:
Servlet是一个Java应用程序,运行在服务器端,用来处理客户端请求并作出响应的程序。
Servlet多线程体系结构是建立在 Java多线程机制之上的,它的生命周期是由Web容器负责的。 当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类,此时它贮存于内存中。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。 这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构建的Web应用时要注意线程安全的问题。每一个请求都是一个线程,而不是进程,因此,Servlet对请求的处理的性能非常高。对于Servlet,它被设计为 多线程的(如果它是单线程的,你就可以想象,当1000个人同时请求一个网页时,在第一个人获得请求结果之前,其它999个人都在郁闷地等待),如果为每个用户的每一次请求都创建 一个新的线程对象来运行的话,系统就会在创建线程和销毁线程上耗费很大的开销,大大降低系统的效率。
解决servlet线程安全的方案:同步对共享数据的操作 Synchronized (this){...}、避免使用实例变量
public class ServletDemo extends HttpServlet {
int i=1;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 加了synchronized后,并发访问i时就不存在线程安全问题了,
* 为什么加了synchronized后就没有线程安全问题了呢?
* 假如现在有一个线程访问Servlet对象,那么它就先拿到了Servlet对象的那把锁
* 等到它执行完之后才会把锁还给Servlet对象,由于是它先拿到了Servlet对象的那把锁,
* 所以当有别的线程来访问这个Servlet对象时,由于锁已经被之前的线程拿走了,后面的线程只能排队等候了
*
*/
synchronized (this) {//在java中,每一个对象都有一把锁,这里的this指的就是Servlet对象
i++;
try {
Thread.sleep(1000*4);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.getWriter().write(i+"");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2:简单的servlet实例:
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
public class FirstServlet extends HttpServlet {
//处理请求的方法
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException {
//数据发送给客户端—>控制台方式输出
//System.out.println(“Hello Servlet”);
//数据发送给客户端—>HTML页面输出
resp.setContentType(“text/html”);
resp.getWriter().print(“<html>”);
resp.getWriter().print(“<head>”);
resp.getWriter().print(“</head>”);
resp.getWriter().print(“<body>”);
resp.getWriter().print(“Hello World”);
resp.getWriter().print(“</body>”);
resp.getWriter().print(“</html>”);
}
}
servlet配置到tomcat中去:
Tomcat是一个web容器,也叫web服务器。编译好的servlet类只能运行在tomcat容器中,客户端浏览器不可以直接访问Servlet,需要在web.xml中配置一下
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>FirstServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/servlet/FirstServlet</url-pattern>
</servlet-mapping>
Tomcat启动成功后,在浏览器中输入:http://localhost:8080/abingtest/servlet/FirstServlet
3:servlet运行原理
当我们在浏览器中输入http://localhost:8080/abingtest/servlet/FirstServlet的时候,Tomcat是如何找到我们的servlet ,运行,并返回我们想看到的页面的呢?
3.1.:WebApplication的标准目录结构:
WEB-INF/classes
/lib
Web.xml
也就是一个完整的web应用程序目录下,必须包含以上的目录结构。
Classes 文件夹下是项目中用到的类文件,均由JDK编译成了.class文件;Lib文件夹是我们项目中引用的jar包;Web.xml是整个web应用程序的配置文档。
3.2:Tomcat解析URL
a) 首先来看URL中包含的信息:”协议” + “端口号” + “路径(项目名称+文件路径)”
Tomcat启动后,监听我们的8080端口,当有Url请求发过来之后,解析出项目名称 abingtest,然后到webapps目录下搜索到该项目文件夹。
b) 项目文件找到后,开始寻找类文件。
这个时候Tomcat去Web.xml文件中寻找<servlet-mapping> 配置节中包含”servlet/FirstServlet”字符串,进而找到该类文件所在的位置。
3. Servelt中的doGet() 和 doPost() 方法
我们写的FirstServlet 继承了HttpServlet ,重写了HttpServlet中的doGet() 方法,HttpServlet中还有一个doPost()方法。这两个方法都是用来处理Http请求的。Servlet会根据我们提交表单的方法(method=post/get)调用service方法来自动选择。
4. Servlet如何接收数据
public class FirstServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
//获取表单数据
String userName = request.getParameter(“userName”);
}
}
Http协议会将网页中的所有内容包装成为一个request对象传递给servlet ,Servlet通过这个对象拿到表单中的所有数据,处理完成之后,通过Response对象返回给客户端浏览器。
Servlet访问URL使用*通配符映射
<servlet>
<servlet-name>ServletDemo1</servlet-name>
<servlet-class>gacl.servlet.study.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
http://localhost:8080/abingtest/任意字符都可以