java基础

java基础-day39-Servlet

2021-07-02  本文已影响0人  触手不可及

Servlet基础

1. Servlet概述

1.1 什么是Servlet
    Servlet ==> Server Applet
    Servlet是JavaWEB服务端的一个小程序,主要用户数据的交互,WEB数据展示和数据传递,这里Servlet是一个动态资源。
    Servlet程序可以应对所有类型的请求和响应,Servlet主要还是用于HTTP协议的WEB服务器程序实现。
    
Servlet开发需要使用到两个包
    javax.servlet
    javax.servlet.http
以下内容是我们开发中会涉猎到的主要接口和类
    javax.servlet.Servlet -- interface
    javax.servlet.GenericServlet -- abstract修饰的类
    javax.servlet.http.HttpServlet;
    javax.servlet.http.HttpServletRequest; -- 请求
    javax.servlet.http.HttpServletResponse; -- 响应
    javax.servlet.http.HttpSession; -- Session
    javax.servlet.http.Cookie; -- Cookie
                            Session 和 Cookie会话控制技术使用的内容
1.2第一个Servlet程序
package com.qfedu.a_servlet;

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

/**
 * 1. 继承HttpServlet
 * 2. 重写doGet和doPost方法
 * 3. 这里使用注解方式告知Tomcat服务器当前Servlet对应的URL名字是什么
 *      @WebServlet("/ServletDemo1")
 *
 * @author MI 2020/3/30 9:53
 */
@WebServlet("/ServletDemo1")
public class ServletDemo1 extends HttpServlet {
    /**
     * 处理GET请求
     *
     * @param req  HttpServletRequest对象,对应当前浏览器请求数据内容对应的对象。
     * @param resp HttpServletResponse对象,对应是当前服务器对于浏览器请求的响应
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().append("Hello Servlet");
    }

    /**
     * 处理POST请求
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*
        通常情况下,浏览器或者客户端发送数据的请求方式就一种方式,对应GET请求和POST请求,在实现
        Servlet代码时,针对GET和POST完成对应的方法,这里会实现一个方法,通过另一个方法来实现所
        有的业务逻辑
         */
        System.out.println("POST请求方式");
        doGet(req, resp);
    }
}
1.3 关于404的那点事情
细心!!!

如果出现了404,需要注意的地方
    1. 资源名称是否正确,可以在IDEA中进行搜索,或者IDEA 侧边栏 WEB工具中查看所有的资源名
    2. 路径是否正确,确认当前资源路径是否和IDAE Tomcat配置一致
    3. 真的是资源不存在,不管是HTML,JSP,Servlet

2. Servlet使用

2.1 Servlet核心类和接口
2.1.1 interface javax.servlet.Servlet【核心接口】
Defines methods that all servlets must implement.
    当前接口中所有的Servlet程序必须实现
A servlet is a small Java program that runs within a Web server
    Servlet是一个小的Java程序,需要运行在WEB服务器当中。
    
Servlet接口中定义了5个方法
    public void init(ServletConfig config) throws ServletException;
        初始化当前Servlet程序,这里需要的参数是ServletConfig,ServletConfig
        是当前Servlet的配置,该配置可以从注解方式或者从当前项目中的web.xml加载
        获取
        
    public ServletConfig getServletConfig();
        获取ServletConfig对象,当前对象中保护Servlet配置内容。
        
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
        【核心方法】Servlet提供服务的方法,浏览器访问当前Servlet程序,service
        方法是起作用,ServletRequest对应的是请求,ServletResponse对应的是响
        应
    
    public String getServletInfo();
        获取当时Servlet程序信息对应字符串
        
    public void destroy();
        销毁当前Servlet程序,可以由Tomcat服务器执行,也可也通过servlet程序自己
        调用
2.1.2 abstract javax.servlet.GenericServlet【Servlet中间商】
    功能是完成了Servlet接口和ServletConfig接口的一部分方法,简化了之后代码的逻辑,主要需要了解的方法:
    public String getInitParameter(String name);
        根据初始化参数名字获取对应的值,而且参数值为String
    public Enumeration<String> getInitParameterNames();
        获取所有参数的名字。枚举类型的List
    public ServletConfig getServletConfig();
        获取ServletConfig对象
    public ServletContext getServletContext();
        获取ServletContext对象,一个Servlet Application有且只有一个
        ServletContext对应,这是Servlet上下文对象
    这里同时实现了Servlet接口中的 init 初始化方法
