web开发 servlet(1)
Servlet:javax.servlet.Servlet接口
servlet 是运行在服务器端的servlet容器中,需要继承javax.servlet.Servlet接口。
可以在这里查看servlet的文档:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/index.html
这个接口有5个方法:如下:
void
destroy()
Called by the servlet container to indicate to a servlet that the servlet is being taken out of service.
ServletConfig
getServletConfig()
Returns a ServletConfig object, which contains initialization and startup parameters for this servlet.
java.lang.String
getServletInfo()
Returns information about the servlet, such as author, version, and copyright.
void
init(ServletConfig config)
Called by the servlet container to indicate to a servlet that the servlet is being placed into service.
void
service(ServletRequest req,ServletResponse res)
Called by the servlet container to allow the servlet to respond to a request.
init 方法:
Servlet 实例化后会调用init方法,可以向其传递一个servletConfig对象,这个对象包括了servlet的配置信息。还可以通过ServletConfig对象获取ServletContext对象,来与servlet进行通信。
service方法:
service 方法处理客户的请求,在调用service之前,必须生成 ServletRequest和ServletResponse对象,前者包含了请求信息,后者包括了响应信息。
destroy方法:
当检测到一个servlet 应该从容器中移除的时候,容器就会调用该servlet的destroy方法。在destroy一般做资源清理工作,比如释放数据库连接,容器会等待service中的方法执行完或者超时了再执行destroy方法。
getServletConfig方法
返回初始化时候传递给servlet的配置信息ServletConfig对象
getServletInfo 方法
返回该servlet的信息,比如作者,版权等。
ServletRequestServletRequest 包含了所有传递给 servlet的参数,
可以在这里查看其文档:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/ServletRequest.html
ServletResponseServletResponse 包含了所有servlet传递给客户端的信息
可以在这里查看其文档:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/ServletResponse.html
Servlet的实现如果直接使用servlet,是很痛苦的事情,javax包中已经有了对servlet的实现。
他们的关系如下图:
GenericServlet
GenericServlet 提供了一个不依赖于协议的sevlet通用实现,它也实现了ServletConfig
接口和init和destory的简单生命周期,另外它实现了log功能。
文档在:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/GenericServlet.html
HttpServletHttpServlet 顾名思义,就是支持http协议的servlet,它是GenericServlet的子类,如图所示。
protected void
doDelete(HttpServletRequest req,HttpServletResponse resp)
Called by the server (via the service method) to allow a servlet to handle a DELETE request.
protected void
doGet(HttpServletRequest req,HttpServletResponse resp)
Called by the server (via the service method) to allow a servlet to handle a GET request.
protected void
doHead(HttpServletRequest req,HttpServletResponse resp)
Receives an HTTP HEAD request from the protected service method and handles the request.
protected void
doOptions(HttpServletRequest req,HttpServletResponse resp)
Called by the server (via the service method) to allow a servlet to handle a OPTIONS request.
protected void
doPost(HttpServletRequest req,HttpServletResponse resp)
Called by the server (via the service method) to allow a servlet to handle a POST request.
protected void
doPut(HttpServletRequest req,HttpServletResponse resp)
Called by the server (via the service method) to allow a servlet to handle a PUT request.
protected void
doTrace(HttpServletRequest req,HttpServletResponse resp)
Called by the server (via the service method) to allow a servlet to handle a TRACE request.
protected long
getLastModified(HttpServletRequest req)
Returns the time the HttpServletRequest object was last modified, in milliseconds since midnight January 1, 1970 GMT.
protected void
service(HttpServletRequest req,HttpServletResponse resp)
Receives standard HTTP requests from the public service method and dispatches them to the doMethod methods defined in this class.
void
service(ServletRequest req,ServletResponse res)
Dispatches client requests to the protected service method.
Http方法加了
doGet doPost doPut dohead等几个方法,这几个方法都接受ServletRequest req,ServletResponse res这两个参数。并且重载了两个service方法,
其中doGet doPost等方法的参数第二个service方法的参数是一样的。而且抛出的异常都是ServletException。
我们一般使用的时候不用去修改service,只需要覆盖doXXX方法即可。因为调用过程是这样的:
当一个请求进入servlet 首先调用:
void
service(ServletRequest req,ServletResponse res)
Dispatches client requests to the protected service method.
方法,然后从req中使用getMethod
()
方法
取得请求的类型XXX,再根据XXX调用doXXX方法。所以覆盖doXXX方法即可。
文档在:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/HttpServlet.html
HttpServletRequest
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/HttpServletRequest.html
HttpServletResponsehttp://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/http/HttpServletResponse.html
实例hello world在eclipse javaEE下面建立一个dynamic web project。取名servletJspLearn
在 WEB-INFO
下面建立clases 和 lib 文件夹,建立 web.xml文件。
classes 放编译好的.class文件。
lib放需要的库文件
welcome.jsp是jsp文件。
新建helloworld.java servlet
package junjun.chapter6; import java.io.IOException;import java.io.PrintWriter; import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse; public class helloworld extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(request.getServletContext().getContextPath()); PrintWriter p = response.getWriter(); p.println("hello world"); p.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub }}
在web.xml中进行配置 servlet
<?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>helloworld</servlet-name> <servlet-class>junjun.chapter6.helloworld</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloworld</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping></web-app>
其中 <servlet>定义一个servlet :包括名字(servlet-name)和报名.类名(servlet-class)
其中<servlet-mapping>定义了一个路径与一个servlet的映射关系
下面就可以使用
http://localhost:8080/servletJspLearn/hello访问这个servlet了
打印请求信息
/** * 打印 请求信息 * @author andyWebsense * */public class OutputInfo extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{response.setContentType("text/html;charset=gb2312");PrintWriter p = response.getWriter();p.println("<html><head><title> Info table </title></head>");p.println("<body>");p.println("<table border = 1 align = center>");p.println("<caption>headers the server received </caption>");p.println("<tr><th>header name</th><th>header value<th></th></tr>");// 打印 请求报头信息 Enumeration<String> headers = request.getHeaderNames();while(headers.hasMoreElements()){String name = headers.nextElement();String value = request.getHeader(name);p.println("<tr><td>"+name+"</td><td>"+value+"</td></tr>");}// 获取客户端ipp.println("<tr><td>"+"remove ip"+"</td><td>"+request.getRemoteAddr()+"</td></tr>");// 获取客户端端口p.println("<tr><td>"+"remote port"+"</td><td>"+request.getRemotePort()+"</td></tr>");// 获取服务器ipp.println("<tr><td>"+"local ip"+"</td><td>"+request.getLocalAddr()+"</td></tr>");// 获取服务器端口p.println("<tr><td>"+"local port"+"</td><td>"+request.getLocalPort()+"</td></tr>");p.println("</table></body></html>");p.close();}}
注意redirect的使用
public class LoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{resp.setContentType("text/html;charset=gb2312");String name = req.getParameter("user");String password = req.getParameter("password");if (name!=null && password!=null && name.equalsIgnoreCase("zhangsan") && password.equals("1234")){//sendRedirect 将用户的请求重定向到 success.jsp中//该方法通过修改HTTP协议的HEADER部分(设置状态代码302,命令浏览器发重新发送请求),对浏览器下达重定向指令的,//让浏览器对在location中指定的URL提出请求,使浏览器显示重定向网页的内容resp.sendRedirect("success.jsp"); }else{resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "服务器忙,请稍后登陆");}resp.flushBuffer();}}
success.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><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>login success</title></head><body><f:view>welcome here</f:view></body></html>
servlet的生命周期
servlet的生命周期是由servlet容器来管理的。
1、加载与实例化当容器启动时候或者检测到需要实例化Servlet来相应 request请求的时候,由容器创建一servlet,容器是使用反射来创建servlet的,所以不要提供带参数的servlet。
2、初始化
调用servlet的init方法进行初始化,servlet可以使用容器提供的ServletConfig从web应用程序的配置信息(web.xml)中获取初始化信息。如果发生异常,使用ServletException或者UnavailableException通知容器。
3、服务
调用service方法进行请求处理。从ServletRequest获取请求信息,通过ServletResponse设置返回信息,如果发生错误,抛出ServletException或者UnavailableException,如果UnavailableException只是该servlet永久不可用,调用destroy方法,注销这个servlet,如果有请求返回404,资源不可用。如果UnavailableException只是该servlet暂时不可用,返回503服务器忙。
4、服务终止
当容器检测到一个servlet需要从时候,调用destroy方法。
下面是这个过程的时序图
servlet上下文ServletContext
ServletContext表示一个servlet的上下文,servlet在初始化期间(调用init方法时候),向其传递ServletConfig,通过ServletConfig获取servletContext。servletContext代表web服务器中一个已知的应用的根目录,例如: http://localhost:8080/servletJspLearn/login 的上下文被定定位于http://localhost:8080/servletJspLearn所有与/servletJspLearn为路径的请求都是与这个servlet关联的应用程序。
使用ServletContext实现页面访问统计
/** * 页面访问量统计 使用 ServletContext来保持访问次数 * @author buptjunjun * */public class CountServlet extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{ServletContext context = this.getServletConfig().getServletContext();// 从servletContext中取出访问次数Integer count = (Integer) context.getAttribute("count");if(count == null)count = 1;else count++;String user = request.getParameter("user");response.setContentType("text/html");PrintWriter p = response.getWriter();p.println("<html><head><title> "+"page visit statistics"+" </title></head>");p.println("<body> this page have been visited"+ count +"times </body></html>");p.close();// 将访问次数放入servletContext中context.setAttribute("count", count);}}