# servlet
Serviet:server applet,称为小型的服务程序或者服务连接器,用于开发动态web资源的技术,可以运行在web服务器中的小型java程序,servelet主要的功能在于交互式的浏览和生成数据,生成动态web内容
如上图所示,服务器端程序其实就是实现了servlet接口的程序
# 一个简单的servlet程序
// 创建一个servlet的过程 1:右键->新建->web Project 2:新建包 3:新建Class文件,点击下方的add,在搜索框中搜索Servlet,将javax.servlet包添加进项目中(实现Servlet接口) 4:此时生成的 FirstServlet.java文件 package com.doaoao.servlet; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FirstServlet implements Servlet { public void destroy() { // TODO Auto-generated method stub } public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } public String getServletInfo() { // TODO Auto-generated method stub return null; } public void init(ServletConfig arg0) throws ServletException { // TODO Auto-generated method stub } public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { // 在该方法中写入测试代码,因为在服务器执行时,会先执行该类中的该方法 System.out.println("first servlet"); } } 5:修改 web.xml 文件 <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 创建一个servlt示例 --> <servlet> <!-- 给servlet命名,改名字与servlet-mapping中的servlet-name一样 --> <servlet-name>firstServlet</servlet-name> <!-- servlet的包名+类名 --> <servlet-class>com.doaoao.servlet.FirstServlet</servlet-class> </servlet> <servlet-mapping> <!-- servlet名字,与servlet中的 servlet-name一致--> <servlet-name>firstServlet</servlet-name> <!-- 要访问的url地址 --> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app> 6:在浏览器中访问 http://127.0.0.1:8080/01-servlet/hello# Servlet的生命周期
实例化 --> 初始化 --> 服务 --> 销毁
上方的四个时间点都是由tomcat执行的,我们可以获取到各个时间点,并可以让每个时间点完成指定功能
package com.doaoao.servlet; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FirstServlet implements Servlet { public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } public String getServletInfo() { // TODO Auto-generated method stub return null; } // 初始化 public void init(ServletConfig arg0) throws ServletException { System.out.println("调用init方法"); } // 服务 public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { System.out.println("调用service方法"); } // 销毁 public void destroy() { System.out.println("调用destory方法"); } // 自定义无参构造方法(实例化) public FirstServlet(){ System.out.println("调用无参构造方法"); } }// 输出
// 第一次访问url
调用无参构造方法
调用init方法
调用service方法
//第二次访问url
调用service方法
// 当右击Tomcat --> stop server 会执行destory方法# Swevlet的特征
1:Servlet是单例多线程的,只创建一个servlet对象,但是每次请求都会起一个线程并在自己线程栈内存中执行service方法。
(每个用户访问的是同一个serclet)(每个用户会拥有自己的线程)如果创建多个对象的话,就会创建多个对象,会导致内存不够用)2:一个 Servlet 实例只会执行一次无参构造器与 init()方法,并且是在第一次访问时执行。
3:用户每提交一次对当前 Servlet 的请求,就会执行一次 service()方法。 4:一个 Servlet 实例只会执行一次 destroy()方法,在应用停止时执行。 5;由于 Servlet 是单例多线程的,所以为了保证其线程安全性,一般情况下是不建议在 Servlet类中定义可修改的成员变量,因为每个线程均可修改这个成员变量,会出现线程安全问题。 5:默认情况下,Servlet 在 Web 容器启动时是不会被实例化的。(再tomcat启动时不会创建实例,只有在用户进行访问时才能创建实例)# 在tomcat启动时默认不会创servlert实例,如果想要让tomcat启动时创建servlet实例,在web,xml中添加<load-on-startup>
下面<load-on-startup>1</load-on-startup>中添加的数值越小(有多个serclet时),数值越小会越优先创建
<servlet> <!-- 给servlet命名,改名字与servlet-mapping中的servlet-name一样 --> <servlet-name>firstServlet</servlet-name> <!-- servlet的包名+类名 --> <servlet-class>com.doaoao.servlet.FirstServlet</servlet-class> <load-on-startup>1</load-on-startup> <------------------------ 中间加入非零的值--> </servlet># 注意:不要定义可修改的成员变量,会有线程安全问题
// 当在servlet中定义可修改的成员变量时 private int count = 1; // 每次有新的线程执行(都会对变量的值修改,这样会导致第一个用户所用的值发生变化) 2 调用service方法 3 调用service方法 4 调用service方法
# ServletConfig接口
在servlet接口的init方法中有一个参数ServletConfig,该接口可以获取web,xnl中对当前servlet类的配置信息,
ServletConcig中的方法
getInitParameter(); // 获取指定名称的初始化参数值。例如从下面的servlet中调用 getInitParameter("username"); // 方法会返回字符串"doaoao"。 getInitParameterNames(); // 获取当前 Servlet 所有的初始化参数名称。其返回值为枚举类型 getServletName(); // 获取当前 Servlet 的中指定的 Servlet名称。如下面中的 ServletName 为"configServlet"。 getServletContext(); // 获取到当前 Servlet 的上下文对象 ServletContext,这是个非常重要的对象,将在下一节中详细介绍。ServletConfig的简单使用
public class ConfigTest01 implements Servlet { private ServletConfig config; @Override public void init(ServletConfig config) throws ServletException { this.config = config; } @Override public ServletConfig getServletConfig() { // TODO Auto-generated method stub return null; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { //获取web.xml中配置的初始化参数 String userName = config.getInitParameter("userName"); System.out.println(userName); //获取当前servlet全部的初始化参数的name(返回一个枚举类型) Enumeration<String> params = config.getInitParameterNames(); while(params.hasMoreElements()){ String name = params.nextElement(); String value = config.getInitParameter(name); System.out.println(name + "=" + value); } //获取servlet的名称 config System.out.println("servletName=" + config.getServletName()); } @Override public String getServletInfo() { // TODO Auto-generated method stub return null; } @Override public void destroy() { // TODO Auto-generated method stub } } // web.xml中的内容 <servlet> <servlet-name>config</servlet-name> <servlet-class>com.doaoao.servlet.ConfigTest01</servlet-class> <init-param> <param-name>userName</param-name> <param-value>doaoao</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>123456</param-value> </init-param> </servlet># 欢迎页面设置
// 当有页面index.jsp时就不会往下再继续查找,如果没有符合的欢迎页面,就会报错 // 当没有设置欢迎界面,系统会默认去访问index.jsp/index.html欢迎页面 <welcome-file-list> <welcome-file>index.jsp</welcome-file> <welcome-file>hello.jsp</welcome-file> </welcome-file-list># url-patten设置
url-patten用于对请求进行筛选匹配
<!-- 精确匹配:请求路径必须和url-patten完全匹配次啊能被Servlet处理 --> <servlet-mapping> <servlet-name>ServletTest</servlet-name> <url-pattern>/test/servlettest</url-pattern> </servlet-mapping> <!-- 通配符路径模式 --> <servlet-mapping> <servlet-name>ServletTest</servlet-name> <url-pattern>/test/*</url-pattern> </servlet-mapping> <!-- 全路径模式 --> <servlet-mapping> <servlet-name>ServletTest</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletTest</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 后缀请求路径 --> <servlet-mapping> <servlet-name>ServletTest</servlet-name> <url-pattern>*.test</url-pattern> </servlet-mapping># GenriServlet
通过实现Servlet接口来实现一个Servlet类时,比较不方便,因为有好几个不需要实现的方法我们必须要实现,javax.servet.GenericServlet可以解决该问题,定义一个servlet类时,继承GenericServlet类即可
package my; import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class SimpleServlet extends GenericServlet { @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { // TODO Auto-generated method stub } }# 继承HttpServle类
package com.doaoao.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HttpServlet_test extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Get请求"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post请求"); } }待补充...