2.1.3 abstract javax.servlet.http.HttpServlet 【Servlet程序基类】
    abstract javax.servlet.http.HttpServlet 这是一个Java中符合Http协议的Servlet程序,继承GenericServlet,同时是Servlet接口和ServletConfig间接实现类。
    HttpServlet中首先实现service核心方法,并且将service核心方法的请求方式,响应方式强转为符合Http协议的请求和响应
    所有和Servlet业务逻辑无关的初始化方法,设置方法,销毁方法,HttpServlet中全部不需要考虑,只考虑符合Http协议请求方式和响应方式。

核心方法:
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
     符合HTTP GET请求的处理方式
     
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
     符合HTTP POST请求的处理方式

【注意】
    以上方法不重写,或者执行还是对应的方法,例如super.doGet(req,resp), 响应方式会提示报错 SC_METHOD_NOT_ALLOWED
2.2三种自定义Servlet程序方法
2.2.1 实现Servlet接口
package com.qfedu.b_threeFunction;

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

/**
 * 遵从Servlet接口实现Servlet程序
 * 代码中存在太多和业务逻辑无关的代码,增加了程序员的压力!!!
 * 不可取!!!
 *
 * @author MI 2020/3/30 11:23
 */
@WebServlet("/ServletImpl")
public class ServletImpl implements Servlet {

    /**
     * 构造方法
     */
    public ServletImpl() {
        System.out.println("ServletImpl Constructor called");
    }

    /**
     * 初始化方法
     *
     * @param config 需要使用ServletConfig类对象,也就是Servlet配置来完成初始化操作
     * @throws ServletException Servlet异常
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init method called");
    }

    /**
     * 获取ServletConfig对象
     *
     * @return 获取ServletConfig对象
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务核心方法
     *
     * @param req ServletRequest对象
     * @param res ServletResponse对象
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service method called");
    }

    /**
     * 获取Servlet信息
     * @return
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁Servlet
     */
    @Override
    public void destroy() {
        System.out.println("destroy method called");
    }
}

2.2.1 继承GenericServlet抽象类
package com.qfedu.b_threeFunction;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

/**
 * 继承GenericServlet 抽象类实现Servlet程序
 * 对应Servlet接口,在继承GenericServlet情况下,我们需要完成的方法有且
 * 只有service核心方法。
 *
 * 代码量明显减少,同时和业务逻辑无关的代码不需要考虑,但是没有针对性,
 * 没有对应Http协议请求方式的对应处理方法
 * 
 * @author MI 2020/3/30 11:30
 */
@WebServlet("/GenericServletExtends")
public class GenericServletExtends extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("GenericServletExtends service method called");
    }
}

2.2.1 继承HttpServlet抽象类
【注意】
    继承HttpServlet重写HttpServlet对应HTTP协议的处理方法,一定要完成,如果未完成或者说依然执行调用的是HttpServlet中的方法,
    会有错误出现 405 Method Not Allow
package com.qfedu.b_threeFunction;

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

/**
 * 继承HttpServlet实现符合HTTP协议的Servlet程序
 * 并且可以自定义实现请求方式的对应处理方法
 *
 * @author MI 2020/3/30 11:34
 */
