Servlet(未完结~)

文章目录

  • 前言
  • [1 Servlet简介](#1 Servlet简介)
  • [2 Servlet初识](#2 Servlet初识)
    • [2.1 Servlet开发流程](#2.1 Servlet开发流程)
    • [2.2 配置欢迎页](#2.2 配置欢迎页)
  • [3 Servlet案例开发!](#3 Servlet案例开发!)
    • [3.1 开发登录页](#3.1 开发登录页)
    • [3.2 开发后台Servlet](#3.2 开发后台Servlet)
    • [3.3 配置Servlet](#3.3 配置Servlet)
  • [4 HttpServletRequest](#4 HttpServletRequest)
  • [5 HttpServletResponse](#5 HttpServletResponse)
  • [6 关于乱码问题](#6 关于乱码问题)
  • [7 Servlet的继承结构](#7 Servlet的继承结构)
    • [7.1 Servlet接口](#7.1 Servlet接口)
    • [7.2 ServletConfig接口](#7.2 ServletConfig接口)
    • [7.3 GenericServlet抽象类](#7.3 GenericServlet抽象类)
    • [7.4 HttpServlet](#7.4 HttpServlet)
  • [8 Servlet的生命周期](#8 Servlet的生命周期)
    • [8.1 初始化时间问题](#8.1 初始化时间问题)
  • [9 ServletContext和servletConfig](#9 ServletContext和servletConfig)
    • [9.1 ServletContext 重要](#9.1 ServletContext 重要)
    • [9.1.1 ServletContext对象的作用](#9.1.1 ServletContext对象的作用)
    • [9.1.2 ServletContext对象的使用](#9.1.2 ServletContext对象的使用)
      • [9.1.2.1 基本使用](#9.1.2.1 基本使用)
      • [9.1.2.2 获取web.xml文件中的信息](#9.1.2.2 获取web.xml文件中的信息)
      • 9.1.2.3全局容器
    • [9.2 SerlvetConfig对象](#9.2 SerlvetConfig对象)
  • [10 ur-pattern的匹配规则](#10 ur-pattern的匹配规则)
    • [10.1 精确匹配](#10.1 精确匹配)
    • [10.2 扩展名匹配](#10.2 扩展名匹配)
    • [10.3 路径匹配](#10.3 路径匹配)
    • [10.4 任意匹配](#10.4 任意匹配)
    • [10.5 匹配所有](#10.5 匹配所有)
    • [10.6 优先顺序](#10.6 优先顺序)
    • [10.7 URL映射方式](#10.7 URL映射方式)
  • [11 注解模式开发Servlet](#11 注解模式开发Servlet)
  • [12 请求转发](#12 请求转发)
    • [12.1 forword处理流程](#12.1 forword处理流程)
    • [12.2 include处理流程](#12.2 include处理流程)
    • [12.3 总结](#12.3 总结)
  • [13 响应重定向](#13 响应重定向)
    • [13.1 总结](#13.1 总结)
  • [14 路径问题](#14 路径问题)
    • 14.1前段的路径问题
    • [14.2 请求转发的路径问题](#14.2 请求转发的路径问题)
    • [14.3 响应重定向的路径问题](#14.3 响应重定向的路径问题)
  • [15 会话管理](#15 会话管理)
    • [15.1 认识Cookie和Session](#15.1 认识Cookie和Session)
    • [15.2 Cookie的使用](#15.2 Cookie的使用)
  • [16 域对象](#16 域对象)

前言

开发工具专栏

上篇接tomcat

历史简单篇tomcat,servlet

1 Servlet简介

Servlet介绍

Servlet是Server Applet的简称,称为服务端小程序,是JavaEE平台下的技术标准,基于Java语言编写的服务端程序。Web容器或应用服务器实现了Servlet标准所以Servlet需运行在Web容器或应用服务器中。Servlet主要功能在于能在服务器中执行并生成数据。

Servlet技术特点

Servlet使用单进程多线程方式运行。

Servlet在应用程序中的位置

两个图来展示,帮助我们理解

静态资源和动态资源区分

静态资源:每次访问都不需要运算,直接就可以返回的资源,如HTML CSS JS多媒体文件等等,每次访问获得的资源都是一样的

动态资源:每次访问都需要运算代码生成的资源,如Servlet JSP ,每次访问获得的结果可能都是不一样的

Servlet作为一种动态资源技术,是我们后续学习框架的基础

Servlet在程序中到底处于一个什么地位?

Servlet是可以接受Http请求并作出相应的一种技术,是JAVA语言编写的一种动态资源

Servlet是前后端衔接的一种技术,不是所有的JAVA类都可以接收请求和作出相应,Servlet可以

在MVC模式中,Servlet作为Controller层(控制层)主要技术,用于和浏览器完成数据交互,控制交互逻辑

2 Servlet初识

2.1 Servlet开发流程

案例:
在后台随机生成一个整数当浏览器请求一个Servlet时 如果生成的是奇数,返回"happy new year"如果生成的是偶数,返回"happy birthday"

1创建一个JAVAWEB项目,并在项目中开发一个自己的Servlet ,继承HttpServlet类

一定要查看External Libraries中有Tomcat中的两个JAR jsp-api servlet-api

2在MyServlet类中重写service方法

如果我们想获得请求中的信息,就要通过HttpServetRequest对象获得

如果我们想给浏览器响应一些信息,就要通过HttpServletResponse对象响应

3在service方法中定义具体的功能代码

4在web.xml中配置Servlet的映射路径

上述图片我们设置的访问路径为localhost:/xxx

2.2 配置欢迎页

当我们访问项目名的时候为什么默认访问的是index.html呢?我们找到tomcat目录下conf/web.xml文件最后面可以看到,他帮我默认配置了输入了项目名访问的路径

假如我们想自定义默认路径可以在项目中的web.xml文件中进行配置
查找顺序是从上往下进行查找

3 Servlet案例开发!

案例开发需求

准备一个登录页,可以输入用户名和密码

输入完毕后向后台Servlet提交用户名和密码

Servlet接收到用户名和密码之后,校验是否正确

如果正确响应Success

如果不正确响应Fail

开发过程如下

3.1 开发登录页

在webapp文件夹下创建login.xml

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="get" action="loginServlet.do">
    <table style="margin: 0px auto" width="300px" cellpadding="0px" cellspacing="0px" border="1px">
        <tr><td>用户名</td><td><input type="text" name="username"></td></tr>
        <tr><td>密码</td><td><input type="password" name="pwd"></td></tr>
        <tr align="center"><td colspan="2"><input type="submit" value="登录"></td></tr>
    </table>
</form>
</body>
</html>

我们在web.xml文件中配置login.xml为根目录

xml 复制代码
    <welcome-file-list>
        <welcome-file>login.html</welcome-file>
    </welcome-file-list>

3.2 开发后台Servlet

创建LoginServlet 类继承HttpServlet并重写service方法

java 复制代码
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;

public class LoginServlet extends HttpServlet {
    @Override
    public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.err.println("进入了servlet");
        //获取请求中的数据
        String username = req.getParameter("username");
        String pwd = req.getParameter("pwd");
        //判断数据
        String message = null;
        if(username.equals("123") && pwd.equals("123")){
            message = "Success";
        }else{
            message = "Fail";
        }
        //作出响应
        resp.getWriter().write(message);
    }
}

3.3 配置Servlet

from表单中的action属性需要配置访问路径

我们在web.xml中配置LoginServlet 访问路径"/loginServlet.do"

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>loginServlet</servlet-name>
        <servlet-class>com.msr.demo_servlet.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>loginServlet</servlet-name>
        <url-pattern>/loginServlet.do</url-pattern>
    </servlet-mapping>


    <welcome-file-list>
        <welcome-file>login.html</welcome-file>
    </welcome-file-list>
</web-app>

运行测试

http://localhost:9008/demo_servlet_war_exploded/

4 HttpServletRequest

4.1 回顾http请求


请求行

请求头

请求体

get方式提交的请求数据通过地址栏提交没有请求体

post方式提交请求数据单独放到请求体中,

请求时所携带的数据(post方式)

http支持的请求方式

post和get方式提交请求的差别(面试重要)

  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET产生的URL地址可以被Bookmark,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行ur编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST则没有。对参数的数据类型GET只接受ASCI字符,而POST即可是字符也可是字节。
  • GETE比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。

4.2 自定义servlet流程图

4.3 HttpServletRequest

HttpServletRequest对象代表客户端浏览器的请求,当客户端浏览器通过HTTP协议访问服务器时,HTTP请求中的所有信息都
会被Tomcat所解析并封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

请求数据

4.4获取请求行信息

测试代码

java 复制代码
System.out.println("完整的URL:"+req.getRequestURL());//返回客户端浏览器发出请求时的完整URL。
System.out.println("请求的指定资源:"+req.getRequestURI());//返回请求行中指定资源部分。
System.out.println("客户端的IP:"+req.getRemoteAddr());//返回发出清求的客户机的IP地址。
System.out.println("WEB服务器IP:"+req.getLocalAddr());//返回WEB服务器的IP地址。
System.out.println("服务器端处理HTTP请求的端口:"+req.getLocalPort());//返回WEB服务器处理Http协议的连接器所监听的端口。
System.out.println("主机名:"+req.getLocalName());
System.out.println("客户端PORT:"+req.getRemotePort());
System.out.println("当前项目部署名:"+req.getContextPath());
System.out.println("协议名:"+req.getScheme());
System.out.println("请求方式:"+req.getMethod());

打印结果

java 复制代码
完整的URL:http://localhost:9008/demo_servlet_war_exploded/loginServlet.do
请求的指定资源:/demo_servlet_war_exploded/loginServlet.do
客户端的IP:0:0:0:0:0:0:0:1
WEB服务器IP:0:0:0:0:0:0:0:1
服务器端处理HTTP请求的端口:9008
主机名:0:0:0:0:0:0:0:1
客户端PORT:49648
当前项目部署名:/demo_servlet_war_exploded
协议名:http
请求方式:GET

4.5获取请求头信息

测试代码

java 复制代码
String headerValue = req.getHeader("accept-encoding");//根据请求头中的key获取对应的value。
System.out.println(headerValue);
//早期的Iterator
Enumeration<String> headerNames = req.getHeaderNames();//获取请求头中所有的key,该方法返回枚举类型。
while(headerNames.hasMoreElements()){
	String headerName = headerNames.nextElement();
	System.out.println(headerName+":"+req.getHeader(headerName));
	}

打印结果

java 复制代码
gzip, deflate, br
host:localhost:9008
connection:keep-alive
pragma:no-cache
cache-control:no-cache
sec-ch-ua:"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"
sec-ch-ua-mobile:?0
sec-ch-ua-platform:"Windows"
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
sec-fetch-site:same-origin
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
referer:http://localhost:9008/demo_servlet_war_exploded/
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
进入了servlet

4.6获取请求数据

在Servlet获取请求数据的方式

req.getParameter("key" );//根据key获取指定value。

String str = req.getParameter("key");
获取复选框(checkbox组件)中的值

eq.getParameterValues("checkboxkey );//获取复选框(checkbox组件)中的值,返回- -个String[I。

String[] userlikes = req.getParameterValues("checkboxkey");
获取所有提交数据的key

req.getParameterNames0);//获取请求中所有数据的key,该方法返回一个枚举类型。

Enumeration parameterNames = req.getParameterNames()
使用Map结构获取提交数据

req.getParameterMap0://获取请求中所有的数据并存放到一 个Map结构中,该方法返回一个Map,其中key为String类

型value为String[]类型。

Map<String, String[]> parameterMap = req.getParameterMap(;
设置请求编码

req.setCharacterEncoding("utf-8")

请求的数据包基于字节在网络上传输,Tomcat接收到请求的数据包后会将数据包中的字节转换为字符。在Tomcat中使用的

是ISO-8859-1的单字节编码完成字节与字符的转换,所以数据中含有中文就会出现乱码,可以通req.setCharacterEncoding("utf-8" )方法来对提交的数据根据指定的编码方式重新做编码处理。

测试代码

前段

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
开发form表单注意事项
1.form 不是from
2.form表单内部不是所有的标签信息都会提交  一些输入信息 input  select  textarea ...
3.要提交的标签必须具备name属性 name属性的作用是让后台区分数据 id属性是便于在前端区分数据
4.要提交的标签一般都要具备value属性 value属性确定我们要提交的具体的数据
5.get  post
    get方式数据是通过URL携带
     提交的数据只能是文本
     提交的数据量不大
     get方式提交的数据相对不安全
    post 将数据单独打包方法请求体中
     提交的数据可以是文本可以是各种文件
     提交的数据量理论上没有上线
     post方式提交数据相对安全

    当一个表单标签
    readonly只读 也是会提交数据的
    hidden隐藏 也是会提交数据
    disabled不可用 显示但是不提交
-->
<form method="get" action="myServlet">
    <table style="margin: 0px auto" width="300px" cellpadding="0px" cellspacing="0px" border="1px">
        <tr><td>用户名</td><td><input type="text" name="username"></td></tr>
        <tr><td>密码</td><td><input type="password" name="pwd"></td></tr>
        <tr><td>性别</td>
            <td>
                男<input type="radio" name="gender" value="1" checked>
                女<input type="radio" name="gender" value="0">
            </td>
        </tr>
        <tr><td>爱好</td>
            <td>
                <input type="checkbox" name="hobby" value="1">篮球
                <input type="checkbox" name="hobby" value="2">足球
                <input type="checkbox" name="hobby" value="3">羽毛球
                <input type="checkbox" name="hobby" value="4">乒乓球
            </td>
        </tr>
        <tr><td>个人简介</td>
            <td>
                <!--文本域 双标签 页面上显示的文字是双标签中的文本  不是value属性

                文本域提交的数据不是value属性值,是双标签中的文本
                -->
                <textarea name="introduce"></textarea>
            </td>
        </tr>
        <tr>
            <td>籍贯</td>
            <td>
                <select name="provience">
                    <option value="1">京</option>
                    <option value="2">津</option>
                    <option value="3">冀</option>
                </select>
            </td>
        </tr>
        <tr align="center"><td colspan="2"><input type="submit" value="提交数据"></td></tr>
    </table>
</form>
</body>
</html>

web.html

xml 复制代码
    <servlet>
        <servlet-name>myServlet</servlet-name>
        <servlet-class>com.msr.demo_servlet.servlet.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>myServlet</servlet-name>
        <url-pattern>/myServlet</url-pattern>
    </servlet-mapping>

后端

java 复制代码
public class MyServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // req获取参数
        //如果前端发过米的数据由教构名但是没有值,getParameter 返回的是一个空字符申 ""
        //获取的参数在提交的数据中名都没有,getParameter返回的是null
        String username = req.getParameter("username");
        System.out.println("username:"+username);
        System.out.println("password:"+req.getParameter("pwd"));
        System.out.println("gender:"+req.getParameter("gender"));
        //hobby=1&hobby=2&hobby=3 想要获得多个同名的参数 getParameterValues返回的是一个String数组
        //获取的参数在提交的数据中名都没有,getParameterValues返回的是null
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("hobbies:"+ Arrays.toString(hobbies));
        //textarea
        System.out.println("introduce:"+req.getParameter("introduce"));
        //select
        System.out.println("provience:"+req.getParameter("provience"));
        System.out.println("-----------------------------------------");
        //如果不知道参数的名字?
        //获取所有的参数名
        Enumeration<String> parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()){
            String pname = parameterNames.nextElement();
            String[] parameterValues = req.getParameterValues(pname);
            System.out.println(pname+":"+Arrays.toString(parameterValues));
        }
        System.out.println("---------------------------------------");
        Map<String, String[]> parameterMap = req.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            System.out.println(entry.getKey()+":"+Arrays.toString(entry.getValue()));
        }
    }
}

输出

java 复制代码
username:aaa
password:123
gender:1
hobbies:[1, 2, 3]
introduce:111
provience:2
-----------------------------------------
username:[aaa]
pwd:[123]
gender:[1]
hobby:[1, 2, 3]
introduce:[111]
provience:[2]
---------------------------------------
username:[aaa]
pwd:[123]
gender:[1]
hobby:[1, 2, 3]
introduce:[111]
provience:[2]

5 HttpServletResponse

5.1回顾http响应

http响应部分可以分为三部分:响应行,响应头,响应体

响应行

响应状态码列表如下

响应头

Content-Type:响应内容的类型(MIME)
响应实体

服务器响应回来的内容

5.2HttpServletResponse

HttpServletResponse对象代表服务器的响应。这个对象中封装了响应客户端浏览器的流对象,以及向客户端浏览器响应的响应头、响应数据、响应状态码等信息。

响应的设置

ContentType响应头

resp.setContentType("MIME");//该方法可通过MIME-Type设置响应类型。

MIME的全称是Multipurpose Internet Mail Extensions,即多用途互联网邮件扩展类型。

这是HTTP协议中用来定义文档性质及格式的标准。对HTTP传输内容类型进行了全面定义。
服务器通过MIME告知响应内容类型,而浏览器则通过MIME类型来确定如何处理文档。

代码

java 复制代码
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //行相关信息
        resp.setStatus(500);
        //头相关信息
        resp.setHeader("Date","2022-2-2");
        resp.setHeader("aaa","xxx");
        //Content-Type响应头 响应给浏览器的MIME类型
        // 如果想知道都可以响应什么类型可以去tomcat的web.xml文件中查看 大概650行开始,有很多
        resp.setHeader("Content-Type","text/html");
        //体相关信息
        PrintWriter writer = resp.getWriter();
        writer.write("<h1>this is tag h1<h1/>");
    }

6 关于乱码问题

6.1控制台乱码

tomcat有三个打印日志的地方
Server乱码

修改

找到tomcat中的日志配置文件编码改为GBK

如果其他两个日志也是乱码

修改为GBK

6.2post请求乱码

通过HttpServletRequest设置请求编码

6.3get请求乱码

需要手动进行编码解码,或者设置tomcat中的server.xml中的URL编码,tomcat9已经解决了该问题

6.4响应乱码

通过HttpServletResponse设置响应编码

7 Servlet的继承结构

7.1 Servlet接口

1.init(),创建Servlet对象后立即调用该方法完成其他初始化工作。

2.getServletConfig(),ServletConfig是容器向servlet传递参数的载体。

3.service(),处理客户端请求,执行业务操作,利用响应对象响应客户端请求。

4.getServletlnfo(),获取servlet相关信息

5.destroy(),在销毁Servlet对象之前调用该方法,释放资源。

7.2 ServletConfig接口

Servlet运行期间,需要一些辅助信息,这些信息可以在web.xml文件中,使用一个或多个元素,进行配置。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中,通过调用init(ServletConfig config)方法,将ServletConfig对称传递给Servlet

7.3 GenericServlet抽象类

GenericServlet是实现了Servlet接口的抽象类。在GenericServlet中进一步的定义了Servlet接口的具体实现,其设计的目的是为了和应用层协议解耦,在GenericServlet中包含一个Service抽象方法。我们也可以通过继承GenericServlet并实现Service方法实现请求的处理,但是需要将ServletReuqest和ServletResponse转为HttpServletRequest和HttpServletResponse。

7.4 HttpServlet

继承自GercSenvlt.针对于处理HTP协议的青求所定制。在Httpendeb的sevcel)方法中已经把Se veReucet和Se verRspone转为HtperveBleuest和Htpservrtrkesponse。直按使甲用HtoSenveEkeqest和HttpServletResponse,不再需要强转。实际开发中,直接继承HttpServlet,并根据请求方式复写doXx()方法即可。

在我们自定义的Servlet中,如果想区分请求方式不同的请求方式使用不同的代码处理,那么我么重写doGet doPost即可如果我们没有必要区分请求方式的差异,那么我们直接重写service方法即可

8 Servlet的生命周期

Servlet的生命周期是由容器管理的,分别经历四各阶段:

java 复制代码
>阶段            次数     时机
>创建		     1次      第一次请求
>初始化          1次      实例化之后 
>执行服务        多次      每次请求
>销毁            一次     停止服务

当客户端浏览器第一次请求Servlet时,容器会实例化这个Servlet,然后调用一次init方法,并在新的线程中执行service方法处理请

求。service方法执行完毕后容器不会销毁这个Servlet而是做缓存处理,当客户端浏览器再次请求这个Servlet时,容器会从缓存中直接找到这个Servlet对象,并再一次在新的线程中执行Service方法。当容器在销毁Servlet之前对调用一次destory方法。

注意:
在Serlvet中我们一般不要轻易使用成员变量!!! 可能会造成线程安全问题
如果要使用的话,应该尽量避免对成员变量产生影响修改
如果要产生影响我们应该注意线程安全问题
如果我们自己添加线程安全编码处理,会严重影响效率
综上所述:原则,能不用成员变量就不用!!!

8.1 初始化时间问题

假如servlet的初始化时间比较长,这就会导致我们第一次访问页面的时候会等待较长的时间,这样我们可以在web.xml文件中配置servlet自动初始化,这样他就会在tomcat启动的时候进行初始化

设置初始化顺序从6开始,前五个被tomcat使用了

xml 复制代码
<servlet>
	<servlet-name>myServlet</servlet-name>
	<servlet-class>com.msr.demo_servlet.servlet.MyServlet</servlet-class>
	<load-on-startup>6</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>myServlet</servlet-name>
	<url-pattern>/myServlet</url-pattern>
</servlet-mapping>

9 ServletContext和servletConfig

9.1 ServletContext 重要

ServletContext官方叫Servlet上下文。服务器会为每一个Web应用创建一个ServletContext对象。这个对象全局唯一,而且Web应用中的所有Servlet都共享这个对象。所以叫全局应用程序共享对象

9.1.1 ServletContext对象的作用

  • 相对路径转绝对路径
  • 获取容器的附加信息
  • 读取配置信息
  • 全局容器

9.1.2 ServletContext对象的使用

9.1.2.1 基本使用

获取项目的部署名

context.getContextPath()

相对路径转绝对路径(文件上传下载时需要注意)

context.getRealPath("path")

该方法可以将一个相对路径转换为绝对路径,在文件上传与下载时需要用到该方法做路径的转换。获取容器的附加信息

servletContext.getServerlnfo()

返回Servlet容器的名称和版本号

servletContext.getMajorVersion()

返回Servlet容器所支持Servlet的主版本号servletContext.getMinorVersion()

返回Servlet容器所支持Servlet的副版本号。

代码

java 复制代码
public class Servlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //获取Servlet对象的方式
        //通过req对象
        ServletContext servletContext1 = req.getServletContext();
        //通过继承的方式
        ServletContext servletContext2 = this.getServletContext();
        System.out.println(servletContext1 ==servletContext2);

        //获取当前项目的部署名
        String contextPath= servletContext1.getContextPath();
        System.out.println("contextPath"+contextPath);
		//将一个相对路径转化为项目的绝对路径
        String fileupload = servletContext1.getRealPath( "fileupload");
        System.out.println(fileupload);
        String serverInfo = servletContext1.getServerInfo();
        System.out.println( "servletInfo"+serverInfo);
        int majorversion = servletContext1.getMajorVersion();
        int minorVersion = servletContext1.getMinorVersion();
        System.out. println(majorversion+":"+minorVersion);
	}
}

输出

java 复制代码
true
contextPath/demo_servlet_war_exploded
D:\word\demo_servlet\target\demo_servlet-1.0-SNAPSHOT\fileupload
servletInfoApache Tomcat/8.5.45
3:1

web.xml文件

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>Servlet1</servlet-name>
        <servlet-class>com.msr.demo_servlet.servlet.Servlet1</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/servlet1.do</url-pattern>
    </servlet-mapping>
</web-app>

9.1.2.2 获取web.xml文件中的信息

servletContext.getlnitParameter("key")

该方法可以读取web.xml文件中标签中的配置信息。servletContext.getInitParameterNames()

该方法可以读取web.xml文件中所有param-name标签中的值。

在web.xml中设置共享的数据

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>username</param-name>
        <param-value>123</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>456</param-value>
    </context-param>
</web-app>

通过servletContext获取web.xml中的数据

web.xml中数据会保存到ServletContext ,通过HttpServletRequest可以拿到上下文对象ServletContext

java 复制代码
public class Servlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	ServletContext servletContext1 = req.getServletContext();
        String username = servletContext1.getInitParameter("username");
        String password = servletContext1.getInitParameter("password");
        System.out.println(username+":"+password);
        }
}

9.1.2.3全局容器

servletContext.setAttribute("key" ,ObjectValue)向全局容器中存放数据。

servletContext.getAttribute("key")从全局容器中获取数据。

servletContext.removeAttribute("key")根据key删除全局容器中的value。

java 复制代码
ArrayList<Object> data = new ArrayList<>();
Collections.addAll(data,"张三","李四","王五");
servletContext1.setAttribute("list",data);

然后可以通过不同的servlet进行读取

java 复制代码
ServletContext servletContext2 = req.getServletContext();
String username = servletContext2.getInitParameter("username");
String password = servletContext2.getInitParameter("password");
System.out.println(username+":"+password);

List<String> list =(List<String>) servletContext2.getAttribute("list");
System.out.println(list);

9.2 SerlvetConfig对象

ServletConfig对象对应web.xml文件中的节点。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封个ServletConfia对象中。我们可以通过该对象读取节点中的配置信息

servletConfig.getlnitParameter("key");

该方法可以读取web.xml文件中标签中标签中的配置信息。servletConfig.getInitParameterNames();

该方法可以读取web.xml文件中当前标签中所有标签中的值。

web.xml文件

测试代码

java 复制代码
 @Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	ServletConfig servletConfig = this.getServletConfig();       
	System.out.println(servletConfig.getInitParameter("brand"));
}

10 ur-pattern的匹配规则

10.1 精确匹配

精确匹配是指<url-pattern>中配置的值必须与url完全精确匹配。

http://localhost:8080/demo/demo.do 匹配

http://localhost:8080/demo/suibian/demo.do 不匹配

10.2 扩展名匹配

在允许使用统配符""作为匹配规则," "表示匹配任意字符。在扩展名匹配中只要扩展名相同都会被匹配和路径无关。注意,在使用扩展名匹配时在中不能使用"r",否则容器启动就会抛出异常。

http://localhost:8080/demo/demo.do 匹配

http://localhost:8080/demo/suibian/demo.do 匹配

10.3 路径匹配

根据请求路径进行匹配,在请求中只要包含该路径都匹配。"*"表示任意路径以及子路径。

http://localhost:8080/demo/suibian/demo.do 匹配

http://localhost:8080/demo/suibian/hehe/demo.do 匹配

http://localhost:8080/demo/hehe/demo.do 不匹配

10.4 任意匹配

匹配"/".匹配所有但不包含JSP页面

http://localhost:8080/demo/suibian.do 匹配

http://localhost:8080/demo/suibian.html 匹配

http://localhost:8080/demo/123/suibian.css 匹配

http://localhost:8080/demo/123/suibian.jsp 不匹配

10.5 匹配所有

http://localhost:8080/demo/suibian.do 匹配

http://localhost:8080/demo/suibian.html 匹配

http://localhost:8080/demo/123/suibian.css 匹配

http://localhost:8080/demo/123/suibian.jsp 匹配

10.6 优先顺序

当一个url与多个Servlet的匹配规则可以匹配时,则按照"精确路径>最长路径>扩展名"这样的优先级匹配到对应的Servlet。
案例分析

10.7 URL映射方式

方式一

方式二

11 注解模式开发Servlet

这里不做过多解释(与目录9.ServletContext和servletConfig原理一样)

java 复制代码
//@WebServlet(urlPatterns = "Servlet1.do")
@WebServlet(urlPatterns = {"Servlet1.do","12.do"},
        	loadOnStartup = 6,
        	initParams = {@WebInitParam(name = "brand1",value = "123"),
                      	  @WebInitParam(name = "brand2",value = "321")
                     })
public class Servlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

12 请求转发

12.1 forword处理流程

1清空Response存放响应正文数据的缓冲区。

2如果目标资源为Servlet或JSP,就调用它们的service()方法,把该方法产生的响应结果发送到客户端;如果目标资源文件系统中的静态HTML文档,就读取文档中的数据把它发送到客户端。

forword处理特点:

1由于forword()方法先清空用于存放响应正文的缓冲区,因此源Servlet生成的响应结果不会被发送到客户端,只有目标资源生成的响应结果才会被发送到客户端。

2如果源Servlet在进行请求转发之前,已经提交了响应结(flushBuffer(),close()方法),那么forward()方法抛出lllegalStateException。为了避免该异常,不应该在源Servlet中提交响应结果。

代码

Servlet1

java 复制代码
@WebServlet(name = "servlet1", value = "/servlet1.do")
public class Servlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet1.do");
        String money = req.getParameter("money");
        System.out.println("money:"+money);

        resp.getWriter().println("asdasd");//响应无效 后边进行了转发

        //请求转发给另一个组件
        //获取请求转发器
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("servlet2.do");
        //由请求转发器作出转发
        requestDispatcher.forward(req,resp);

//在forward转发模式下,请求应该完全交给目标资源去处理,我们在源组件中,不要作出任何的响应处理
//在forward方法调用之后,也不要在使用req和resp对象做其他操作了
    }
}

Servlet2

java 复制代码
@WebServlet(name = "servlet2", value = "/servlet2.do")
public class Servlet2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet2.do");

        String money = req.getParameter("money");
        System.out.println("money:"+money);

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

        PrintWriter writer = resp.getWriter();
        writer.println("支付宝到账:"+money+"元");
    }

}

访问接口:http://localhost:9008/demo_servlet_war_exploded/servlet1.do?money=100

12.2 include处理流程

1如果目标资源为Servlet或JSP,就调用他们的相应的service()方法,把该方法产生的响应正文添加到源Servlet的响应结果中;如果目标组件为HTML文档,就直接把文档的内容添加到源Servlet的响应结果中。

2返回到源Servlet的服务方法中,继续执行后续代码块。

include()处理特点

include与forward转发相比,包含有以下特点:

1源Servlet与被包含的目标资源的输出数据都会被添加到响应结果中。2在目标资源中对响应状态码或者响应头所做的修改都会被忽略。

代码
Servlet1

java 复制代码
@WebServlet(name = "servlet1", value = "/servlet1.do")
public class Servlet1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet1.do");
        String money = req.getParameter("money");
        System.out.println("money:"+money);

        设置响应类型和编码(include模式下)
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        //增加响应内容(include)
        resp.getWriter().println("servlet1在转发之前做出相应内容");

        //请求转发给另一个组件
        //获取请求转发器
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("servlet2.do");
        //由请求转发器作出转发
        //equestDispatcher.forward(req,resp);
        requestDispatcher.include(req,resp);

        //继续增加响应内容(include)
        resp.getWriter().println("servlet1在转发之后做出相应内容");
    }
}

Servlet2

java 复制代码
@WebServlet(name = "servlet2", value = "/servlet2.do")
public class Servlet2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet2.do");

        String money = req.getParameter("money");
        System.out.println("money:"+money);

        //设置响应类型和编码(forward模式下)
        // resp.setCharacterEncoding("UTF-8");
        // resp.setContentType("text/html;charset=UTF-8");

        resp.getWriter().println("支付宝到账:"+money+"元");
    }

}

访问接口:http://localhost:9008/demo_servlet_war_exploded/servlet1.do?money=100

12.3 总结

java 复制代码
//在forward转发模式下,请求应该完全交给目标资源去处理,我们在源组件中,不要作出任何的响应处理
//在forward方法调用之后,也不要在使用req和resp对象做其他操作了
//在incLude较发模式下,设置响应可以在转发之前,也可以在转发之后
/*
*1请求转发是一种服务器的行为,是对浏览嚣器屏蔽
*2浏览器的地址栏不会发生变化
*3请求的参数是可以从源组件传递到目标组件的
*4请求对象和响应对象没有重新创建,而是传递给了目标组件*5请求转发可以帮助我们完成页面的跳转
*6请求转发可以转发至wEB-工NF里
*7请求转发只能转发给当前项目的内部资源,不能转发至外部资源
*8常用forward
**/

13 响应重定向

代码

Servlet3

java 复制代码
@WebServlet(name = "servlet3", value = "/servlet3.do")
public class Servlet3 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet3");
        String money = req.getParameter("money");
        System.out.println("money:"+money);
        //响应重定向
        resp.sendRedirect("servlet4.do");
    }
}

Servlet4

java 复制代码
@WebServlet(name = "servlet4", value = "/servlet4.do")
public class Servlet4 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet4");
    }
}

访问接口:http://localhost:9008/demo_servlet_war_exploded/servlet3.do?money=100

13.1 总结

java 复制代码
//响应重定向
resp.sendRedirect(s:"servlet4.do?money="+money); 
//resp.sendRedirect("wEB-INF/bbb.htmL");
// resp.sendRedirect("https://www.baidu.com");
/*
*响应重定向总结
*1重定向是服务器给浏览器重新指定请求方向是一种浏览器行为地址栏会发生变化
* 2重定向时,请求对象和响应对象都会再次产生,请求中的参数是不会携带
*3重定向也可以帮助我们完成页面跳转
*4重定向不能帮助我们访问wEB-INF中的资源
*5重定向可以定向到外部资源

14 路径问题

14.1前段的路径问题

项目结构

a2.html和b1.html代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
this is a2/b1
</body>
</html>

a1.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--
    2.
    base标签的作用是在相对路径之前自动补充base[href]中的值
    如果base标签不写,那么默认就是当前文件所在的路径
    -->
    <base href="http://127.0.0.1:9008//demo_servlet_war_exploded/">
</head>
<body>
this is a1
<!--
1.
相对(基准)路径:以当前文件本身的位置去定位其他文件,相对自己的路径,以当前文件所在的位置为基准位置
绝对(基准)路径:以一个固定的位置去定位其他文文件,以一个固定的路径作为定位文件的基准位置,和文件本身位置无关

相对路怪,不以/开头,就是相对路程..代表向上一层
绝对路径,以/开头―在页面上/代表从项目的部署目录开始找﹑从webapps中开始找
页面的绝对路径要有项目名,除非我们的项目没有设置项目名
-->

<a href="a2.html" target="_self">相对路径跳转a2</a>
<a href="../../b/b2/b1.html" target="_self">相对路径跳转b1</a>

<a href="a/a2/a2.html" target="_self">base相对路径跳转a2</a>
<a href="b/b2/b1.html" target="_self">base相对路径跳转b1</a>

<a href="/demo_servlet_war_exploded/a/a2/a2.html" target="_self">绝对路径跳转a2</a>
<a href="/demo_servlet_war_exploded/b/b2/b1.html" target="_self">绝对路径跳转b1</a>
</body>
</html>

14.2 请求转发的路径问题

14.3 响应重定向的路径问题

15 会话管理

15.1 认识Cookie和Session

Cookie对象与HttpSession对象简介

Cookie对象与HttpSession对象的作用是维护客户端浏览器与服务端的会话状态的两个对象,由于HTTP协议是一个无状态的协议,所以服务端并不会记录当前客户端浏览器的访问状态,但是在有些时候我们是需要服务端能够记录客户端浏览器的访问状态的,如获取当前客户端浏览器的访问服务端的次数时就需要会话状态的维持。在Servlet中提供了Cookie对象与Httpsession对象用于维护客户端与服务端的会话状态的维持。二者不同的是Cookie是通过客户端浏览器实现会话的维持,而HttpSession是通过服务端来实现会话状态的维持。

如何记录用户状态信息原理,举例:会员卡,银行卡

用户记录用户状态的技术

15.2 Cookie的使用

Cookie是一种保存少量信息至浏览器的一种技术,第一请求时,服务器可以响应给浏览器一些Cookie信息,第二次请求浏览器会携带之前的cookie发送给服务器,通过这种机制可以实现在浏览器端保留一些用户信息.为服务端获取用户状态获得依据

Cookie对象的特点

  • Cookie使用字符串存储数据
  • Cookie使用Key与Value结构存储数据单个
  • Cookie存储数据大小限制在4097个字节
  • Cookie存储的数据中不支持中文,Servlet4.0中支持
  • Cookie是与域名绑定所以不支持跨━级域名访问
  • Cookie对象保存在客户端浏览器内存上或系统磁盘中
  • Cookie分为持久化Cookie(保存在磁盘上)与状态Cookie(保存在内存上)
  • 浏览器在保存同一域名所返回Cookie的数量是有限的。不同浏览器支持的数量不同,Chrome浏览器为50个
  • 浏览器每次请求时都会把与当前访问的域名相关的Cookie在请求中提交到服务端。

Cookie对象的创建

Cookie cookie = new Cookie("key" , "value")

通过new关键字创建Cookie对象

response.addCookie(cookie)

通过HttpServletResponse对象将Cookie写回给客户端浏览器。

Cookie中数据的获取

通过HttpServletRequest对象获取Cookie,返回Cookie数组.

Cookie[] cookies = request.getCookies();

Cookie不支持中文解决方案

在Servlet4.0版本之前的Cookie中是不支持中文存储的,如果存储的数据中含有中文,代码会直接出现异常。我们可以通过对含有中文的数据重新进行编码来解决该问题。在Servlet4.0中的Cookie是支持中文存储的。

可以使用对中文进行转码处理

URLEncoder.encode("content","code")

将内容按照指定的编码方式做URL编码处理。URLDecoder.decode("content" ,"code")

将内容按照指定的编码方式做URL解码处理。

Cookie持久化和状态Cookie

状态Cookie:浏览器会缓存Cookie对象。浏览器关闭后Cookie对象销毁。

持久化Cookie:浏览器会对Cookie做持久化处理,基于文件形式保存在系统的指定目录中。在Windows10系统中为了安全问题不会显示Cookie中的内容。

当Cookie对象创建后默认为状态Cookie。可以使用Cookie对象下的cookie.setMaxAge(60)方法设置失效时间,单位为秒。一旦设置了失效时间,那么该Cookie为持久化Cookie,浏览器会将Cookie对象持久化到磁盘中。当失效时间到达后文件删除。

16 域对象

待编写

相关推荐
J不A秃V头A28 分钟前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡30 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
小池先生41 分钟前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
CodeClimb1 小时前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
odng1 小时前
IDEA自己常用的几个快捷方式(自己的习惯)
java·ide·intellij-idea
CT随1 小时前
Redis内存碎片详解
java·开发语言
brrdg_sefg1 小时前
gitlab代码推送
java
hanbarger1 小时前
mybatis框架——缓存,分页
java·spring·mybatis
cdut_suye2 小时前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
苹果醋32 小时前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx