关于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.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")
 *
 *
 */

@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请求
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        /*
        通常情况下,浏览器或者客户端发送数据的请求方式就一种方式,对应GET请求和POST请求,
        来实现Servlet代码是,针对GET和POST完成对应的方法,这里会实现一个方法,通过另一个方法来实现所有的业务逻辑
         */
        System.out.println("POST请求方式");
        super.doPost(req, resp);
    }
}

对应的HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="ServletDemo1" method="get">
    <input type="submit" value="GET请求"><br>
</form>
<form action="ServletDemo1" method="post">

    <input type="submit" value="POST请求"><br>

</form>

</body>
</html>

 

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接口

 

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抽象类

 

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

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生命周期四个方法

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程序的管理是自动完成的,不需要人为干预

 


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之后允许使用注解方式配置

属性名概述
nameServlet名字,可以自定义
valueurl资源匹配方式,和urlPatterns互斥
urlPatterns允许当前Servlet有多个匹配方式,和value互斥
loadOnStartup是否启动服务时加载当前Servlet,默认 -1,选择加载 1
initParamsWebInitParam 注解类型 name和value 当前Servlet配置初始化配置

 

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>

 

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 注解方式

 

 

2.5.2 web.xml

 

 

 

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>

 

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

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值