21.Servlet 技术

JavaWeb应用的概念

在Sun的Java Servlet规范中,对Java Web应用作了这样定义:"Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。"

Java Web应用中可以包含如下内容:

• Servlet

• JSP

• 实用类

• 静态文档如HTML、图片等

• 描述Web应用的信息(web.xml)

Servelt 与 Servlet 容器

Servlet容器的概念

Servlet容器为JavaWeb应用提供运行时环境,它负责管理Servlet和JSP的生命周期,以及管理它们的共享数据。Servlet容器也称为JavaWeb应用容器,或者Servlet/JSP容器。

目前最流行的Servlet容器软件括:

• Tomcat

• Resin

• J2EE服务器(如Weblogic)中也提供了内置的Servlet容器

Servlet 简介

Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用"请求/响应"的模式。

Servlet可完成如下功能:

• 处理请求;

• 发出响应

Servlet容器响应客户请求的过程

ServletAPI

Servlet 创建的三种方式

实现 Servlet 接口

继承 HttpServlet 类

继承 GenericServlet 类(几乎不用)

Servlet的注册与运行

• Servlet程序必须通过Servlet容器来启动运行,并且储存目录有特殊要求,通需要存储在<WEB应用程序目录>\WEB-INF\classes\目录中。

• Servlet程序必须在WEB应用程序的web.xml文件中进行注册和映射其访问路径,才可以被Servlet引擎加载和被外界访问。

• 一个元素用于注册一个Servlet,它包含有两个主要的子元素:和,分别用于设置Servlet的注册名称和Servlet的完整类名。

• 一个元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:和,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

Servlet映射的细节

• 同一个Servlet可以被映射到多个URL上,即多个元素的子元素的设置值可以是同一个Servlet的注册名。

• 在Servlet映射到的URL中也可以使用通配符,但是只能有两种固定的格式:一种格式是".扩展名",另一种格式是以正斜杠(/)开头并以"/*"结尾。

Servlet容器响应客户请求的过程

• ①Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。

• ②装载并创建该Servlet的一个实例对象:调用该 Servlet 的构造器

• ③调用Servlet实例对象的init()方法。

• ④创建一个用于封装请求的ServletRequest对象和一个代表响应消息的ServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。

• ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

Servlet对象生命周期

Servlet对象什么时候生,什么时候死.

生命周期相关的三个方法, init,service,destroy

• init(ServletConfig config)Servlet对象的初始化方法,对象被创建的时候调用

• service(request,response)客户端访问一次,执行一次

• destory()Servlet对象销毁之前调用

• Servlet对象什么时候被创建

  • Servlet默认第一次访问的时候,对象被创建
  • Tomcat服务器启动的时候创建对象,需要修改web.xml (一般不配置)(5)

• Servlet对象什么时候被销毁

  • 停止Tomcat服务器
  • WEB项目从服务器移除

ServletConfig 接口

• Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以,Serlvet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称和初始化参数等信息也需要传递给该Servlet

• Servlet引擎将代表Servlet容器的对象(ServletContext)和Servlet的配置参数信息一并封装到一个称为ServletConfig的对象中,并在初始化Servlet实例对象时传递给该Servlet。ServletConfig接口则用于定义ServletConfig对象需要对外提供的方法,以便在Servlet程序中可以调用这些方法来获取有关信息。

• Servlet引擎调用Servlet的实例对象的init(ServletConfig config)方法将ServletConfig对象传递给Servlet。Servlet.getServletConfig()方法必须返回init(ServletConfig config)方法传递进来的这个ServletConfig对象的引用。

配置 Serlvet 的初始化参数
复制代码
<servlet>
		<servlet-name>helloServlet</servlet-name>
		<servlet-class>com.javaweb.HelloServlet</servlet-class>
		<!-- 配置 Serlvet 的初始化参数。 且节点必须在 load-on-startup 节点的前面 -->
		<init-param>
			<!-- 参数名 -->
			<param-name>user</param-name>
			<!-- 参数值 -->
			<param-value>root</param-value>
		</init-param>	
		<init-param>
			<param-name>password</param-name>
			<param-value>1230</param-value>
		</init-param>	
		<load-on-startup>-1</load-on-startup>	
	</servlet>

ServletConfig接口的方法

• getInitParameterNames() 获取某servlet中所有参数名字,返回值为Enumeration 对象

• getInitParameter(String name) 根据某参数名字获取对应的值

• getServletName(): 获取servlet名字

• getServletContext: 获取ServletContext对象

获取初始化参数
复制代码
	String user = servletConfig.getInitParameter("user");
	System.out.println("user: " + user);
	
	Enumeration<String> names = servletConfig.getInitParameterNames();
	while(names.hasMoreElements()){
		String name = names.nextElement();
		String value = servletConfig.getInitParameter(name);
		System.out.println(name + ": " + value);
	}

