

简单来说:Servlet 是运行在 Web服务器(如Tomcat服务器)的,使用 Java编写的小应用程序。

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("Hello Servlet 被访问了");
	}
}<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>
        
        <servlet-name>HelloServletservlet-name>
        
        <servlet-class>com.servlet.HelloServletservlet-class>
    servlet>
    
    <servlet-mapping>
        
        <servlet-name>HelloServletservlet-name>
        
        <url-pattern>/hellourl-pattern>
    servlet-mapping>
web-app>

 Servlet 对象的生命周期:Servlet 创建对象–>初始化操作–> 运行操作–>销毁操作
 Web 服务器管理了 Servlet 的生命周期,Servlet 对象整个过程都是 Web 服务器来管理的。

生命周期方法  | 作用  | 运行次数  | 
|---|---|---|
构造方法  | 在对象实例化的时候执行必须有公共的无参数构造方法  | 1次  | 
void init(ServletConfig config)  | 在初始化的时候执行  | 1次  | 
void service(ServletRequest req, ServletResponse res)  | 每次请求都会执行  | n次  | 
void destroy()  | 在服务器正常关闭的时候  | 1次  | 

localhost:8080/one/hello
# 1. 浏览器发送请求,Tomcat接收到请求并通过结息请求地址来获取到要访问的项目路径和资源路径。
   项目路径:/one
   资源路径:/hello
# 2. Tomcat会扫描服务器内部的one项目下的所有Servlet,获取每一个Servlet的访问地址,并存储到一个集合中。资源路径作为ket,类的全限定名作为value。
   Map map = new HashMap<>();
   map.put("/one","com.servlet.HelloServlet");
# 3. 将资源路径/one作为key从map中获取value,得到了类的全限定名。
# 4. 他会预先创建一个Servlet实例缓存池(key是Servlet的全限定名,value是Servlet的实例对象),拿着找到的key,去servletmap中寻找,如果找得到说明不是第一次访问,如果找不到,说明是第一次访问。
   Map servletmap = new HashMap<>();
   if(servletmap.get(“全限定名”) == null){
		// 第一次访问,执行第5步
	} else{
		// 第N次,直接执行第7步
	}
# 5. 通过反射实例化这个Servlet对象,并放入实例缓存池中。
# 6. Tomcat创建ServletConfig对象,然后调用init方法,传入创建的Servlet对象
# 7. 创建HttpRequest和HttpResponse对象,并调用service方法,传入HttpRequest和HttpResponse对象。
# 8. 等待下一次访问。 

 默认实现了 Servlet 和 ServletConfig 这两个接口,它的子类是 HttpServlet,如果我们写的Servlet使用的是 Http 协议。
package cn.servlet;
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;
@WebServlet(urlPatterns = "/demo")
public class DemoServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("我是GenericServlet子类");
    }
}
package cn.httpservlet;
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;
@WebServlet(urlPatterns = "/demo02")
public class DemoServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("我是HttpServlet的子类");
    }
}1. 创建类继承 HttpServlet
2. 重写参数带着 Http 开头的 service 方法:在该方法中处理请求并响应数据。
	 注意事项:不要在该方法中调用父类的 service 方法(405) ServletConfig 类从类名上来看,就知道是 Servlet 程序的配置信息类。
 Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。  Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象。
ServletConfig接口常用方法  | 说明  | 
|---|---|
String getInitParameter(“参数名”)  | 通过指定的参数名得到参数  | 
 根据不同的编码格式响应数据给浏览器,编码格式作为Servlet的初始化配置参数,在Servlet的service方法中读取初始化配置参数并输出。
public class ServletConfigServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获得配置对象
        ServletConfig config = this.getServletConfig();
        // 获得初始化参数值
        String encoding = config.getInitParameter("encoding");
        if ("utf-8".equalsIgnoreCase(encoding)){
            // 模拟响应数据给浏览器
            System.out.println("执行utf-8编码操作");
        } else {
            // 模拟响应数据给浏览器
            System.out.println("执行gbk编码操作");
        }
    }
}<servlet>
	
    <servlet-name>ServletConfigServletservlet-name>
    
    <servlet-class>com.servletservlet-class>
	<init-param>
    	
        <param-name>encodingparam-name>
        
        <param-value>utf-8param-value>
    init-param>
servlet>
<servlet-mapping>
	
    <servlet-name>ServletConfigServletservlet-name>
    
    <url-patten>ServletConfigServleturl-patten>
