侧边栏壁纸
博主头像
Santa博主等级

不能平庸,也不甘堕落

  • 累计撰写 43 篇文章
  • 累计创建 29 个标签
  • 累计收到 28 条评论

JavaWeb之Servlet(一)

Santa
2022-01-19 / 0 评论 / 3 点赞 / 349 阅读 / 9,322 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-01-20,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Servlet技术

什么是servlet

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

手动实现Servlet程序

  1. 编写一个类去实现Servlet接口
  2. 实现service方法,处理请求,并响应接口
  3. 到web.xml中去配置servlet程序的访问地址

service方法相关代码:

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {
    /**
     * service是专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("我被访问了!");
    }
}

web.xmldee相关配置:

<?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.example.demo.HelloServlet</servlet-class>
    </servlet>
    <!-- servlet-mapping标签给Servlet程序配置访问地址 -->
    <servlet-mapping>
        <!-- 告诉服务器,我们当前配置的地址给哪个Servlet程序使用 -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- 配置访问地址
            “/” 表示在服务器解析时,表示的地址为:http://ip:port/工程路径
            “/hello” 表示地址为:http://ip:port/hello,可以随意改动
         -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

注意:

  1. 在配置<url-pattern>标签时不能漏掉“/”,否则运行报错非法地址

    Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> hello in servlet mapping
    
  2. servlet-name 配置的值不存在(没配置或者说两个servlet-name名不一致):

    Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name HelloServlets
    

    servletname.png

  3. servlet-class 标签的全类名配置错误:

    servletclass.png

url地址到Servlet的访问

servlet连接访问.png

Servlet的生命周期

相关代码:

package com.example.demo;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {
    public HelloServlet() {
        System.out.println("1.构造器");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("2.init初始化");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * service是专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("3.service 我被访问了!");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("4.destroy销毁");
    }
}
  1. 执行Servlet构造器方法

  2. 执行init初始化方法

    第一、二步,是在第一次访问,的时候创建 Servlet

    访问周期1.png

    访问周期2.png

  3. 执行 service 方法

    第三步,每次访问都会调用。

    访问周期3.png

  4. 执行 destroy 销毁方法

    第四步,在 web工程停止的时候调用。

    访问周期4.png

GET和POST请求分发处理

src->main->webapp下创建html文件,并简单写下getpost请求方式:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/demo/hello" method="post">
        <input type="submit" value="OK">
    </form>
</body>
</html>

运行代码:

public class HelloServlet implements Servlet {
    /**
     * service是专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        // 类型转换(因为它有 getMethod()方法)
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        // 获取请求的方式
        String method = httpServletRequest.getMethod();
        if ("get".equalsIgnoreCase(method)){
            doGet();
        }else if ("post".equalsIgnoreCase(method)){
            doPost();
        }
    }
    //请求get
    public void doGet(){
        System.out.println("GET");
    }
    //请求post
    public void doPost(){
        System.out.println("POST");
    }

通过继承 HttpServlet 实现 Servlet 程序

一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。

  1. 编写一个类去继承HTTPServlet类
  2. 根据业务需要重写doGet或者doPost方法
  3. 到web.xml文件中的配置servlet程序的访问地址

代码展示:

同样创建一个home2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/demo/hello2" method="get">
        <input type="submit" value="OK">
    </form>
</body>
</html>

继承HttpServlet:

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 HelloServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet的get请求");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost的post请求");
    }
}

IDEA自动生成HttpServlet:

idea自动生成HttpServlet.png

idea自动生成HttpServlet2.png

Servlet 类的继承体系

Servlet继承体系.png

Servletconfig类

  • servlet程序的配置信息类
  • Servlet程序和ServletConfig对象都是由TomCat负责创建,我们负责使用
  • Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象(比如你创建了两个java文件,名字分别为h2h1,我们只在web.xml中配置servlet-name:h1的ServletConfig信息,运行h1的程序初始化我们可以得到值,但是当我们运行h2的程序时得到的值为null)

作用

  1. 可以获取servlet程序的别名servlet-name的值
  2. 获取初始化参数init-param
  3. 获取ServletContext对象

web.xml相关配置:

<servlet>
    ......
    <init-param>
        <!-- 参数名 -->
        <param-name>root</param-name>
        <!-- 参数值 -->
        <param-value>123456</param-value>
    </init-param>
    <init-param>
        <!-- 参数名 -->
        <param-name>username</param-name>
        <!-- 参数值 -->
        <param-value>ll123456</param-value>
    </init-param>
</servlet>

Servlet代码:

public class HelloServlet implements Servlet {
    ......
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //获取servlet-name别名
        System.out.println("HelloServlet的别名servlet-name是" + servletConfig.getServletName());
        //获取初始化init-param参数
        System.out.println("root的值是:" + servletConfig.getInitParameter("root") );
        System.out.println("username的值是:" + servletConfig.getInitParameter("username") );
        //获取ServletContext对象
        System.out.println("ServletContext对象" + 			   		servletConfig.getServletContext());
        ......
    }
}

**注意:**重写init()方法必须加上super.init(config);,否则会出现空指针异常

init1.png

ServletContext类

什么是域对象?

域对象,是可以像Map一样存取数据的对象,叫域对象。这里的域是指存取数据的操作范围

存数据取数据删除数据
Mapput()get()remove()
域对象setAttribute()getAttribute()removeAttribute()

ServletContext的四个作用

  1. 获取 web.xml 中配置的上下文参数 context-para
  2. 获取当前的工程路径,格式: /工程路径
  3. 获取工程部署后在服务器硬盘上的绝对路径
  4. 像 Map 一样存取数据

代码实例:

public class ContextServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext servletContext = getServletConfig().getServletContext();
        //获取 web.xml 中配置的上下文参数 context-para
        System.out.println("username的值为:" + servletContext.getInitParameter("username"));
        System.out.println("username2的值为:" + servletContext.getInitParameter("username2"));
        System.out.println("username3的值为:" + servletContext.getInitParameter("username3"));
        //获取当前的工程路径,格式: /工程路径
        System.out.println("获取当前工程路径:" + servletContext.getContextPath());
        //获取工程部署后在服务器硬盘上的绝对路径
        System.out.println("获取工程部署后在服务器硬盘上的绝对路径" + servletContext.getRealPath("/"));
        System.out.println("获取工程部署的css绝对路径" + servletContext.getRealPath("/css"));

    }
}

web.xml中的配置:

<!-- context-param是上下文参数(它属于整个web工程) -->
<context-param>
    <param-name>username</param-name>
    <param-value>context</param-value>
</context-param>
<context-param>
    <param-name>username2</param-name>
    <param-value>context2</param-value>
</context-param>

像Map一样存取数据:

代码实例:

public class ContextServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();
        //保存数据之前
        System.out.println("保存之前ContextServlet2中key的值:" + context.getAttribute("key"));
        //保存数据之后
        context.setAttribute("key","value");
        System.out.println("保存之后ContextServlet2中key的值:" + context.getAttribute("key"));
    }
}

总结:

  1. ServletContext是一个接口,它表示Servlet上下文对象

  2. 一个web工程,只有一个Servletcontext对象实例

  3. Servletcontext对象是一个域对象

  4. ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁(和静态变量存储相似之处)

    1. 在上面文件的基础上,我们重新创建一个ContextServlet3.java,只写ServletContext context = getServletContext(); System.out.println("保存之前ContextServlet3中key的值:" + context.getAttribute("key"));

      public class ContextServlet3 extends HttpServlet {
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
          }
      
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              ServletContext context = getServletContext();
              System.out.println("保存之前ContextServlet3中key的值:" + context.getAttribute("key"));
          }
      }
      
    2. 重新启动

      ServletContext1.png

    3. 先在网址中输入ContextServlet2中存取数据的地址http://localhost:8080/demo/context2,idea显示key值为value。

    4. 然后在网址中输入Contextservlet3的数据地址http://localhost:8080/demo/context3,会发现即使Contextservlet3.java没有存取数据也能的到key值为value

3

评论区