web开发 servlet(一)
Servlet:
javax.servlet.Servlet接口
servlet 是运行在服务器端的servlet容器中,需要继承javax.servlet.Servlet接口。
可以在这里查看servlet的文档:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/index.html
这个接口有5个方法:
如下:
void |
destroy() |
ServletConfig |
getServletConfig() |
java.lang.String |
getServletInfo() |
void |
init(ServletConfig config) |
void |
service(ServletRequest req,ServletResponse res) |
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的信息,比如作者,版权等。
ServletRequest
ServletRequest 包含了所有传递给 servlet的参数,
可以在这里查看其文档:
http://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/ServletRequest.html
ServletResponse
ServletResponse 包含了所有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
HttpServlet
HttpServlet 顾名思义,就是支持http协议的servlet,它是GenericServlet的子类,如图所示。
protected void |
doDelete(HttpServletRequest req,HttpServletResponse resp) |
protected void |
doGet(HttpServletRequest req,HttpServletResponse resp) |
protected void |
doHead(HttpServletRequest req,HttpServletResponse resp) |
protected void |
doOptions(HttpServletRequest req,HttpServletResponse resp) |
protected void |
doPost(HttpServletRequest req,HttpServletResponse resp) |
protected void |
doPut(HttpServletRequest req,HttpServletResponse resp) |
protected void |
doTrace(HttpServletRequest req,HttpServletResponse resp) |
protected long |
getLastModified(HttpServletRequest req) |
protected void |
service(HttpServletRequest req,HttpServletResponse resp) |
void |
service(ServletRequest req,ServletResponse res) |
Http方法加了
doGet doPost doPut dohead等几个方法,这几个方法都接受ServletRequest req,ServletResponse res这两个参数。并且重载了两个service方法,
其中doGet doPost等方法的参数第二个service方法的参数是一样的。而且抛出的异常都是ServletException。
我们一般使用的时候不用去修改service,只需要覆盖doXXX方法即可。因为调用过程是这样的:
当一个请求进入servlet 首先调用:
void |
service(ServletRequest req,ServletResponse res) |
方法,然后从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
HttpServletResponse
http://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 { @Override protected 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>"); } // 获取客户端ip p.println("<tr><td>"+"remove ip"+"</td><td>"+request.getRemoteAddr()+"</td></tr>"); // 获取客户端端口 p.println("<tr><td>"+"remote port"+"</td><td>"+request.getRemotePort()+"</td></tr>"); // 获取服务器ip p.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(); } }
Servlet 登陆
注意redirect的使用
public class LoginServlet extends HttpServlet { @Override protected 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 { @Override protected 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); } }