servlet-mapping> ServletContext 是一个接口,它表示 Servlet 上下文对象,**一个 web 工程,只有一个 ServletContext 对象实例。**ServletContext 对象是一个域对象。ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。
 域对象,是可以像 Map 一样存取数据的对象,叫域对象。这里的域指的是存取数据的操作范围,整个 web 工程。
 他的作用是数据共享。
存数据  | 取数据  | 删除数据  | |
|---|---|---|---|
map  | put()  | get()  | remove()  | 
域对象  | setAttribute()  | getAttribute()  | removeAttribute()  | 
 让 web 容器启动的时候创建并初始化 Servlet。取值范围1到10,值越小越先加载。默认值是-1:代表第1次访问时创建和初始化
 他可以在xml中进行配置:
<load-on-startup>1load-on-startup> 他还可以利用注解配置的方法:
@WebServlet(urlPatterns = "/response", loadOnStartup =1) HttpServletRequest 是一个接口,该接口的实现类对象称为请求对象,请求对象封装了所有的请求信息(请求行,请求头,请求体(请求参数))。
 HttpServletRequest 接口包含了大量的方法。由 Tomcat 去实现这个对象,并且在 servlet 启动的时候调用service() 将请求对象传递进来了。我们在 service 方法中直接使用即可。
request 与请求行相关方法  | 功能描述  | 
|---|---|
String getMethod()  | 获得请求方式 GET 或 POST  | 
String getRequestURI()  | Uniform Resource Identifier统一资源标识符,代表一个资源名字  | 
StringBuffer getRequestURL()  | Uniform Resource Locator 统一资源定位符,代表一个可以访问地址  | 
String getProtocol()  | 获得协议和版本  | 
String getContextPath()  | 获得上下文路径(项目名path)  | 
request 与请求头相关方法  | 功能描述  | 
|---|---|
String getHeader(String headName)  | 得到指定的请求头的值 参数:键的名字 返回:相应请求头的值  | 
request与请求参数相关方法  | 功能描述  | 
|---|---|
String getParameter(String name)  | 通过参数名得到一项参数值  | 
String[] getParameterValues(String name)  | 根据参数名得到一组同名的值复选框,下拉列表多选  | 
Enumeration getParameterNames()  | 获得所有的参数名  | 
Map getParameterMap()  | 得到表单所有的参数键和值,封装成Map对象  | 
Enumeration接口中方法  | 说明  | 
|---|---|
boolean hasMoreElements()  | 如果还有其它元素,返回true  | 
E nextElement()  | 返回下一个元素  | 
package com.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;
@WebServlet("/line")
public class RequestLineServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获得请求行信息
        System.out.println("得到方法:" + request.getMethod());
        System.out.println("统一资源标识符:" + request.getRequestURI());
        System.out.println("统一资源定位符:" + request.getRequestURL());
        System.out.println("协议和版本:" + request.getProtocol());
        System.out.println("当前项目地址:" + request.getContextPath());
        // 得到一个请求头
        System.out.println("得到host的请求头值:" + request.getHeader("host"));
    }
} 在浏览器发送数据给服务器的时候,使用 utf-8 编码,但服务器解码默认使用 ISO-8859-1 解码:欧洲码,不支持汉字的。
 如果是 GET 请求且 Tomcat 版本大于8.0.5,则不需要考虑乱码问题,否则 GET 请求也需要考虑乱码问题。
 HttpServletResponse 是一个接口,该接口的实现类对象称为响应对象,用于响应数据(响应行,响应头,响应体)给浏览器。HttpServletResponse 接口包含了大量的方法。由 Tomcat 去实现这个对象,并且在 servlet 启动的时候调用 service() 将请求对象和响应对象传递进来了。我们在 service 方法中直接使用即可。
响应体相关的方法  | 功能描述  | 
|---|---|
OutputStream getOutputStream()  | 如果服务器端返回的是二进制数据则使用这个方法,比如图片  | 
PrintWriter getWriter()  | 如果服务器端返回的是字符的文本数据,使用这个方法  | 
@WebServlet(urlPatterns = "/response")
public class ResponseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获得字符打印流对象
        PrintWriter out = response.getWriter();
        // 响应数据给浏览器显示
        out.print("hello browser");
    }
} 因为 Tomcat 中响应体默认的是欧洲码表,ISO-8859-1 不支持中文。
 在获得打印流对象之前,通过下面方法设置打印流的编码为utf-8
