Servlet概述

Servlet

什么是Servlet?

Servlet是由SUN公司提供的一门动态Web资源开发技术

Servlet本质上是一段Java程序,和之前的Java程序不同的是,Servlet程序无法独立运行,需要将Servlet程序放在服务器中(比如tomcat服务器),由服务器调用才可以执行。

Servlet: 服务器端的Java程序.

Servlet是运行在服务器端的Java程序,其作用是什么?

其作用是对服务器接收过来的请求进行处理(作用为处理请求)

相关的接口与类

  • Servlet接口

    初始化
    init(ServletConfig config);
    调用
    service(ServletRequest Request, ServletResponse Response);
    销毁
    destroy();

  • GenericServlet抽象类

    实现了Servlet接口中的部分方法(init,destroy)

  • HttpServlet抽象类

继承了GenericServlet,实现了service方法.

Servlet常用方法

返回值 方法 说明
void doGet(略) 处理get请求的方法
void doPost(略) 处理post请求的方法
void init(略) 初始化servlet方法
void destroy() 销毁servlet方法
void service(略) servlet的核心方法, 能同时处理get和post请求

一个简单的servlet代码

servlet class, 需要继承HttpServlet

public class Test extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        // 响应格式
		response.setContentType("text/html;charset=utf-8");
        // post提交使用utf-8, 否则会乱码(默认为iso8859-1)
        request.setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter(); // 获取输出流
		// 获取提交参数
		// request.getParameter("参数名"); // 返回String类型
        // 如果一个参数名有多个参数值(多选框等), 则使用以下方法
        // request.getParameterValues("参数名"); // 返回String[]
		
		out.write("测试成功!"); // 以响应格式返回到浏览器
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

web.xml

<servlet>
    <servlet-name>Test</servlet-name><!--servlet名字(可以随意命名)-->
    <servlet-class>com.test.Test</servlet-class><!--servlet包名+类名, 不写.java后缀-->
  </servlet>
  <servlet-mapping>
    <servlet-name>Test</servlet-name><!--servlet名字(和上面对应)-->
    <url-pattern>/Test</url-pattern><!--访问的url-->
  </servlet-mapping>

url-pattern有三种写法:

  1. 精确匹配:

    即请求资源路径除掉应用名之后的值必须等于url-pattern的值。(比如这儿,请求资源路径除掉应用名之后是"/abc.html",url-pattern的值正好也是"/abc.html",这样就匹配了)

  2. 通配符匹配:

    使用*匹配任意的零个或者多个字符。

    比如:

    <url-pattern>/*</url-pattern>
    <url-pattern>/demo/*</url-pattern>
    
  3. 后缀匹配:

    使用*.开头,然后接一个后缀(后缀就是一个字符串)。

    比如:

    <url-pattern>*.do</url-pattern>
    以上配置,会匹配所有以.do结尾的请求。
    <url-pattern>*.action</url-pattern>
    

    如果没有找到匹配的Servlet,则会找对应位置的文件.

@WebServlet注解

tomcaat7(servlet3.0)以及之后的版本, 有了一个注解, 可以省去web.xml的编写

@WebServlet 注解属性:

属性名 类型 描述
name String 指定Servlet 的 name 属性,等价于 。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。
value String[] 该属性等价于 urlPatterns 属性。两个属性不能同时使用。
urlPatterns String[] 指定一组 Servlet 的 URL 匹配模式。等价于标签。
loadOnStartup int 指定 Servlet 的加载顺序,等价于 标签。
initParams WebInitParam[] 指定一组 Servlet 初始化参数,等价于标签
asyncSupported boolean 声明 Servlet 是否支持异步操作模式,等价于 标签。
description String 该 Servlet 的描述信息,等价于 标签。
displayName String 该 Servlet 的显示名,通常配合工具使用,等价于 标签。

request和response介绍

request是代表HTTP请求信息的对象,response是代表HTTP响应信息的对象。

当浏览器发请求访问服务器中的某一个Servlet时,服务器将会调用Servlet中的service方法来处理请求。在调用service方法之前会创建出request和response对象。

其中request对象中封装了浏览器发送给服务器的请求信息(请求行、请求头、请求实体等),response对象中将会封装服务器要发送给浏览器的响应信息(状态行、响应头、响应实体),在service方法执行完后,服务器再将response中的数据取出,按照HTTP协议的格式发送给浏览器。

每次浏览器访问服务器,服务器在调用service方法处理请求之前都会创建request和response对象。(即,服务器每次处理请求都会创建request和response对象)

在请求处理完,响应结束时,服务器会销毁request和response对象。

Servlet的生命周期

什么是Servlet的声明周期?

容器如何创建Servlet实例,如何对其进行初始化处理,如何对其方法来处理请求,以及如何销毁其实例的整个过程.

生命周期分为那几个阶段

GenericServlet是HttpServlet的实现接口

  1. 实例化

    什么是实例化?

    容器调用Servlet的构造器,创建Servlet对象.

    什么时候实例化?

    • 默认情况下,容器收到请求之后,才会创建Servlet实例(容器只会创建一个实例!)
    • 容器启动之后,立即创建Servlet实例(需要配置load-on-startup参数)
  2. 初始化

    什么是初始化?

    容器在实例化之后,会调用Servlet实例的init方法.(该方法只会执行一次!)

    GenericServlet已经提供了init方法的一个简单实现

    所以,我们不写这个方法,也可以.

    如果要实现自己的初始化处理逻辑,只需要override GenericSerlvet的init()方法.

  3. 调用(就绪)

    什么是就绪?

    容器收到请求之后,会调用Servlet实例的service方法来处理请求.

    HttpServlet的service方法是这样实现的:

    依据请求类型调用对应的doXXX方法.

    比如 get 请求会调用doGet方法, post请求会调用doPost方法.

    这些doXXX方法只是抛出来的异常.

  4. 销毁

    什么是销毁?

    容器在删除Servlet实例之前,会调用该实例的destroy方法.该方法只会调用一次.

    GenericServlet已经实现了destroy方法.

Servlet的线程安全问题

为什么说Servlet会有线程安全问题?

容器只会创建一个Servlet实例

容器收到请求之后,会启动一个线程,由该线程来调用Servlet来处理请求. 这样一来,就有可能有多个线程同时去调用某个Servlet实例,就有可能发生线程安全问题. 比如,这些线程同时去修改Servlet实例的某个属性.

如何解决?

使用synchronized对有可能产生线程安全问题的代码加锁.

注意,加锁会影响性能.

posted @ 2020-06-12 15:35  zpk-aaron  阅读(172)  评论(0编辑  收藏  举报