@WebServlet("/HttpServletExtends")
public class HttpServletExtends extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HttpServletExtends doGet or doPost method called");
        resp.getWriter().append("Hello Servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
2.3 Servlet生命周期
2.3.1 什么是生命周期
人类
    胚胎 --> 婴儿 --> 儿童 --> 少年 --> 壮年 --> 中年 --> 老年 --> 死亡
    
Tomcat管理Servlet程序的生命周期,主要涉及到4个方法
    Constructor构造方法
    init初始化方法
    service方法
    destroy销毁方法
2.3.2 Servlet生命周期概述
阶段一:
    Constructor方法执行,实例化过程。Tomcat中Servlet容器调用Servlet程序对应的构造方法,创建Servlet类对象,有前提条件
    1. 当前Servlet程序需要被执行!!!
    2. 当前Servlet程序配置了开机启动!!!Tomcat启动,当前Servlet启动完成。
    而且Constructor有且只执行一次!!!
阶段二:
    init(ServletConfig config)初始化方法,当Servlet程序创建之后,一定要对当前Servlet程序进行初始化过程,需要使用ServletConfig对象完成初始化操作,ServletConfig对象中是从注解或者web.xml中获取对应的配置信息,完成初始化操作,而且有且只执行一次!!!
阶段三:
    service方法提供服务
    当前Servlet程序准备完毕,Servlet程序是在被请求时执行service方法,完成对应请求和响应的执行过程。
    到HttpServlet抽象类中对于service方法实现,并且按照HTTP请求方式完成划分工作。比如doGet doPost
阶段四:
    Tomcat服务器中Servlet容量对于Servlet进行销毁过程,有几种情况下会执行destroy方法
    1. Tomcat服务器关闭,Servlet容器会执行每一个Servlet程序的destroy方法
    2. 当前Servlet程序执行过程中,存在特定条件选择关闭
    3. 通常情况下Servlet容器对于Servlet程序的管理是自动完成的,不需要人为干预
package com.qfedu.c_life;

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

/**
 * 生命周期演示
 *
 * @author MI 2020/3/30 14:32
 */
@WebServlet("/ServletLife")
public class ServletLife implements Servlet {

    /**
     * 构造方法
     */
    public ServletLife() {
        System.out.println("ServletLife Constructor called");
    }

    /**
     * 初始化方法
     *
     * @param config 需要使用ServletConfig类对象,也就是Servlet配置来完成初始化操作
     * @throws ServletException Servlet异常
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init method called");
    }

    /**
     * 获取ServletConfig对象
     *
     * @return 获取ServletConfig对象
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务核心方法
     *
     * @param req ServletRequest对象
     * @param res ServletResponse对象
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service method called");
    }

    /**
     * 获取Servlet信息
     * @return Servlet字符串信息
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁Servlet
     */
    @Override
    public void destroy() {
        System.out.println("destroy method called");
    }
}
2.4 Servlet两种配置方式
2.4.1 Servlet3.0之后允许使用注解方式配置
属性名 概述
name Servlet名字,可以自定义
value url资源匹配方式,和urlPatterns互斥
urlPatterns 允许当前Servlet有多个匹配方式,和value互斥
loadOnStartup 是否启动服务时加载当前Servlet,默认 -1,选择加载 1
initParams WebInitParam 注解类型 name和value 当前Servlet配置初始化配置
package com.qfedu.d_config;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 注解方式来配置Servlet
 *
 * @author MI 2020/3/30 14:41
 */
@WebServlet(name = "AnnotationServlet",
        urlPatterns = {"/AnnotationServlet", "/as", "/saolei"},
        loadOnStartup = 1,
        initParams = {@WebInitParam(name = "aa", value = "骚磊无敌"), @WebInitParam(name = "bb", value = "46号技师")})
public class AnnotationServlet extends HttpServlet {
    public AnnotationServlet() {
        System.out.println("AnnotationServlet Constructor Called");
    }

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("Init Method Called");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Annotation Config Servlet");
        String aa = this.getServletConfig().getInitParameter("aa");
        String bb = this.getServletConfig().getInitParameter("bb");

        System.out.println(aa);
        System.out.println(bb);

        resp.getWriter().append("Annotation Config Servlet");
    }

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

    @Override
    public void destroy() {
        super.destroy();
        System.out.println("Destroy Method Called");
    }
}

2.4.2 任何一个版本都允许使用web.xml配置
<!-- 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_3_1.xsd"
         version="3.1">
    <!-- Servlet 程序声明,告知Servlet程序对应的名字和Servlet程序对应的class -->
    <servlet>

        <!-- ServletName -->
        <servlet-name>WebXmlServlet</servlet-name>

        <!-- Servlet对应的class,该名字必须是完整的包名.类名 -->
        <servlet-class>com.qfedu.d_config.WebXmlServlet</servlet-class>
        <!-- 当前Servlet程序初始化操作,需要放在servlet-class之后 -->
        <init-param>
            <param-name>saolei</param-name>
            <param-value>千锋最骚气的老师</param-value>
        </init-param>
        <init-param>
            <param-name>saojie</param-name>
            <param-value>我见过最恐怖的臭脚</param-value>
        </init-param>
        <!-- 当前Servlet随着Tomcat服务器启动加载 -->
        <load-on-startup>1</load-on-startup>

    </servlet>
    <!-- Servlet映射关系 -->
    <servlet-mapping>
        <!-- 告知Tomcat服务器,当前url-pattern映射的是哪一个Servlet -->
        <servlet-name>WebXmlServlet</servlet-name>
        <!-- URL匹配原则 -->
        <url-pattern>/WebXmlServlet</url-pattern>
    </servlet-mapping>
    <!-- Servlet映射关系 -->
    <servlet-mapping>
        <!-- 告知Tomcat服务器,当前url-pattern映射的是哪一个Servlet -->
        <servlet-name>WebXmlServlet</servlet-name>
        <!-- URL匹配原则 -->
        <url-pattern>/wxs</url-pattern>
    </servlet-mapping>