response方法  | 说明  | 
|---|---|
response.setCharacterEncoding(“字符集”)  | 用于设置响应体的字符集 设置打印流使用的码表  | 
@WebServlet(urlPatterns = "/response")
public class ResponseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置打印流编码
        response.setCharacterEncoding("utf-8");
        // 获得字符打印流对象
        PrintWriter out = response.getWriter();
        // 响应数据给浏览器显示
        out.print("你好 browser");
    }
} 通过下面方法告诉浏览器返回数据类型和编码
响应对象的方法  | 功能描述  | 
|---|---|
void setContentType(String type)  | 1. 告诉浏览器返回内容类型2. 设置打印流编码注意: 必须在获取流之前设置,否则无效  | 
@WebServlet(urlPatterns = "/response")
public class ResponseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置打印流编码
        // response.setCharacterEncoding("utf-8");
        // 告诉浏览器返回内容类型并设置打印流编码
        response.setContentType("text/html;charset=utf-8");
        // 获得字符打印流对象
        PrintWriter out = response.getWriter();
        // 响应数据给浏览器显示
        out.print("你好 browser");
    }
} JSP——Java Server Page运行在服务器端的 Java 页面,以前学习的 HTML 运行在浏览器端。JSP 是运行在服务器上,最终还是解析成静态的HTML,运行在浏览器。我们在浏览器上看到的HTML页面,其实是 JSP 在服务器上运行的结果。
 JSP 的主要作用是代替 Servlet 程序回传 html 页面的数据。因为 Servlet 程序回传 html 页面数据是一件非常繁锁的事情。开发成本和维护成本都极高。

技术  | 特点  | 
|---|---|
HTML  | 静态页面 优点:方便页面美化操作,写JS脚本和CSS代码都比较方便。 缺点:不能写动态的内容。  | 
Servlet  | 运行在服务器上小 Java 程序 优点:制作动态内容 缺点:不方便写 HTML 以及 CSS 和 JS 代码  | 
JSP  | JSP = HTML + Servlet 特点:既有 HTML 的优点:方便美化和编写 JS 代码。 又有 Servlet 优点:可以在页面写 Java 代码,可以制作动态内容(不建议)。  | 
 **JSP页面本质上是一个 Servlet 程序。**当我们第一次访问 jsp 页面的时候。Tomcat 服务器会帮我们把 jsp 页面翻译成为一个 java 源文件。并且对它进行编译成为.class 字节码程序。我们打开 java 源文件不难发现其里面的内容是:

 我们跟踪原代码发现,HttpJspBase 类。它直接地继承了 HttpServlet 类。也就是说。jsp 翻译出来的 java 类,它间接了继承了 HttpServlet 类。也就是说,翻译出来的是一个 Servlet 程序。

 翻译出来的 Servlet 程序的源代码,不难发现。其底层实现,也是通过输出流。把 html 页面数据回传
