web服务器的作用本质是提供内容。一开始只是将静态的内容(文件)传送出去,后来CGI技术允许动态的内容的出现。
web容器是web服务器中管理servlet组件的一部分,是servlet的运行时环境。在Java里web容器就是servlet容器。servlet容器有管理servlet的生存周期,为servlet匹配url等作用。
Servlet
在Java中,开发者使用servlet来生成动态内容。Servlet接口在javax.servlet package
中被定义。有3个重要的生存期方法,分别是init(), service(), and destroy()。这些方法在这些时候被调用:
- 在Servlet生命周期的初始化阶段,web容器通过调用init()方法来初始化Servlet实例,并且可以传递一个实现 javax.servlet.ServletConfig 接口的对象给它。这个方法在Servlet实例的生命周期里只调用一次。
- 初始化后,Servlet实例就可以处理客户端请求了。web容器调用Servlet的service()方法来处理每一个请求。
- 最后,web容器调用destroy()方法来终结Servlet。如果想在Servlet的生命周期内关闭或者销毁一些文件系统或者网络资源,可以调用这个方法来实现。destroy() 方法和init()方法一样,在Servlet的生命周期里只能调用一次。
Servlet类通过懒惰装载和预先装载这两种方式被装载到容器中,一个实例可以为多个线程服务。卸载时由JVM进行垃圾回收。
ServletContext定义了Servlet和容器之间交流的方法,在web应用装载时有Servlet容器创建出来。同时,在web.xml中定义的Servlet, Filter and Listener都会被创建出一个类的实例。
创建一个Servlet需要注意以下几点:
- MyServlet类需要继承了HttpServlet。Servlet类要么是继承了
javax.servlet.GenericServlet
的普通Servlet,要么是继承了javax.servlet.http.HttpServlet
的HTTP Servlet。 - 重载 doGet() 和 doPost() 方法。这两个方法都已在 HttpServlet 类里定义了。当一个GET或POST请求到来时,它就会被映射到相应的方法里。例如,如果你向这个servlet发送一个HTTP GET请求,doGet()方法就会被调用。如:
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//Do some other work
}
- HttpServletRequest 和 HttpServletResponse 是所有doXXX()方法的默认参数。
Servlet容器和web服务器连接在一起,web服务器在特定的端口处(80)监听HTTP请求。当client(浏览器)发送一条HTTP请求时,Servlet容器创建了HttpServletRequest和HttpServletResponse各一个实例,然后匹配事先创建好的filter、servlet实例与请求的url,再把Request、Response传递给匹配实例的方法。requst实例的作用是处理HTTP请求的信息(HTTP头,请求主体);response实例的作用是帮助控制发送HTTP响应。
在web应用中,要获取请求参数,需要调用 HttpServletRequest 对象的 getParameter() 方法,并且传递你要获取的输入参数的id给该方法。
String value1 = req.getParameter("param1");
String value1 = req.getParameter("param2");
使用RequestDispatcher.forward()转发请求到另一个Servlet:有时候,你的应用需要把一个Servlet要处理的请求转让给另外的Servlet来处理并完成任务。而且,转让请求时不能重定向客户端的URL。即浏览器地址栏上的URL不会改变。在 ServletContext 里已经内置了实现上面需求的方法。当你获取了 ServletContext 的引用,你就可以简单地调用getRequestDispatcher()
方法去获取用来转发请求的 RequestDispatcher 对象。当调用getRequestDispatcher()
方法时,需要传递包含servlet名的字符串,这个Servlet就是你用来处理转让请求的Servlet。获取 RequestDispatcher 对象后,通过传递 HttpServletRequest 和HttpServletResponse 对象给它来调用转发方法。转发方法负责对请求进行转发。如下:
RequestDispatcher rd = servletContext.getRequestDispatcher("/NextServlet");
rd.forward(request, response);
使用HttpServletResponse.sendRedirect()重定向请求到另一个Servlet:
当应用内的特定URL被访问时,你想把浏览器的URL重定向到另外一个。要实现这种功能,你需要调用 HttpServletResponse 对象的sendRedirect()方法。
httpServletResponse.sendRedirect("/anotherURL");
ps:请求转发和重定向区别
Session和Cookie
client第一次访问web应用时,或HttpSession通过request.getSession()获得时,servlet会生成一个长而独特的ID( session.getId()),然后存在内存里,再在response中设置一个Cookie,JSESSIONID作为Cookie名,ID值作为Cookie的值。在Http Cookie验证阶段,client回送有效的Cookie,servlet容器会使用Cookie的值来从内存中获取HttpSession。 HttpSession默认存活30分钟,client30分钟内没有访问web应用就会被销毁。client用新的browser实例去访问会创建一个新的HttpSession。
线程安全
public class MyServlet extends HttpServlet
{
private Object thisIsNOTThreadSafe; //Don't to this
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
这段代码很好的解释了如何规避线程不安全的行为。一个Servlet实例能为多个请求服务,如果多个请求共用一个变量就会造成线程不安全。
参考
ps:JSP技术参考:javaweb入门笔记(6)-JSP技术