javaweb之servlet详解

Servlet

1.1什么是servlet

    Servletweb程序中的小应用程序,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应用,通过地址栏里面的urlweb.xml

中配置的url-mapping映射找到对应的servlet类,并实例化,tomcat会依次调用servletinitservice方法,完成后servlet会把请求数据返回给客户端,tomcat再执行servlet的销毁工作。

1.4 servlet生命周期

实例化-->初始化-->服务-->销毁

出生:(实例化-->初始化)第一次访问Servlet就出生

活着:(服务)应用活着,servlet就活着,应用没有卸载的时候

死亡:(销毁)应用卸载了servlet就销毁.

扫描二维码关注公众号,回复: 1543886 查看本文章

//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);
	
}

servlet相关对象关系










猜你喜欢

转载自blog.csdn.net/worn_xiao/article/details/80385987