给客户端。
    out.write("\r\n");
    out.write("\r\n");
    out.write("\r\n");
    out.write("\r\n");
    out.write("
    <title>Title</title>\r\n");
    out.write("\r\n");
    out.write("\r\n");
    out.write("
    a.jsp 页面\r\n");
    out.write("\r\n");
    out.write("\r\n"); JspServlet 首先会将 jsp 文件代码翻译成 Servlet 的 Java 代码,然后再编译成字节码文件执行,其底层就是一个 Servlet。

 浏览器第一次访问 JSP 的时候,由 Tomcat 将 JSP 翻译成了 Servlet,并且编译成字节码文件,只生成1次。如果这期间修改了JSP内容,就会重新翻译。
 用于 web 组件的跳转,从A 组件跳到另一个组件B。

 请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。在服务器端进行的组件(资源)的跳转。

request.getRequestDispatcher("/要跳转到的地址").forward(request, response);
 在浏览器端进行的页面(组件/资源)跳转。

response.sendRedirect("要跳转的地址")区别  | 转发 forward  | 重定向 redirect  | 
|---|---|---|
目录  | 可以访问WEB-INF目录下的资源  | 不可以访问WEB-INF目录下的资源  | 
地址栏  | 地址栏不会发生变化,还是上一个地址  | 会变化,显示新的地址  | 
跳转位置  | 在服务端进行跳转  | 在浏览器端跳转  | 
请求对象(域)  | 请求域数据不会丢失,因为是同一个请求  | 请求域数据会丢失,因为不是同一个请求  | 
 用于 Servlet 之间数据共享的服务器内存区域,作用域结构是一个Map。

作用域  | 类型  | 作用范围  | 
|---|---|---|
请求域  | HttpServletRequest  | 只在同一次请求中起作用  | 
会话域  | HttpSession  | 同一个会话中起作用浏览器第1次访问服务器直到浏览器关闭的整个过程称为1次会话  | 
上下文域  | ServletContext  | 同一个应用中起作用服务器启动直到服务器关闭的整个过程都起作用  | 
与作用域有关的方法  | 作用  | 
|---|---|
Object getAttribute(“键”)  | 从中得到一个值  | 
void setAttribute(“键”,Object数据)  | 向作用域中存储键值对数据  | 
void removeAttribute(“键”)  | 删除作用域中的键值对数据  | 
 先考虑作用范围小的作用域,如果小作用范围的作用域能满足需求就使用小作用范围的作用域。
 EL 表达式的全称是:Expression Language。是表达式语言。
 EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多。
算术运算符  | 说明  | 举例  | 结果  | 
|---|---|---|---|
+  | 加法  | ${12+18}  | 30  | 
-  | 减法  | ${18-8}  | 10  | 
*  | 乘法  | ${12*12}  | 144  | 
/(div)  | 除法  | 6 / 3 或 {6/3}或 6/3或{6 div 3}  | 2  | 
%(mod)  | 取模  | KaTeX parse error: Expected '}', got 'EOF' at end of input: {10%3} 或{10 mod 3}  | 1  | 
逻辑运算符  | 说明  | 举例  | 结果  | 
|---|---|---|---|
&& 或 and  | 与运算  | ${ 12 == 12 && 12 < 11 } 或 ${ 12 == 12 and 12 < 11 }  | false  | 
| 或 or  | 或运算  | ${ 12 = = 12 || 12<11}或 ${12= =12 or 12<11}  | true  | 
! 或 not  | 取反运算  | ${!true} 后 ${not true}  | false  | 
关系运算  | 说明  | 举例  | 结果  | 
|---|---|---|---|
== 或 eq  | 等于  | ${5 == 5} 或 ${5 eq 5}  | true  | 
!= 或 ne  | 不等于  | ${5 !=5} 或 ${5 ne 5}  | false  | 
< 或 lt  | 小于  | ${3 < 5} 或 ${3 lt 5}  | true  | 
> 或 gt  | 大于  | ${2 > 10} 或 ${2 gt 10}  | false  | 
<= 或 le  | 小于等于  | ${ 5 <= 12 } 或 ${ 5 le 12 }  | true  | 
>= 或 ge  | 大于等于  | ${ 3 >= 5 }或 ${ 3 ge 5 }  | false  | 
 表达式 1?表达式 2:表达式 3
 如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。

 判空:判断的是内容是否为空,不是对象是否为空。

 EL 获取数据的方式是从 4 个作用域对象中,从小到大的去获取,如果需要指定作用域获取数据,可使用以下 EL 的内置对象来指定。
 JSP 本质是 Servlet,但比 Servlet 多了一个作用域:页面域,在 JSP 中有四大作用域。页面域是只在一个JSP页面中起作用,不同的JSP之间不能实现数据的共享,比请求域范围还要小。
PageContext 操作有关的方法  | 说明  | 
|---|---|
void setAttribute(String key, Object value)  | 向页面域中添加键和值  | 
Object getAttribute(String key)  | 从页面域中得到值  | 
void removeAttribute(String key)  | 删除四个域中同名的键  | 
Object findAttribute(String key)  | 自动从四个作用域中去查某个键,从小到大的范围来查找,如果找到就停止。如果没有找到,返回null  | 
<%
	//向页面域中添加一个字符串    
	pageContext.setAttribute("name","我是页面域");
%>作用域  | EL的写法  | 
|---|---|
页面域  | ${pageScope.键名}  | 
请求域  | ${requestScope.键名}  | 
会话域  | ${sessionScope.键名}  | 
上下文域  | ${applicationScope.键名}  | 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    EL指定域获取数据
    <%
        // 向页面域中添加一个字符串
        pageContext.setAttribute("name", "页面域");
        // 请求域
        request.setAttribute("name", "请求域");
        // 会话域
        session.setAttribute("name", "会话域");
        // 上下文域
        application.setAttribute("name", "上下文域");
    %>
        
    从页面域获取:${pageScope.name}
    
    从请求域获取:${requestScope.name}
    
    从会话域获取:${sessionScope.name}
    
    从上下文域获取:${applicationScope.name}
    
    	自动查找作用域获取:${name} JSTL 标签库 全称是指 JSP Standard Tag Library JSP 标准标签库。是一个不断完善的开放源代码的 JSP 标签库。EL 表达式主要是为了替换 jsp 中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个 jsp 页面变得更佳简洁。JSTL 由五个不同功能的标签库组成。
功能范围  | URL  | 前缀  | 
|---|---|---|
核心标签库  | http://java.sun.com/jsp/jstl/core  | c  | 
格式化  | http://java.sun.com/jsp/jstl/fmt  | fmt  | 
函数  | http://java.sun.com/jsp/jstl/functions  | fn  | 
taglibs-standard-impl-1.2.1.jar
taglibs-standard-spec-1.2.1.jar<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 用于页面上单条件判断。
属性名  | 是否支持EL  | 属性类型  | 属 性 描 述  | 
|---|---|---|---|
test  | 支持,必须是 EL  | boolean值  | EL 中条件为真则执行标签体内容注意:没有对应 else 标签  | 
<%--
ii.
if 标签用来做 if 判断。
test 属性表示判断的条件(使用 EL 表达式输出)
--%>
如果a等于b
如果a不等于b 用于多分支判断(多条件判断),类似于跟 switch … case … default 。
标签名  | 作用  | 
|---|---|
choose  | 类似于 java 中swtich, choose只是一个容器,包含下面两个元素  | 
when  | 可以出现多个,用于每个判断条件,类似于 switch 中 case。有一个 test 属性,与 if 功能相同  | 
otherwise  | 如果上面所有的条件都不满足,执行 otherwise 内容。类似于 switch 中 default  | 
 用于遍历集合或数组(最为常用)。
属性名  | 是否支持EL  | 属性类型  | 属性描述  | 
|---|---|---|---|
items  | true  | 数组或集合  | 使用 EL 表达式,代表集合或数组  | 
var  | false  | String  | var 的变量名代表集合中的每一个元素  | 
varStatus  | false  | String  | 代表每个元素的状态对象,一共有4个属性,属性的含义见下表  | 
 varStatus属性表:
属性  | 数据类型  | 含义  | 
|---|---|---|
index  | int  | 当前遍历到的这个元素索引号,从 0 开始  | 
count  | int  | 遍历到当前为止,一共遍历了多少个元素,从1 开始  | 
first  | boolean  | 如果当前遍历的是第1个元素,则返回true  | 
last  | boolean  | 如果当前遍历的是最后1个元素,则返回true  | 
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>学生信息表</title>
    <style>
        tr {
            text-align: center;
        }
    </style>
</head>
<body>
<table align="center" border="1" cellspacing="0" cellpadding="0" width="80%">
    <caption>学生信息列表</caption>
    <tr>
        <th>序号</th>
        <th>学号</th>
        <th>姓名</th>
        <th>性别</th>
        <th>成绩</th>
    </tr>
    <%--
        forEach标签:用于JSP页面遍历集合和数组
            items属性:设置要遍历的集合或数组:一般从作用域中获取
            var属性:设置一个变量名:用来接收遍历到的每一个元素
            varStatus属性:设置一个变量名:记录当前遍历元素的状态(状态对象)
                index 属性:当前遍历元素的在集合中的索引值:从0开始
                count 属性:遍历到当前元素为止已经遍历了多少个元素,从 1 开始
    --%>
    <c:forEach items="${stus}" var="stu" varStatus="status">
        <!-- 给偶数行设置背景颜色 -->
        <tr style="background-color:${status.count % 2 == 0 ? 'gray;' : ''}">
            <td>${status.count}</td>
            <td>${stu.id}</td>
            <td>${stu.name}</td>
            <td>${stu.gender? "男":"女"}</td>
            <td>${stu.score}</td>
        </tr>
    </c:forEach>
</table>
</body>
</html> 用于对日期进行格式化。
属性名  | 属性类型  | 属 性 描 述  | 
|---|---|---|
test  | Date  | 要格式化的日期对象  | 
pattern  | String  | 指定日期格式  |