</web-app>
package com.qfedu.d_config;

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

/**
 * @author MI 2020/3/30 14:57
 */
public class WebXmlServlet extends HttpServlet {

    public WebXmlServlet() {
        System.out.println("WebXmlServlet Constructor Called");
    }

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("WebXmlServlet Init Method Called");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("WebXmlServlet Config Servlet");
        String aa = this.getServletConfig().getInitParameter("saolei");
        String bb = this.getServletConfig().getInitParameter("saojie");

        System.out.println(aa);
        System.out.println(bb);

        resp.getWriter().append("WebXmlServlet Config Servlet");
    }

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

    @Override
    public void destroy() {
        super.destroy();
        System.out.println("WebXmlServlet Destroy Method Called");
    }

}
2.4.3 两种方式对比
注解
    配置简单,直观,高效
    url-pattern 冲突问题,并且是在Tomcat启动时发现,需要注意细节
    
web.xml
    繁琐,麻烦,步骤繁多
    url-pattern 一旦写错或者冲突,web.xml文件会提示错误!!!
2.5 两种匹配方式Tomcat工作原理
2.5.1 注解方式
image.png
2.5.2 web.xml
image.png
2.6 Servlet获取请求数据
【注意】
    1. 要求前端提交数据的name属性和后台获取getParameter参数一致
    2. 在后台通过HttpServletRequest获取数据使用getParameter方法,返回值是String类型
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>02-ParameterUpload</title>
</head>
<body>
<form action="GetParameterServlet" method="get">
    <span>姓名:</span><input type="text" name="userName"> <br>
    <span>密码:</span><input type="password" name="password"> <br>
    <input type="submit" value="提交">
</form>
<hr>
<form action="GetParameterServlet" method="post">
    <span>姓名:</span><input type="text" name="userName"> <br>
    <span>密码:</span><input type="password" name="password"> <br>
    <input type="submit" value="提交">
</form>
</body>
</html>
package com.qfedu.e_parameter;

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

/**
 * 获取前端通过HTTP请求方式发送过来的数据
 *
 * @author MI 2020/3/30 16:02
 */
@WebServlet("/GetParameterServlet")
public class GetParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 浏览器通过form表单提交的数据都在HttpServletRequest对象中

        // 通过getParameter获取对应的参数名数据,参数名和form表单中的name属性一致
        String userName = req.getParameter("userName");
        String password = req.getParameter("password");

        System.out.println(userName + ":" + password);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("POST请求方式");
        doGet(req, resp);
    }
}
2.7 Servlet请求乱码问题
2.7.1 GET请求使用
    Tomcat7以及以下版本使用情况下,前端数据传输使用的HTTP协议,传递的方式是UTF-8编码,Tomcat服务器Request对象接收数据时,使用的编码是ISO-8859-1。
    数据接收方式和发送方式使用的编码集不一致,导致中文乱码
    Tomcat8以上GET请求中文乱码基本上不会出现
String userName = req.getParameter("userName");
// 这里需要转换对应你的编码集方式
userName = new String(userName.getBytes("ISO-8859-1"), "UTF-8");
String password = req.getParameter("password");
System.out.println(userName + ":" + password);
2.7.2 POST请求使用
    客户端发送数据的方式是通过该UTF-8传输,客户端需要设置同样的方式接受,需要设置HttpServletRequest.setCharacterEncoding("utf-8");统一设置编码。
2.8 Servlet响应乱码问题
    HttpServletResponse响应对象默认采用的编码集方式是根据当前系统编码集有关,这里使用的编码集是GB2312,浏览器默认解析方式是UTF-8
    解决方案:
        告知HttpServletResponse,当前响应编码集和方式为UTF-8
        response.setContentType("text/html;charset=utf-8");
2.9 针对乱码问题总结解决方案
    针对于Tomcat8及其以上版本的Tomcat服务器软件,需要在接受数据时和响应数据时设置对应的编码集
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    以上两行代码可以放在所有的Servlet程序之前
    
    Tomcat7及其以下版本,需要注意GET请求方式使用的编码集为ISO-8859-1
上一篇 下一篇

猜你喜欢

热点阅读