ServletContext接口

• Servlet引擎为每个WEB应用程序都创建一个对应的ServletContext对象,ServletContext对象被包含在ServletConfig对象中,调用ServletConfig.getServletContext方法可以返回ServletContext对象的引用。

• 由于一个WEB应用程序中的所有Servlet都共享同一个ServletContext对象,所以,ServletContext对象被称之为 application 对象(Web应用程序对象)。

• 可以认为 SerlvetContext 是当前 WEB 应用的一个大管家. 可以从中获取到当前 WEB 应用的各个方面的信息.

• 功能:

  • 获取WEB应用程序的初始化参数
  • 记录日志
  • application域范围的属性
  • 访问资源文件
  • 获取虚拟路径所映射的本地路径
  • WEB应用程序之间的访问
  • ServletContext的其他方法
配置WEB应用程序的初始化参数

在web.xml文件的根元素中增加子元素,如下所示:

复制代码
<context-param>
	<param-name>driver</param-name>
	<param-value>com.mysql.jdbc.Driver</param-value>
</context-param>
获取WEB应用程序的初始化参数
复制代码
	//getInitParameter
	//getInitParameterNames
ServletContext servletContext = servletConfig.getServletContext();
		
String driver = servletContext.getInitParameter("driver");
System.out.println("driver:" + driver);

Enumeration<String> names2 = servletContext.getInitParameterNames();
while(names2.hasMoreElements()){
	String name = names2.nextElement();
	System.out.println("-->" + name); 
}
ServletContext接口其他方法

获取当前 WEB 应用的某一个文件在服务器上的绝对路径, 而不是部署前的路径:

String realPath = servletContext.getRealPath("/note.txt");

System.out.println(realPath);

获取当前 WEB 应用的名称:

String contextPath = servletContext.getContextPath();

ServletContext对象是一个容器,可以存储数据.

对象有个作用域问题,ServletContext作用域是整个WEB应用程序。

• 向域对象存储数据: setAttribute(String key, Object value)

• 取出域对象数据: Object getAttribute(String key)

• 移除域对象数据: removeAttribute(String key)

ServletContext context =servletConfig.getServletContext();

//域对象存储数据,键值对

context.setAttribute("hello","java");

//取出域对象存储的键值对

Object value = context.getAttribute("hello");

统计访问的次数

• 练习域对象ServletContext的使用

• 第一次访问Servlet的时候,数据1存储到域对象

• 第二次访问,从域中取出数据++,存储回去

复制代码
	public void init() throws ServletException {
    	ServletContext context = getServletContext();
    	context.setAttribute("count",1);
	}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    ServletContext context = getServletContext();
    Integer count = (Integer) context.getAttribute("count");
    response.getWriter().print("welcome "+count);
    count++;
    context.setAttribute("count",count);
}
注解开发取代web.xml

@WebServlet,注解添加到自己定义的Servlet中的类声明上即可

注解的属性 urlPatterns,属性值就是浏览器的访问地址.

@WebServlet(urlPatterns = "/test")

Request对象概述

Request对象获取客户端的请求数据, 接口ServletRequest,子接口HttpServletRequest继承ServletRequest.

HttpServletRequest接口的实现类是Tomcat引擎提供.

servlet请求方式GET/POST
Request对象获取请求行

• String getMethod() 获取提交的方式 (GET,POST)

• String getRequestURI() 获取请求的参数,请求服务器路径

• StringBuffer getRequestURL() 获取请求的参数,请求服务器路径

• String getQueryString()获取请求行 问号后面的参数 (GET)

• String getContextPath() 获取WEB应用名称

复制代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //request对象方法 getMethod()获取客户端的请求方式
    String method = request.getMethod();
    System.out.println(method);
    //方法 String getRequestURI() 获取请求服务器路径
    //方法 StringBuffer getRequestURL() 获取请求服务器路径
    String URI = request.getRequestURI();
    StringBuffer URL = request.getRequestURL();
    System.out.println("URI=="+URI); 
    System.out.println("URL=="+URL);

    //方法 String getQueryString()获取请求行,?后面的所有参数
    String query = request.getQueryString();
    System.out.println(query);

    //获取WEB应用名称  String getContextPath()
    String path = request.getContextPath();
    System.out.println(path);
}
Request对象获取请求头

请求头数据格式键值对, k:v

指导性信息,指导服务器

• String getHeader(String key)返回对应键的值

• Enumeration getHeaderNames()

