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.png2.5.2 web.xml
image.png2.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