Servlet以及单例设计模式

1.Servlet概述

a)Servlet,全城是Servlet Applet,服务器端小程序,是一个接口,定义了若干方法,要求所有的Servlet必须实现。

b)Servlet用于接收客户端的请求,并对请求做出相应的相应。

c)Servlet中的方法:

>init:用于初始化Servlet;

>service:用于(执行)服务;

>destroy:在Servlet被销毁前调用;

d)Servlet是一个接口,为了方便使用,官方提供了对应的实现类,关系如下:

Servlet:   -- GenericServlet(c):通用协议的Servlet;

                --HttpServlet(c):专门用于HTTP的Servlet;

2.定义Servlet并配置

2.1定义Servlet

测试时继承了GenericServlet,实际使用时建议使用HttpServlet.

package com.bjsxt.servlet;

 

import java.io.IOException;

import javax.servlet.GenericServlet;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

public class FirstServlet extends GenericServlet{

       public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException{

                System.out.println("FirstServlet.service()");

                //响应信息

                res.getWriter().print("<h1>Hello Servlet!</h1>");

    }

}

2.2配置Servlet

在web.xml中配置Servlet,告诉Tomcat在客户端访问哪个路径时,应该执行哪个Servlet.

<!-- 配置Servlet -->

<servlet>

               <servlet-name>FirstServlet</servlet-name>

               <servlet-class>com.bjsxt.servlet.FirstServlet</servlet-class>

               </servlet>

               <!-- 配置Servlet映射 -->

<servlet-mapping>

               <servlet-name>FirstServlet</servlet-name>

               <url-pattern>/abc</url-pattern>

               <!-- http://localhost:8080/0529_servlet_hello/abc -->

</servlet-mapping>

3.Servlet的执行过程(图略)

a)客户端通过浏览器输入URL地址访问Tomcat

b)Tomcat解析URL路径

c)到当前项目的web.xml中匹配Servlet的映射路径;

       ---如果匹配成功,则调用对应的Servlet的service方法;

       ---如果没有匹配成功,则继续到Tomcat的web.xml中匹配。

d)在Tomcat的web.xml中,提供了两个Servlet,分别为DefaultServlet和JspServlet.

       ---JspServlet用于处理jsp

       ---DefaultServlet处理没有匹配到其他Servlet的所有请求,用于加载静态资源或404异常。

 4.Servlet配置详解

a)web.xml的名称不能改变,位置不能改变;

b)<servlet-name><servlet-class>要写正确,必须要匹配;

c)关于<url-pattern>的几种配置方式:

 

<servlet-mapping>

<servlet-name>FirstServlet</servlet-name>

<!-- 固定路径, 必须以/开头 -->

<url-pattern>/abc</url-pattern>

<!-- xxx结尾的路径 -->

<url-pattern>*.sxt</url-pattern>

<!-- 访问xxx下的路径 -->

<url-pattern>/sxt/*</url-pattern>

<!-- 不可以使用如下的方式 -->

<!-- <url-pattern>/sxt/*.aaa</url-pattern> -->

<!-- 匹配所有的路径包括jsp -->

<url-pattern>/*</url-pattern>

<!-- 匹配所有除了jsp之外的路径 -->

<url-pattern>/</url-pattern>

</servlet-mapping>

 5.解决405异常

a)在HttpServlet中,service方法用于分发请求,例如:如果是get方式,就调用doGet方法;如果是post方式,就调用doPost方法。

b)而HttpServlet中的doPost方法和doGet方法没有做什么事,就发送了一个405异常,因此,一旦执行到这两个方法就会报405异常。

c)解决405异常的两种方式

 ---子类重写service方法:

public class DemoServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

System.out.println("DemoServlet.service()");

}

}

 ---子类重写doGet和doPost方法:

 

public class DemoServlet extends HttpServlet {

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

System.out.println("DemoServlet.doGet()");

doPost(req, resp);

}

 

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

System.out.println("DemoServlet.doPost()");

}

}

 6.单例设计模式

a)设计模式是解决特定问题的最佳方案。

b)单例,单个对象,在对象的使用过程中,永远都只创建一个对象;

c)饿汉式单例,类加载时就创建对象,由于静态成员变量只被加载一次,所以保证了对象之创建一次;

 

package com.bjsxt.singleton;

 

/**

 * 饿汉式单例

 * 不管这个对象是否被使用, 先被创建

 * @author Administrator

 *

 */

public class HungrySingleton {

 

private static HungrySingleton instance = new HungrySingleton();

 

private HungrySingleton() {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("创建对象[饿汉式]");

}

 

/**

 * 静态方法, 用于给其他类提供对象

 *

 * @return

 */

public static HungrySingleton getInstance() {

return instance;

}

}

 d)懒汉式单例,在需要的时候才创建对象,多线程时不安全,需要使用双重检查机制保证线程安全;

package com.bjsxt.singleton;

 

/**

 * 懒汉式单例

 *

 * @author Administrator

 *

 */

public class LazySingleton {

 

private static LazySingleton instance;

 

private LazySingleton() {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("创建对象[懒汉式]");

}

 

public static LazySingleton getInstance() {

if (instance == null) {

synchronized (LazySingleton.class) {

// Double Check, 双重检查

if (instance == null) {

instance = new LazySingleton();

}

}

}

return instance;

}

}

7.饿汉式单例和懒汉式单例的比较

a)饿汉式:

  >代码非常简单。

 >类加载时及创建对象,该对象可能并不会被使用。

 >多线程下也可以保证单例的实现,没有问题。

 >省去了判断,效率较高;

b)懒汉式:

  >代码较为复杂

  >类加载时不会创建对象,需要时才创建,不会创建多余的对象。

  >多线程时可能会有线程安全问题,需要进行Double Check。

  >需要很多判断,效率较低;

8.Servlet的生命周期

a)Servlet是单实例,多线程的

b)生命周期阶段

   ----创建:构造器只创建一次;

   ----初始化:innit,只初始化一次;

   ---执行:service,累一次请求执行一次;

   ---销毁:destroy,项目卸载或服务关闭时,Servlet被销毁,销毁前会由服务器调用destriy方法;

c)默认情况下,Servlet是懒汉式单例,对象是在第一次请求时被创建的。

d) 如果希望Servlet在服务器启动时就创建, 可以在<servlet>标签下通过<load-on-startup>标签进行指定. 该标签需要配置一个整数:

  • 负整数: 和不配置一样, 表示第一次请求时创建和初始化.
  • 0和正整数: 表示服务器启动时就创建和初始化, 数字越小, 被加载的优先级越高. 如果数字相同加载顺序由服务器决定.

 

posted @ 2018-05-29 20:08  愤怒的码农。  阅读(1317)  评论(0编辑  收藏  举报