JavaWeb---Servlet 学习笔记

1、Servlet

1.1、Servlet概述

Servlet主要用于处理客户端传来的HTTP请求,并返回一个响应。Servlet由Servlet容器提供,Servlet容器将Servlet动态的加载到服务器上。与HTTP协议相关的Servlet使用HTTP请求和HTTP响应与客户端进行交互。因此,Servlet容器支持所有HTTP协议的请求响应。

image-20210827222239281

在上图中,Servlet的请求首先会被HTTP服务器(如Apache)接收,HTTP服务器值负责静态HTML页面的解析,对于SErvlet的请求转交给Servlet容器,Servlet容器会根据web.xml文件中的映射关系,调用相应的Servlet,Servlet将处理的结果返回给Servlet容器,并通过HTTP服务器响应给客户端。

1.2、Sercvlet开发入门

1.从原型中创建maven工程,然后删除src文件夹

image-20210826132616031

2.在刚才创建的工程中创建子module,

image-20210826132917299

3.将web.xml中的文件替换为webapp4.0版本,和Tomcat保持一致。

<?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">

</web-app>

4.编写自己的类继承HttpServlet,重写方法

package com.nty.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("进入了doGet方法");
        PrintWriter writer = resp.getWriter();//响应流
        writer.print("Hello servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

5.在web.xml文件中注册Servlet,编写Servlet的映射

    <!--注册Servlet-->
    <servlet>
        <!--Servlet名称-->
        <servlet-name>hello</servlet-name>
        <!--Servlet类所在的位置-->
        <servlet-class>com.nty.servlet.HelloServlet</servlet-class>
    </servlet>

    <!--请求的路径:虚拟路径-->
    <servlet-mapping>
        <!--Servlet名称-->
        <servlet-name>hello</servlet-name>
        <!--虚拟路径-->
        <url-pattern>/hello</url-pattern>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

6.配置Tomcat,

image-20210826134009790

7.启动测试

image-20210826134120244

1.3、Servlet原理

image-20210826135439381

1.4、Mapping问题

1.一个Servlet可以指定一个映射路径

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

2.一个Servlet可以指定多个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello4</url-pattern>
    </servlet-mapping>
    </servlet-mapping>

3.一个Servlet可以指定通用映射路径

<servlet-mapping>
	<servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
</servlet-mapping>

4.默认请求路径

<servlet-mapping>
	<url-pattern>/hello</url-pattern>
	<url-pattern>/*</url-pattern>
</servlet-mapping>

5.指定一些后缀或前缀等等...

<!--可以自定义后缀实现请求映射
    注意点,*前面不能加项目映射的路径
    abc.do
    -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

6.优先级问题

指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;

<!--404-->
<servlet>
    <servlet-name>error</servlet-name>
    <servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>error</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

1.5、ServletConfig接口

1、什么是ServletConfig对象?
  Servlet/Jsp容器创建一个Servlet类型的对象时,会为这个Servlet对象创建一个唯一的ServletConfig对象。在ServletConfig对象中包含了Servlet的初始化参数信息。在Servlet的配置文件中,可以用一个或多个init-param标签为Servlet配置一些初始化参数。当Servlet配置了初始化参数之后,Web容器在创建Servlet实例对象时,会自动将这些初始化参数封装到这个Servlet对象对应的ServletConfig对象中,并在调用Servlet的init()方法时,将ServletConfig对象传递给Servlet。进而,程序员通过ServletConfig对象得到当前Servlet的初始化参数信息。

2、ServletConfig的常用方法

方法说明 功能描述
String getInitParameter(String name) 根据参数名取得参数值
Enumeration getInitParameterNames() 取得标签中配置的所有参数的参数名
ServletContext getServletContext() 返回一个代表当前web应用的Servletontext对象
String getServletName() 取得当前Servlet的名称

3、ServletConfig获取web.xml文件中为Servlet配置的初始化参数案例

web.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>
        <servlet-name>test01</servlet-name>
        <servlet-class>com.nty.servlet.TestServlet01</servlet-class>
        <!--要设置的参数-->
        <init-param>
            <!-- 参数名称-->
            <param-name>encoding</param-name>
            <!--参数的值-->
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>

    <!--虚拟路径-->
    <servlet-mapping>
        <servlet-name>test01</servlet-name>
        <url-pattern>/test</url-pattern>
    </servlet-mapping>

</web-app>

Java类文件

package com.nty.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class TestServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        //获得ServletConfig对象
        ServletConfig servletConfig = this.getServletConfig();
        //获得参数名为encoding对应的参数值
        String encoding = servletConfig.getInitParameter("encoding");
        writer.println("encoding=" + encoding);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

1.6、ServletContent接口

1、什么是ServletContent对象?

当Web容器(Tomcat)启动,且Web应用加载完成后,Web容器立即为该Web应用创建一个的ServletContext对象代表当前Web应用。每一个Web应用都有且仅有一个ServletContext对象,又称Application对象。该对象不仅封装了当前web应用的所有信息,而且实现了多个Servlet之间数据的共享。

2、ServletContext案例

web.xml

<!-- 添加下述代码-->
    <context-param>
        <param-name>companyName</param-name>
        <param-value>test</param-value>
    </context-param>
    <context-param>
        <param-name>address</param-name>
        <param-value>beijing</param-value>
    </context-param>

类文件

package com.nty.servlet;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

public class TestServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        //得到ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //得到包含所有初始化参数名的Enumeration对象
        Enumeration<String> parameterNames = servletContext.getInitParameterNames();
        writer.println("all the paramName and paramValue are following:");
        //遍历所有初始化参数名,得到相应的参数并打印
        while (parameterNames.hasMoreElements()) {
            String name = parameterNames.nextElement();
            String value = servletContext.getInitParameter(name);
            writer.println(name + ": " + value);
            writer.println("<br />");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

2、实现多个Serlvet对象共享数据

TestServlet01

package com.nty.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


public class TestServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        //得到ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //通过getAttribute()方法获取属性值
        String data = (String) servletContext.getAttribute("data");
        writer.println(data);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

TestServlet02

package com.nty.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet02 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //通过setAttribute()方法设置属性值
        context.setAttribute("data", "this servlet save data");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

web.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>
        <servlet-name>test01</servlet-name>
        <servlet-class>com.nty.servlet.TestServlet01</servlet-class>
    </servlet>

    <servlet>
        <servlet-name>test02</servlet-name>
        <servlet-class>com.nty.servlet.TestServlet02</servlet-class>
    </servlet>

    <!--虚拟路径-->
    <servlet-mapping>
        <servlet-name>test01</servlet-name>
        <url-pattern>/test01</url-pattern>
    </servlet-mapping>
    
    <servlet-mapping>
        <servlet-name>test02</servlet-name>
        <url-pattern>/test02</url-pattern>
    </servlet-mapping>

</web-app>

浏览器中先访问test02,再访问test01,然后将会出现结果

3、读取web应用下的资源文件

1.resources文件夹下建立properties文件

image-20210827231526484

Company = nty
Address = BeiJin

2.编写servlet类文件

package com.nty.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;

public class TestServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/test.properties");

        Properties prop = new Properties();
        prop.load(is);
        String company = prop.getProperty("Company");
        String address = prop.getProperty("Address");

        resp.getWriter().print(company + ":" + address);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

2、请求和响应

2.1、HttpServletRespose对象

HttpServletRespose继承自ServletRespose接口,专门用来封装HTTP响应消息。HTTP响应消息分为状态行,响应消息头,消息体三部分。

1、发送状态码

  1. setStatus(int status)方法
  2. sendError(int sc)方法
    void sendError(int var1, String var2) throws IOException;

    void sendError(int var1) throws IOException;

2、发送响应消息头

void sendRedirect(String var1) throws IOException;

    void setDateHeader(String var1, long var2);

    void addDateHeader(String var1, long var2);

    void setHeader(String var1, String var2);

    void addHeader(String var1, String var2);

    void setIntHeader(String var1, int var2);

    void addIntHeader(String var1, int var2);

    void setStatus(int var1);

3、发送响应消息体相关的方法

  1. getOutputStream()方法
  2. getWriter()方法

下面是两个发送响应消息体的案例:


package com.nty.response;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class PrintServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String data = "nty";
        //获取字节流输出对象啊
        ServletOutputStream outputStream = resp.getOutputStream();
        //输出信息
        outputStream.write(data.getBytes());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

package com.nty.response;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String data = "ntyxhx";
        //获取字节流输出对象啊
        PrintWriter printWriter = resp.getWriter();
        //输出信息
        printWriter.write(data);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

2.1.1、HttpServletRespose应用

1、解决中文输出乱码

//在自己编写的servlet类中加入下列三种方法其中之一
resp.setCharacterEncoding("utf-8");

resp.setCharacterEncoding("utf-8");
resp.setHeader("Content-Type", "text/html;charset=utf-8");

resp.setHeader("text/html;charset=utf-8");

2、重定向

2.2、HttpServletRequest对象

1、获取请求信息的相关方法

2、获取请求消息头的相关方法

方法声明 功能描述
String getMethod() 该方法用于获取 HTTP 请求消息中的请求方式(如 GET、POST 等)
String getRequestURI() 该方法用于获取请求行中的资源名称部分即位于 URL 的主机和端门之后、参数部分之前的部分
String getQueryString() 该方法用于获取请求行中的参数部分,也就是资源路径后问号(?)以后的所有内容
String getContextPath() 该方法用于获取请求 URL 中属于 Web 应用程序的路径,这个路径以 / 开头,表示相对于整个 Web 站点的根目录,路径结尾不含 /。如果请求 URL 属于 Web 站点的根目录,那么返回结果为空字符串("")
String getServletPath() 该方法用于获取 Servlet 的名称或 Servlet 所映射的路径
String getRemoteAddr() 该方法用于获取请求客户端的 IP 地址,其格式类似于 192.168.0.3
String getRemoteHost() 该方法用于获取请求客户端的完整主机名,其格式类似于 pcl.mengma.com。需要注意的是,如果无法解析出客户机的完整主机名,那么该方法将会返回客户端的 IP 地址
int getRemotePort() 该方法用于获取请求客户端网络连接的端口号
String getLocaIAddr() 该方法用于获取 Web 服务器上接收当前请求网络连接的 IP 地址
String getLocalName() 该方法用于获取 Web 服务器上接收当前网络连接 IP 所对应的主机名
int getLocalPort() 该方法用于获取 Web 服务器上接收当前网络连接的端口号
String getServerName() 该方法用于获取当前请求所指向的主机名,即 HTTP 请求消息中 Host 头字段所对应的主机名部分
int gctServcrPort() 该方法用于获取当前请求所连接的服务器端口号,即 HTTP 请求消息中 Host 头字段所对应的端口号部分
StringBuffcr getRequestURL() 该方法用于获取客户端发出请求时的完整 URL,包括协议、服务器名、端口号、 资源路径等信息,但不包括后面的査询参数部分。注意,getRequcstURL() 方法返冋的结果是 StringBuffer 类型,而不是 String 类型,这样更便于对结果进行修改

案例:

package com.nty.request;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

public class RequestHeaderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        //获取请求消息中的所有头字段
        Enumeration headerNames = req.getHeaderNames();
        //循环遍历所有请求头,并通过getHeader()方法获取一个指定名称的头字段
        while (headerNames.hasMoreElements()) {
            String hn = (String) headerNames.nextElement();
            writer.println(hn + ":" + req.getHeader(hn) + "<br/>");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

host:localhost:8080
connection:keep-alive
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 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.9
sec-fetch-site:none
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
cookie:JSESSIONID=5BA1E7B8E0A058EF3BAFE4BCBE0AB5AC

2.2.1、HttpServletRequest应用

3、剩余内容

代码:JavaWeb学习代码: 记录学习JavaWeb时的代码,顺便熟悉git使用。 (gitee.com)

教程:Servlet教程 (biancheng.net)

posted @ 2021-08-01 15:11  NotYourferry  阅读(108)  评论(0编辑  收藏  举报