复制代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     * request获取请求头
     */
     //方法  String getHeader(String key)
    String key = request.getHeader("Referer");
    System.out.println(key);
    /*
     * Enumeration getHeaderNames() 获取所有的请求头的键
     * 返回值Enumeration接口 (向量枚举)
     * 集合:1.0-1.1 Enumeration    集合1.2  迭代器
     * Iterator迭代器接口:  hasNext()   next()
     * Enumeration接口:  hasMoreElement()  nextElement()
     */
    Enumeration<String> enums  = request.getHeaderNames();
    while (enums.hasMoreElements()){
         key = enums.nextElement();
         String value = request.getHeader(key);
        System.out.println(key+"=="+value);
    }
}
Request获取请求参数

• String getParameter("表单中的name值")获取指定的请求参数

• String[] getParameterValues("表单中的name值")获取参数中的一键多值

• Map<String,String[]> getParameterMap()获取提交的所有参数

复制代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     * request 获取客户端提交数据
     */
    //方法getParameter(String key)指定表单中的参数
    String username = request.getParameter("username");
    String password = request.getParameter("pass");
    System.out.println(username+"=="+password);

    //方法getParameterValues()获取一键多值  checkbox  radio
    String[] hobby = request.getParameterValues("hobby");
    System.out.println(Arrays.toString(hobby));
    System.out.println("=============");
    //方法 getParameterMap()获取提交的所有参数
    Map<String,String[]> map = request.getParameterMap();
    for (String key : map.keySet()){
        String[] value = map.get(key);
        System.out.println(key+"="+Arrays.toString(value));
    }
}
Request域对象

作用域: Request域对象的作用域比较小,范围是一次请求有效.

• 域对象存储数据: setArratibute(String key, Object value)

• 取出域对象数据: Object getAttribute(String key)

• 移除域对象数据: removeAttribute(String key)

复制代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //向域对象 ,request 存储数据
    request.setAttribute("hello","java");
    //取出域对象数据
    Object value = request.getAttribute("hello");
    System.out.println("servlet1="+value);
}
Response对象概述

• 负责对浏览器进行响应的对象

• ServletResponse接口,HttpServletResponse接口继承自ServletResponse

• 使用的是子接口HttpServletResponse,此接口对象由Tomcat引擎提供

• 可以实现对客户端的响应, 响应行,响应头,响应体

Response设置响应行

• 设置状态码: setStatus(int 状态码)

response.setStatus(500);

Response设置响应头

HTTP协议的响应头,数据格式键值对 k:v

包含指导性信息,指导客户端

• addHeader(String key,String value)

• addIntHeader(String key,int value)

• addDateHeader(String key,long l)

• setHeader(String key,String value)

• setIntHeader(String key,int value)

• setDateHeader(String key,long l)

复制代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     * response对象设置响应头
     */
    response.addHeader("hello","java");
  /*  response.addIntHeader("good",5);
    response.addDateHeader("date",System.currentTimeMillis());*/
    /*
     * addHeader() 添加,实现一个键对应多个值
     * setHeader() 设置,原来的键覆盖
     */
    response.setHeader("hello","java2222");
}
Response设置响应体

HTTP的响应体,就是页面的正文部分.

• getWriter() 返回值是打印流PrintWrite.

复制代码
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      /*
       * response对象方法getWriter()
       * 打印流的响应体
       * write() 使用字符串数据,没有差别, 输出是整数,查询编码表
       * print() 无论是什么,原样打印
       */
       PrintWriter pw =  response.getWriter();
       pw.write(100);
       pw.print(100);
  }
响应中的中文乱码问题

产生乱码原因: 编码和解码不一致.

response.setContentType("text/html;charset=UTF-8");

相关推荐
wfsm9 小时前
flowable使用01
java·前端·servlet
六件套是我1 天前
redission实现延时队列
android·java·servlet
非典型代码2 天前
Jenkins发不出邮件
运维·servlet·jenkins
佐杰3 天前
Jenkins安装部署
运维·servlet·jenkins
chxii3 天前
Spring Boot 中,内嵌的 Servlet 容器(也称为嵌入式 Web 服务器)
spring boot·servlet
BUG?不,是彩蛋!4 天前
Maven-Java 项目到底解决了什么痛点?
java·servlet·maven
CS Beginner7 天前
【搭建】个人博客网站的搭建
java·前端·学习·servlet·log4j·mybatis
一只小透明啊啊啊啊10 天前
Java Web 开发的核心组件:Servlet, JSP,Filter,Listener
java·前端·servlet
芙蓉王真的好111 天前
优化 Jenkins 构建脚本:避免 pnpm lockfile 相关报错的关键配置
spring·servlet·jenkins
要站在顶端11 天前
Jenkins Pipeline 多job依赖、触发多Job、并行执行及制品下载
运维·servlet·jenkins