一 Servlet
1.1什么是servlet
Servlet是web程序中的小应用程序,servlet通过http接收和相应来自客户端的请求。
1.2创建一个Servlet
步骤 1创建servlet
public class MyServlet implements Servlet { private static final long serialVersionUID = 1L; public MyServlet() { super(); } public void destroy() { System.out.println("输出 输出....destroy "); } public ServletConfig getServletConfig() { return null; } public String getServletInfo() { return null; } public void init(ServletConfig servletConfig) throws ServletException { System.out.println("输出 输出....init "); } public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { System.out.println("输出 输出.... service"); } }
步骤 2 web.xml中配置servlet
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>LServlets</display-name> <servlet> <servlet-name>myServlet</servlet-name> <servlet-class>xiao.it.java.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>myServlet</servlet-name> <url-pattern>/ser</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
1.3 servlet执行过程
如上图所示,浏览器请求服务,服务找到对应的servlet应用,通过地址栏里面的url与web.xml
中配置的url-mapping映射找到对应的servlet类,并实例化,tomcat会依次调用servlet的init与service方法,完成后servlet会把请求数据返回给客户端,tomcat再执行servlet的销毁工作。
1.4 servlet生命周期
实例化-->初始化-->服务-->销毁
出生:(实例化-->初始化)第一次访问Servlet就出生
活着:(服务)应用活着,servlet就活着,应用没有卸载的时候
死亡:(销毁)应用卸载了servlet就销毁.
//servlet是单实例的 public class MyServlet implements Servlet { //第一次被访问的时候调用 public MyServlet(){ super(); } //第一次被访问的时候调用 public void init(ServletConfig servletConfig) throws ServletException { System.out.println("******** init ********"); } //每一次访问的时候都调用 //这里是个多线程的 public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { System.out.println("******** service ********"); } //被销毁的时候调用 public void destroy() { System.out.println("******** destroy ********"); } public ServletConfig getServletConfig() { return null; } public String getServletInfo() { return null; } }
如上面的代码所示,servlet是单例的,而service方法确实多线程的,当servlet第一次被访问的时候依次是构造函数,init()方法,然后接下来才是service的调用,从第一次以后访问servlet构造方法跟init()方法不再被调用,但是service()方法确实访问一次调用一次,最后卸载应用的时候servlet才会被销毁。
<servlet> <servlet-name>myServlet</servlet-name> <servlet-class>xiao.it.java.MyServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
如上所示增加了load-on-startup可以在服务器启动的时候对servlet进行实例化与初始化。
二 Servlet的三种创建方式
4.1、实现javax.servlet.Servlet接口(参见:编写一个servlet程序:)
4.2、继承javax.servet.GenericServlet类(适配器模式)
4.3、继承javax.servlet.http.HttpServlet类(模板方法设计模式)
如上图所示
Servlet接口
public abstract interface Servlet { public abstract void init(ServletConfig paramServletConfig) throws ServletException; public abstract ServletConfig getServletConfig(); public abstract void service(ServletRequest paramServletRequest, ServletResponse paramServletResponse) throws ServletException, IOException; public abstract String getServletInfo(); public abstract void destroy(); }
servletConfig接口
public abstract interface ServletConfig { public abstract String getServletName(); public abstract ServletContext getServletContext(); public abstract String getInitParameter(String paramString); public abstract Enumeration<String> getInitParameterNames(); }
GenericConfig 类
public abstract class GenericServlet /* */ implements Servlet, ServletConfig, Serializable /* */ { /* */ private static final long serialVersionUID = 1L; /* */ private transient ServletConfig config; /* */ public GenericServlet() {} /* */ public void destroy() {} /* */ public String getInitParameter(String name) /* */ { /* 80 */ return getServletConfig().getInitParameter(name); /* */ }
HttpServlet类
1主要service方法 public void service(ServletRequest req, ServletResponse res) /* */ throws ServletException, IOException /* */ { /* */ HttpServletRequest request; /* */ HttpServletResponse response; /* */ try /* */ { /* 726 */ request = (HttpServletRequest)req; /* 727 */ response = (HttpServletResponse)res; /* */ } catch (ClassCastException e) { /* 729 */ throw new ServletException("non-HTTP request or response"); /* */ } /* 731 */ service(request, response); /* */ } /* */ } 2 自己实现的service方法 / protected void service(HttpServletRequest req, HttpServletResponse resp) /* */ throws ServletException, IOException /* */ { /* 617 */ String method = req.getMethod(); /* */ /* 619 */ if (method.equals("GET")) { /* 620 */ long lastModified = getLastModified(req); /* 621 */ if (lastModified == -1L) /* */ { /* */ /* 624 */ doGet(req, resp); /* */ } else { /* */ long ifModifiedSince; /* */ try { /* 628 */ ifModifiedSince = req.getDateHeader("If-Modified-Since"); /* */ } /* */ catch (IllegalArgumentException iae) { /* 631 */ ifModifiedSince = -1L; /* */ } /* 633 */ if (ifModifiedSince < lastModified / 1000L * 1000L) /* */ { /* */ /* */ /* 637 */ maybeSetLastModified(resp, lastModified); /* 638 */ doGet(req, resp); /* */ } else { /* 640 */ resp.setStatus(304); /* */ } /* */ } /* */ } /* 644 */ else if (method.equals("HEAD")) { /* 645 */ long lastModified = getLastModified(req); /* 646 */ maybeSetLastModified(resp, lastModified); /* 647 */ doHead(req, resp); /* */ } /* 649 */ else if (method.equals("POST")) { /* 650 */ doPost(req, resp); /* */ } /* 652 */ else if (method.equals("PUT")) { /* 653 */ doPut(req, resp); /* */ } /* 655 */ else if (method.equals("DELETE")) { /* 656 */ doDelete(req, resp); /* */ } /* 658 */ else if (method.equals("OPTIONS")) { /* 659 */ doOptions(req, resp); /* */ } /* 661 */ else if (method.equals("TRACE")) { /* 662 */ doTrace(req, resp); /* */ /* */ /* */ } /* */ else /* */ { /* */ /* */ /* 670 */ String errMsg = lStrings.getString("http.method_not_implemented"); /* 671 */ Object[] errArgs = new Object[1]; /* 672 */ errArgs[0] = method; /* 673 */ errMsg = MessageFormat.format(errMsg, errArgs); /* */ /* 675 */ resp.sendError(501, errMsg); /* */ } /* */ }
如上图所示 我们配置多个路径,可以映射到同一个servlet上,也就是一个servlet可以映射多个路径。
servet映射细节2: 通配符* 代表任意字符串
url-pattern: *.do 以*.字符串的请求都可以访问 注:不要加/
url-pattern: /* 任意字符串都可以访问
url-pattern: /action/* 以/action开头的请求都可以访问
匹配规则:
优先级:从高到低
绝对匹配--> /开头匹配 --> 扩展名方式匹配
如果url-pattern的值是/,表示执行默认映射。所有资源都是servlet
实际开发的时候servlet的创建方式,就用最后一种方式。
三 servlet线程安全
解决servlet线程安全问题,尽量不要使用全局变量,因为servlet是单实例,多服务的所以,尽量使用局部变量,来解决并发资源共享的问题。
四 servlet配置与资源
4.1 ServletConfig
4.1.1获取配置信息
servlet配置
<servlet> <servlet-name>myServlet</servlet-name> <servlet-class>xiao.it.java.MyServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>myServlet</servlet-name> <url-pattern>/ser</url-pattern> </servlet-mapping>
获取servlet配置
public class Hser extends HttpServlet{ private ServletConfig servconfig; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //方式一 获取配置信息 String encoding = servconfig.getInitParameter("encoding"); System.out.println(encoding); //方式二 获取配置信息 String encoding1 = this.getServletConfig().getInitParameter("encoding"); System.out.println(encoding1); //方式三 获取配置信息 String encoding2 = super.getInitParameter("encoding"); System.out.println(encoding2); } @Override public void init(ServletConfig config) throws ServletException { super.init(config); this.servconfig=config; } }
4.1.2获取servletContext
ServletContext servletContext = servconfig.getServletContext();
4.2 servletContext
创建方式
ServletContext servletContext = servconfig.getServletContext();
ServletContext servletContext2 = this.getServletContext();
ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。单实例。
4.2.1 共享数据
常用方法:
void setAttribute(String name,object value);//向ServletContext对象的map中添加数据
Object getAttribute(String name);//从ServletContext对象的map中取数据
void rmoveAttribute(String name);//根据name去移除数据
4.2.2 获取全局配置
Web.xml中配置全局参数
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>LServlets</display-name> <context-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </context-param> <servlet> <servlet-name>myServlet</servlet-name> <servlet-class>xiao.it.java.MyServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>myServlet</servlet-name> <url-pattern>/ser</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
代码中获取全局参数
public class ServletContext extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub super.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String utf = this.getServletContext().getInitParameter("encoding"); System.out.println(utf); } }
4.2.3 获取资源路径
public void test1() throws FileNotFoundException, IOException{ String realPath = this.getServletContext(). getRealPath("/WEB-INF/a.properties"); Properties properties=new Properties(); properties.load(new FileInputStream(realPath)); } public void test2() throws FileNotFoundException, IOException{ String realPath = this.getServletContext(). getRealPath("/WEB-INF/classes/b.properties"); Properties properties=new Properties(); properties.load(new FileInputStream(realPath)); } public void test3() throws FileNotFoundException, IOException{ String realPath = this.getServletContext(). getRealPath("/WEB-INF/classes/xiao/it/java/c.properties"); Properties properties=new Properties(); properties.load(new FileInputStream(realPath)); }
4.2.4 请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.getServletContext().getRequestDispatcher("/servlet2").forward(req, resp); }