• 【JavaWeb】Servlet技术


    一.Servlet

    1.Servlet概念
    (1).是JavaEE规范之一,规范就是接口.
    (2).是JavaWeb三大组件之一,三大组件分别是:Servlet程序、Filter过滤器、Listener监听器.
    (3).是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端.

    2.手动实现Servlet程序

    (1).编写一个类去实现Servlet接口.
    (2).实现service方法,处理请求并响应数据.

    package com.servlet;
    import javax.servlet.*;
    import java.io.IOException;
    public class HelloServlet implements Servlet{
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
        }
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
                   System.out.println("Hello Servlet");
        }
        @Override
        public String getServletInfo() {
            return null;
        }
        @Override
        public void destroy() {
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    (3).到web.xml中去配置Servlet程序的访问地址.

    <?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标签给Tomcat配置Servlet程序-->
        <servlet>
            <!--servlet-name标签给Servlet程序起一个别名(一般是类名)-->
            <servlet-name>HelloServlet</servlet-name>
            <!--servlet-class标签是Servlet程序的全类名-->
            <servlet-class>com.servlet.HelloServlet</servlet-class>
        </servlet>
        <!--servlet-mapping标签给Servlet程序配置访问地址-->
        <servlet-mapping>
            <!--servlet-name标签告诉服务器当前配置的地址给哪个Servlet程序用-->
            <servlet-name>HelloServlet</servlet-name>
            <!--url-pattern标签配置访问地址-->
            <!--/斜杠 在服务器解析的时候,表示地址为:http://ip:port/工程路径
                /hello表示地址为:http://ip:port/工程路径/hello-->
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.Servlet程序常见错误
    (1).url-pattern中配置的路径没有以斜杠打头.
    (2).servlet-name配置的值不存在.
    (3).servlet-class标签的全类名配置错误.

    4.url地址到Servlet程序的访问

    在这里插入图片描述

    5.Servlet的生命周期
    (1).执行Servlet构造器方法.
    (2).执行init初始化方法.
    (3).执行service方法.
    (4).执行destroy销毁方法.

    注意:

    • 第一、二步,是在第一次访问的时候创建Servlet程序会调用.
    • 第三步,每次访问都会调用.
    • 第四步,在web工程停止的时候调用.

    6.GET和POST请求的分发处理

    在这里插入图片描述

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("Hello Servlet");
            //类型转换(因为HttpServletRequest中有getMethod()方法)
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            //获取请求的方式
            String method = httpServletRequest.getMethod();
            if ("GET".equals(method)) {
                doGet();
            } else if ("POST".equals(method)) {
                doPost();
            }
        }
            public void doGet(){
                System.out.println("get请求");
            }
            public void doPost(){
                System.out.println("post请求");
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="http://localhost:8080/06_servlet/hello" method="GET">
            <input type="submit">
        </form>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7.通过继承HttpServlet实现Servlet程序
    这种方式在开发中比较常用

    (1).编写一个类去实现HttpServlet类.
    (2).根据业务需要重写doGet或doPost方法.

    public class HelloServlet2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          System.out.println("HelloServlet2 get");
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("HelloServlet2 post");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (3).到web.xml中配置Servlet程序的访问地址.

     <servlet>
            <servlet-name>HelloServlet2</servlet-name>
            <servlet-class>com.servlet.HelloServlet2</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>HelloServlet2</servlet-name>
            <url-pattern>/hello2</url-pattern>
        </servlet-mapping>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    8.IDEA菜单生成Servlet程序

    在这里插入图片描述

    在这里插入图片描述

    9.整个Servlet类的继承体系

    在这里插入图片描述

    二.ServletConfig

    • 是Servlet程序的配置信息类.
      Servlet程序和ServletConfig对象,都是由Tomcat负责创建,我们负责使用.
      Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象(一个ServletConfig仅对应一个Servlet程序)

    • ServletConfig类的三大作用
      (1).获取对应Servlet程序的别名servlet-name的值.
      (2).获取对应Servlet程序的初始化参数init-param.
      (3).获取ServletContext对象.

    public void init(ServletConfig servletConfig) throws ServletException {
    
            System.out.println("HelloServlet程序的别名是:" + servletConfig.getServletName());
            System.out.println("初始化参数username的值是:" + servletConfig.getInitParameter("username"));
            System.out.println("初始化参数url的值是:" + servletConfig.getInitParameter("url"));
            System.out.println(servletConfig.getServletContext());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
      <!--init-param是初始化参数-->
            <init-param>
                <!--param-name是参数名-->
                <param-name>username</param-name>
                <!--param-value是参数值-->
                <param-value>root</param-value>
            </init-param>
    
            <init-param>
                <param-name>url</param-name>
                <param-value>jdbc:mysql://localhost:3306/test</param-value>
            </init-param>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:我们重写init()方法时,需要先写一条调用父类init()方法的语句.

     public void init(ServletConfig config) throws ServletException {
            super.init(config);
            System.out.println("11111");
        }
    
    • 1
    • 2
    • 3
    • 4

    三.ServletContext

    1.ServletContext的概念
    (1).是一个接口,它表示Servlet上下文对象.
    (2).是一个web工程,只有一个ServletContext对象实例.
    (3).是一个域对象.
    (4).是在web工程部署启动的时候创建,在web工程停止的时候销毁.
    域对象:是可以像Map一样存取数据的对象,这里的指的是存取数据的操做范围.
    存数据: setAttribute() 取数据: getAttribute() 删除数据: removeAttribute()

    2.ServletContext类的四个作用
    (1).获取web.xml中配置的上下文参数context-param.
    (2).获取当前的工程路径,格式:/工程路径.
    (3).获取工程部署后在服务器硬盘上的绝对路径.

    package com.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 ContextServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ServletContext context = getServletConfig().getServletContext();
            String username = context.getInitParameter("username");
            System.out.println("username的值" + username);
            System.out.println("password的值" + context.getInitParameter("password"));
            System.out.println("当前工程路径:" + context.getContextPath());
            System.out.println("工程部署的路径:" + context.getRealPath("/"));//映射到IDEA的web目录
            System.out.println("工程部署的路径:" + context.getRealPath("/images"));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    (4).像Map一样存取数据.

    package com.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 ContextServlet1 extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ServletContext context = getServletContext();
            System.out.println("保存前" + context.getAttribute("k1"));
            context.setAttribute("k1","v1");
            System.out.println("Context1中获取k1的值是:" + context.getAttribute("k1"));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    四.HTTP协议

    1.HTTP协议:客户端和服务器之间通信时发送的数据(又叫报文),需要遵守的规则.

    2.请求的HTTP协议格式

    客户端给服务器发送数据叫请求.
    服务器给客户端回传数据叫响应.
    请求分为GET请求和POST请求两种.

    • GET请求
    • 请求行
      (1).请求的方式:GET
      (2).请求的资源路径[+?+请求参数]
      (3).请求的协议的版本号:HTTP/1.1.
    • 请求头:key : value 组成,不同的键值对,表示的含义不同.
      在这里插入图片描述
    • POST请求
    • 请求行
      (1).请求的方式:POST.
      (2).请求的资源路径[+?+请求参数].
      (3).请求的协议的版本号:HTTP/1.1.
    • 请求头:key:value 不同的请求头,有不同的含义.
    • 空行
    • 请求体: 发送给服务器的数据.
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="http://localhost:8080/06_servlet/hello2" method="post">
            <inout type="hidden" name="action" value="login" />
            <inout type="hidden" name="username" value="root" />
            <input type="submit">
        </form>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    • 常用请求头的说明
      Accept:表示客户端可以接收的数据类型.
      Accept-Languege:表示客户端可以接收的语言类型.
      user-Agent:表示客户端浏览器的信息.
      Host:表示请求时的服务器ip和端口号.

    • GET请求与POST请求的划分
      GET请求有:
      (1).form标签 method=get
      (2).a标签
      (3).link标签引入css
      (4).Script标签引入js文件
      (5).img标签引入图片
      (6).iframe引入html页面
      (7).在浏览器地址栏中引入地址后敲回车

    • POST请求有:form标签 method=get

    3.响应的HTTP协议格式

    • 响应行
      (1).响应的协议和版本号: HTTP/1.1
      (2).响应状态码
      (3).响应状态描述符
    • 响应头:key:value 不同的响应头,有其不同的含义
    • 空行
    • 响应体 回传给客户的程序
      在这里插入图片描述
      4.常用响应码说明
      200 表示请求成功
      302 表示请求重定向
      404 表示服务器已经收到请求,但是需要的数据不存在或者请求地址错误
      500 表示服务器已经收到请求,但是服务器内部错误(代码错误)

    5.MIME类型说明
    (1).概念:MIME(多功能Internet邮件扩充服务)是HTTP协议中的数据类型
    (2).格式:大类型/小类型,并与某一种文件的扩展名相对应.
    在这里插入图片描述
    在浏览器查看HTTP协议:启动部署项目后,发出请求,然后按F12在网络部分就能看到了.

    五.HttpServletRequest类

    1.HttpServletRequest类的作用:
    每次只要进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中.然后传递到service方法(doGet和doPost)中给我们使用,我们可以通过HttpServletRequest对象,获取到所有请求的信息.

    2.HttpServletRequest类的常用方法
    (1).getRequestURI(); 获取请求的资源路径
    (2).getRequestURL(); 获取请求的统一资源定位符(绝对路径)
    (3).getRemoteHost(); 获取客户端的ip地址
    (4).getHeader(); 获取请求头
    (5).getMethod(); 获取请求的方式(GET/POST)
    (6).getParameter(); 获取请求的参数
    (7).getParameterValues(); 获取请求的参数(多个值时使用)
    (8).setAttribute(key,value); 设置域数据
    (9).getAttribute(key); 获取域数据
    (10).getRequestDispatcher(); 获取请求转发对象

    package com.servlet;
    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 RequestAPIServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //getRequestURI()
            System.out.println("URI: " + req.getRequestURI());
            //getRequestURL()
            System.out.println("URL: " + req.getRequestURL());
            //getRemoteHost()
            System.out.println("客户端ip地址: " + req.getRemoteHost());
            //getHeader()
            System.out.println("请求头: " + req.getHeader("User-Agent"));
            //getMethod()
            System.out.println("请求方式: " + req.getMethod());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.获取请求参数

      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String[] hobby = req.getParameterValues("hobby");
            System.out.println("用户名: " + username);
            System.out.println("密码: " + password);
            System.out.println("兴趣爱好: " + Arrays.asList(hobby));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    <form action="http://localhost:8080/07_servlet/parameterServlet" method="get">
        用户名:<input type="text" name="username"></br>
        密码: <input type="password" name="password"></br>
        兴趣爱好: <input type="checkbox" name="hobby" value="java">java
        <input type="checkbox" name="hobby" value="js">javaScript</br>
        <input type="submit">
    </form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:对于Post请求存在中文乱码问题,通过设置请求体字符集编码为UTF-8来解决,而且必须在获取请求参数之前才有效.

     //设置请求体的字符集为UTF-8,从而解决Post请求的中文乱码问题
            req.setCharacterEncoding("UTF-8");
    
    • 1
    • 2

    4.请求转发

    在这里插入图片描述

     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取请求的参数(办事的材料)查看
            String username = req.getParameter("username");
            System.out.println("在Servlet1中查看参数: " + username);
            //给材料盖章,并传到Servlet2去查看
            req.setAttribute("key","Servlet1的章");
            //问Servlet2怎么走
            //请求转发必须要以斜杠打头, / 表示地址为:http://ip:port/工程名/,映射到IDEA代码的web目录
            RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
            //去Servlet2
            requestDispatcher.forward(req,resp);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取请求的参数(办事的材料)查看
            String username = req.getParameter("username");
            System.out.println("在Servlet2中查看参数: " + username);
            //查看是否有Servlet1的盖章
            Object key = req.getAttribute("key");
            System.out.println("Servlet1是否有盖章: " + key);
            //处理自己的业务
            System.out.println("Servlet2处理自己的业务");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意:不可以访问工程以外的资源

    5.base标签的作用

    在这里插入图片描述

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    web下的index.html<br/>
    <a href="a/b/c.html">a/b/c.html</a><br/>
    <a href="http://localhost:8080/07_servlet/fowarC">请求转发:a/b/c.html</a>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class FowarC extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("经过了Fowrd");
            req.getRequestDispatcher("/a/b/c.html").forward(req,resp);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!--base标签设置当前页面相对路径工作时的参照地址
        c.html可以省略-->
        <base href="http://localhost:8080/07_servlet/a/b/c.html">
    </head>
    <body>
    这是a/b/c.html页面</br>
    <a href="../../index.html">跳回首页</a>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    6.Web中的相对路径和绝对路径
    在JavaWeb中路径分为相对路径和绝对路径:
    相对路径:
    . 表示当前目录
    .. 表示上一级目录
    资源名 表示当前目录/资源
    绝对路径: http://ip:port/工程路径/资源路径

    7.Web中 / 斜杠的不同意义
    在Web中 / 斜杠 是一中绝对路径.
    如果被浏览器解析,得到的地址是:http://ip:port/

    例如:

    如果被服务器解析,得到的地址是:http://ip:port/工程路径
    例如:
    在这里插入图片描述

    六.HttpServletResponse类

    1.HttpServletResponse类的作用:

    • 和HttpServletRequest类一样,每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用.
    • HttpServletRequest表示请求过来的信息
    • HttpServletResponse表示所有响应的信息
    • 如果需要设置返回给客户端的信息,可以通过HttpServletResponse对象来进行设置

    2.两个输出流的说明

    • 字节流 getOutputStream() 常用于下载(传递二进制数据)
    • 字符流 getWriter() 常用于回传字符串(常用)
      注意:两个输出流只能同时使用一个

    3.往客户端回传数据

     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            PrintWriter writer = resp.getWriter();
            writer.write("wyl");
        }
    
    • 1
    • 2
    • 3
    • 4

    4.响应的乱码的解决
    第一种方式:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //此方法一定要在获取流对象之前调用才有效
            //设置服务器字符集为UTF-8
            resp.setCharacterEncoding("UTF-8");
            //通过响应头,设置浏览器也使用UTF-8字符集
            resp.setHeader("Content-Type","text/html;UTF-8");
            PrintWriter writer = resp.getWriter();
            writer.write("王");
        }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第二种方式:

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //此方法一定要在获取流对象之前调用才有效
            //同时设置服务器和浏览器字符集为UTF-8
            resp.setContentType("text/html;charset=UTF-8");
            PrintWriter writer = resp.getWriter();
            writer.write("王");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5.请求重定向

    概念:是指客户端给服务器发请求,然后服务器告诉客户端一个新地址,要求客户端去新地址访问(之前的地址可能被废弃)

    在这里插入图片描述

     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           System.out.println("曾到此一游");
           req.setAttribute("key","value");
           //设置响应状态码302,表示重定向,(已搬迁)
            resp.setStatus(302);
            //设置响应头,说明新的地址在哪
            resp.setHeader("Location","http://localhost:8080/07_servlet/response2");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Object key = req.getAttribute("key");
            System.out.println(key);
            resp.getWriter().write("result");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    请求重定向的第二种方案:

       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           System.out.println("曾到此一游");
           req.setAttribute("key","value");
            resp.sendRedirect("http://localhost:8080/07_servlet/response2");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    34.Python从入门到精通—Python3 正则表达式检索和替换
    贪心算法(算法竞赛、蓝桥杯)--糖果传递
    【AI视野·今日NLP 自然语言处理论文速览 第三十六期】Tue, 19 Sep 2023
    python LeetCode 刷题记录 58
    C++算法之旅、09 力扣篇 | 常见面试笔试题(上)算法小白专用
    竞赛选题 机器视觉目标检测 - opencv 深度学习
    Linux操作系统裸机开发-环境搭建
    如何实现IT基础设施的全面监控和智能运维?
    中科院自动化所:基于关系图深度强化学习的机器人多目标包围问题新算法
    Day19 | 每天五道题
  • 原文地址:https://blog.csdn.net/qq_53798578/article/details/127636635