后端开发基础——JavaWeb(根基,了解原理)浓缩

总述

学习Tomcat、JSON、Servlet、Filter、Session、Cookie、Ajax异步请求、RESTful接口规范、JSP(很老的技术,了解)

Servlet

系统架构

C/S架构(Client / Server(客户端 / 服务器))

B/S架构(Browser / Server,浏览器 / 服务器)

java

JavaSE:Java标准版

JavaEE:企业版(WEB方向,WEB系统)13种规范,其中Servlet就是JavaEE规范之一

JavaME:Java微型版

B/S结构的系统通信原理(没有涉及到Java小程序)

WEB系统

域名

IP地址(身份证号)

端口号(一个端口代表一个软件)

一个WEB系统的通信原理?通信步骤:

  • 第一步:用户输入网址(URL:统一资源定位符(http://www.baidu.com))

  • 第二步:域名解析器进行域名解析:http://110.242.68.3:80/index.html

  • 第三步:浏览器软件在网络中搜索110.242.68.3这一台主机,直到找到这台主机。

  • 第四步:定位110.242.68.3这台主机上的服务器软件,80端口

  • 第五步:80端口对应的服务器软件得知浏览器想要的资源名是:index.html

  • 第六步:服务器软件找到index.html文件,并且将index.html文件中的内容直接输出响应到浏览器上。

  • 第七步:浏览器接收到来自服务器的代码(HTML CSS JS)

  • 第八步:浏览器渲染,执行HTML CSS JS代码,展示效果

    请求request\响应response

关于WEB服务器软件

  • Tomcat(WEB服务器):java语言写的,需配置java环境:(JAVA_HOME=JDK的根

    CATALINA_HOME=Tomcat服务器的根

    PATH=%JAVA_HOME%\bin;%CATALINA_HOME%\bin)

  • jetty(WEB服务器)

  • JBOSS(应用服务器)

  • WebLogic(应用服务器)

  • WebSphere(应用服务器)

  • web服务器(Servlet + JSP两个规范)

  • 应用服务器(13个不同的规范)

tomcat服务器的目录

  • bin :命令文件,比如:启动Tomcat,关闭Tomcat等。(xxx.bat文件:bat文件是windows操作系统专用的、xxx.sh文件:sh文件是linux操作系统,使用shell语言)

  • conf: 配置文件(server.xml文件中可以配置端口号,默认Tomcat端口是8080)

  • lib :核心程序,因为Tomcat服务器是Java语言编写的,这里的jar包里面都是class文件。

  • logs: 日志,Tomcat服务器启动等信息都会在这个目录下生成日志文件。

  • temp:临时目录。存储临时文件。

  • webapps:存放大量的webapp(web application:web应用)

  • work:存放JSP文件翻译之后的java文件以及编译之后的class文件。

实现一个最基本的web应用(这个web应用中没有java小程序)

webapps(oa文件)

  • 第一步:找到CATALINA_HOME\webapps目录

    • 因为所有的webapp要放到webapps目录下。(没有为什么,这是Tomcat服务器的要求。如果不放到这里,Tomcat服务器找不到你的应用。)
  • 第二步:在CATALINA_HOME\webapps目录下新建一个子目录,起名:oa

    • 这个目录名oa就是你这个webapp的名字。
  • 第三步:在oa目录下新建资源文件,例如:index.html

    • 编写index.html文件的内容。
  • 第四步:启动Tomcat服务器

  • 第五步:打开浏览器,在浏览器地址栏上输入这样的URL:

  • http://127.0.0.1:8080/oa/index.html

  • 也可以超链接

动态的web应用

需要连接数据库->需要JDBC程序->需要编写Java程序连接数据库

后端到底要执行哪个java小程序,取决于前端浏览器发送的请求路径。一个路径对应一个Servlet

浏览器browser->网页服务器web server(Tomcat)->数据库服务器db server(mysql)->webapp(javaweb)

角色之间规范

webapp<JavaEE规范之一Servlet规范>webserver(JavaEE7-API-帮助文档(Servlet3.1).CHM)

brower<传输协议:HTTP协议(超文本传输协议)>webserver

webapp<JDBC规范>dbserver(jdk-17.0.1_doc-all.zip)

Servlet规范

代码->模拟Servlet本质(只是模拟)里面有文档

遵循Servlet规范的webapp,这个webapp就可以放在不同的WEB服务器中运行。(因为这个webapp是遵循Servlet规范的。)

包括:接口、类、配置文件、配置文件名字、配置文件内容、目录结构......

充当Tomcat服务器的开发者(Tomcat.java):已写好

对于javaweb程序员:两件事(编写一个类实现Servlet接口、将编写的类配置到配置文件中并指定请求路径和类名的关系):XXXServlet、web.properties。配置文件取名和路径是固定的(遵循的规范,这样Tomcat服务器和webapp才能解耦合)。

开发一个带有Servlet(Java小程序)的webapp(重点)

开发步骤:

第一步:在webapps目录下新建一个目录,起名crm(这个crm就是webapp的名字) 注意:crm就是这个webapp的根

第二步:在webapp的根下新建一个目录:WEB-INF(规定的名字)

第三步:在WEB-INF目录下新建一个目录:classes(规定的名字),存放字节码文件(java程序编译之后的class文件)。java源代码随便在哪儿,只要class文件放到classes目录下即可。

第四步:在WEB-INF目录下新建一个目录:lib(不必须,存放jar包)

第五步:在WEB-INF目录下新建一个文件:web.xml(必须,配置文件:请求路径和Servlet对照关系),可从其他webapp中拷贝

第六步:编写一个Java程序,必须实现Servlet接口。(Servlet属于JavaEE,接口时Oracle提供,而不是JDK(JavaSE))。Tomcat服务器中应该有这个接口,Tomcat服务器的CATALINA_HOME\lib目录下有一个servlet-api.jar,解压这个servlet-api.jar之后,你会看到里面有一个Servlet.class文件。 从JakartaEE9开始,Servlet接口的全名变了:jakarta.servlet.Servlet(java->jakarta->servlet->servlet.java),所以可以用迁移工具a migration tool。

第七步:编译,需要配置环境变量CLAASSPATH(CLASSPATH=.;地址)才能通过。配置的CLASSPATH和Tomcat服务器运行没有关系

第八步:(能和前端关联到一起)编译之后的HelloServlet.class文件拷贝到(tomcat-webapps-crm)WEB-INF\classes目录下。

第九步:(和前端关联)在web.xml文件中编写配置信息,让"请求路径"和"Servlet类名"关联在一起(专业术语:在web.xml文件中注册Servlet类)。

复制代码
   <?xml version="1.0" encoding="UTF-8"?>
   
   <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                         https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
     version="5.0"
     metadata-complete="true">
   
     <!--servlet描述信息-->
     <!--任何一个servlet都对应一个servlet-mapping -->
     <servlet>
         <servlet-name>wanna</servlet-name>
         <!--这个位置必须是带有包名的全限定类名-->
         <servlet-class>com.bjpowernode.servlet.HelloServlet</servlet-class>
     </servlet>
   
     <!--servlet映射信息-->
     <servlet-mapping>
         <!--这个也是随便的,不过这里写的内容要和上面的一样。-->
         <servlet-name>wanna</servlet-name>
         <!--这里需要一个路径-->
         <!--这个路径唯一的要求是必须以 / 开始-->
         <!--当前这个路径可以随便写-->
         <url-pattern>/wanna/wanna/wanna</url-pattern>
     </servlet-mapping>
     
   </web-app>

第十步:启动Tomcat服务器 第十一步:打开浏览器,在浏览器地址栏上输入一个url,这个URL必须是:

复制代码
 - http://127.0.0.1:8080/crm/wanna/wanna/wanna  

在Servlet中连接数据库

Servlet是Java程序,所以在Servlet中完全可以编写JDBC代码连接数据库u

在集成开发环境当中开发Servlet程序

IntelliJ IDEA、Eclipse(寓意是"日食")

使用IDEA集成开发工具开发Servlet

第一步:New Project(mpty Project【空工程】)

第二步:新建模块(File --> new --> Module...)

第三步:让Module变成JavaEE的模块(在搜索中搜Add Framework Support,选择Web Application )

第四步:编写Servlet(StudentServlet)导包- File --> Project Structrue --> Modules --> + 加号 --> Add JARS....

第五步:在Servlet当中的service方法中编写业务代码(连接数据库)

第六步:在WEB-INF目录下新建了一个子目录:lib。将连接数据库的驱动jar包放到lib目录下

第七步:在web.xml文件中完成StudentServlet类的注册

第八步:给一个html页面,在HTML页面中编写一个超链接

  • index.html

  • 这个文件不能放到WEB-INF目录里面,只能放到WEB-INF目录外面。

  • 添加相关地址

第九步:IDEA工具关联Tomcat服务器。关联的过程当中将webapp部署到Tomcat服务器当中

  • run->edit configuration->Tomcat Server --> local

  • deployment里面修改application context为项目名

第十步:启动Tomcat服务器

第十一步:打开浏览器,在浏览器地址栏上输入:http://localhost:8081/xmm/student.html

Servlet对象的生命周期

  1. Servlet对象是由谁来维护的?

    • Servlet对象的创建,对象上方法的调用,对象最终的销毁,Javaweb程序员是无权干预的。

    • Servlet对象的生命周期是由Tomcat服务器(WEB Server)全权负责的。

  2. 思考:我们自己new的Servlet对象受WEB容器的管理吗?

    • 我们自己new的Servlet对象是不受WEB容器管理的。
  3. 研究:服务器在启动的Servlet对象有没有被创建出来(默认情况下)?

    • :默认情况下,服务器在启动的时候Servlet对象并不会被实例化
  4. 怎么让服务器启动的时候创建Servlet对象呢?

    • 在servlet标签中添加<load-on-startup>子标签,在该子标签中填写整数,越小的整数优先级越高
  5. Servlet对象更像一个人的一生:

    • Servlet的无参数构造方法执行:标志着你出生了。

    • Servlet对象的init方法的执行:标志着你正在接受教育。

    • Servlet对象的service方法的执行:标志着你已经开始工作了,已经开始为人类提供服务了。

    • Servlet对象的destroy方法的执行:标志着临终。有什么遗言,抓紧的。要不然,来不及了。

  6. 关于Servlet类中方法的调用次数?

    • 构造方法只执行一次。

    • init方法只执行一次。

    • service方法:用户发送一次请求则执行一次,发送N次请求则执行N次。

    • destroy方法只执行一次。

GenericServlet适配器

  1. 适配器设计模式Adapter

    • 手机直接插到220V的电压上,手机直接就报废了。怎么办?可以找一个充电器。这个充电器就是一个适配器。手机连接适配器。适配器连接220V的电压。这样问题就解决了。
  2. 编写一个GenericServlet类,这个类是一个抽象类,其中有一个抽象方法service。

    • GenericServlet实现Servlet接口。

    • GenericServlet是一个适配器。

    • 以后编写的所有Servlet类继承GenericServlet,重写service方法即可。

  3. 在web.xml文件里配置

    复制代码
     <servlet>
             <servlet-name>userServlet</servlet-name>
             <servlet-class>com.bjpowernode.javaweb.servlet.UserServlet</servlet-class>
         </servlet>
         <servlet-mapping>
             <servlet-name>userServlet</servlet-name>
             <url-pattern>/user</url-pattern>
         </servlet-mapping>

ServletConfig

  1. ServletConfig是什么?

    1. jakarta.servlet.ServletConfig 显然ServletConfig是Servlet规范中的一员。 ServletConfig是一个接口。(jakarta.servlet.Servlet是一个接口。)
  2. 谁去实现了这个接口呢?

    1. Tomcat服务器实现了ServletConfig接口
  3. ServletConfig接口到底是干啥的?有什么用呢? Config是哪个单词的缩写?

    1. Configuration ServletConfig对象被翻译为:Servlet对象的配置信息对象。 一个Servlet对象就有一个配置信息对象。 两个Servlet对象就有两个配置信息对象。
  4. ServletConfig接口中有4个方法:

    1. 第1个方法: public String getInitParameter(String name);

    2. 第2个方法: public Enumeration getInitParameterNames();

    3. 第3个方法: public ServletContext getServletContext();

    4. 第4个方法: public String getServletName();

    5. 以上的4个方法,在自己编写的Servlet类当中也可以使用this去调用。(这个Servlet继承了GenericServlet)

ServletContext

  • 一个Servlet对象对应一个ServletConfig。100个Servlet对象则对应100个ServletConfig对象。

  • 只要在同一个webapp当中,只要在同一个应用当中,所有的Servlet对象都是共享同一个ServletContext对象的。

  • ServletContext怎么理解?context是什么意思?

    • Servlet对象的环境对象。(Servlet对象的上下文对象。)
  • ServletContext接口中有哪些常用的方法?

    复制代码
     public String getInitParameter(String name); // 通过初始化参数的name获取value
     public Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数的name
    复制代码
     <!--以上两个方法是ServletContext对象的方法,这个方法获取的是什么信息?是以下的配置信息-->
     <context-param>
         <param-name>pageSize</param-name>
         <param-value>10</param-value>
     </context-param>
     <context-param>
         <param-name>startIndex</param-name>
         <param-value>0</param-value>
     </context-param>
     <!--注意:以上的配置信息属于应用级的配置信息,一般一个项目中共享的配置信息会放到以上的标签当中。-->
     <!--如果你的配置信息只是想给某一个servlet作为参考,那么你配置到servlet标签当中即可,使用ServletConfig对象来获取。-->
    复制代码
     // 获取应用的根路径(非常重要),因为在java源代码当中有一些地方可能会需要应用的根路径,这个方法可以动态获取应用的根路径
     // 在java源码当中,不要将应用的根路径写死,因为你永远都不知道这个应用在最终部署的时候,起一个什么名字。
     public String getContextPath();
     //String contextPath = application.getContextPath();
    复制代码
     // 获取文件的绝对路径(真实路径)
     public String getRealPath(String path);
    复制代码
     // 通过ServletContext对象也是可以记录日志的
     public void log(String message);
     public void log(String message, Throwable t);
     // 这些日志信息记录到哪里了?
     // localhost.2021-11-05.log
     ​
     // Tomcat服务器的logs目录下都有哪些日志文件?
     //catalina.2021-11-05.log 服务器端的java程序运行的控制台信息。
     //localhost.2021-11-05.log ServletContext对象的log方法记录的日志信息存储到这个文件中。
     //localhost_access_log.2021-11-05.txt 访问日志
    复制代码
     // ServletContext对象还有另一个名字:应用域(后面还有其他域,例如:请求域、会话域)
     ​
     // 如果所有的用户共享一份数据,并且这个数据很少的被修改,并且这个数据量很少,可以将这些数据放到ServletContext这个应用域中
     ​
     // 为什么是所有用户共享的数据? 不是共享的没有意义。因为ServletContext这个对象只有一个。只有共享的数据放进去才有意义。
     ​
     // 为什么数据量要小? 因为数据量比较大的话,太占用堆内存,并且这个对象的生命周期比较长,服务器关闭的时候,这个对象才会被销毁。大数据量会影响服务器的性能。占用内存较小的数据量可以考虑放进去。
     ​
     // 为什么这些共享数据很少的修改,或者说几乎不修改?
     // 所有用户共享的数据,如果涉及到修改操作,必然会存在线程并发所带来的安全问题。所以放在ServletContext对象中的数据一般都是只读的。
     ​
     // 数据量小、所有用户共享、又不修改,这样的数据放到ServletContext这个应用域当中,会大大提升效率。因为应用域相当于一个缓存,放到缓存中的数据,下次在用的时候,不需要从数据库中再次获取,大大提升执行效率。
     ​
     // 存(怎么向ServletContext应用域中存数据)
     public void setAttribute(String name, Object value); // map.put(k, v)
     // 取(怎么从ServletContext应用域中取数据)
     public Object getAttribute(String name); // Object v = map.get(k)
     // 删(怎么删除ServletContext应用域中的数据)
     public void removeAttribute(String name); // map.remove(k)
     ​
     ​
  • 缓存机制

    • 连接池

      • JVM是一个进程。MySQL数据库是一个进程。进程和进程之间建立连接,打开通道是很费劲的。是很耗费资源的。怎么办?可以提前先创建好N个Connection连接对象,将连接对象放到一个集合当中,我们把这个放有Connection对象的集合称为连接池。每一次用户连接的时候不需要再新建连接对象,省去了新建的环节,直接从连接池中获取连接对象,大大提升访问效率。
    • 线程池

      • Tomcat服务器本身就是支持多线程的。

      • 实际上是在Tomcat服务器启动的时候,会先创建好N多个线程Thread对象,然后将线程对象放到集合当中,称为线程池。用户发送请求过来之后,需要有一个对应的线程来处理这个请求,这个时候线程对象就会直接从线程池中拿,效率比较高。

      • 所有的WEB服务器,或者应用服务器,都是支持多线程的,都有线程池机制。

    • redis

      • NoSQL数据库。非关系型数据库。缓存数据库。

HTTP协议

复制代码
 jakarta.servlet.Servlet(接口)【爷爷】
 jakarta.servlet.GenericServlet implements Servlet(抽象类)【儿子】
 jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)【孙子】
 ​
 我们以后编写的Servlet要继承HttpServlet类。
  1. 什么是HTTP协议?

    • HTTP协议:是W3C制定的一种超文本传输协议。(通信协议:发送消息的模板提前被制定好。)

    • W3C:

      • 万维网联盟组织

      • 负责制定标准的:HTTP HTML4.0 HTML5 XML DOM等规范都是W3C制定的。

      • 万维网之父:蒂姆·伯纳斯·李

    • B向S发数据要遵循HTTP协议。S向B发数据同样需要遵循HTTP协议。这样B和S才能解耦合。

    • 什么是解耦合?

      • B不依赖S。

      • S也不依赖B。

    • B/S表示:B/S结构的系统(浏览器访问WEB服务器的系统)

    • 浏览器 向 WEB服务器发送数据,叫做:请求(request)

    • WEB服务器 向 浏览器发送数据,叫做:响应(response)

  2. TTP的请求协议(B --> S)

    • HTTP的请求协议包括:4部分

      • 请求行

      • 请求头

        • 请求主机

        • 主机端口

        • 浏览器信息

        • 平台信息

        • cookie信息

        • ...

      • 空白行

        • 区分请求头和请求体
      • 请求体

        • 向服务器发送的具体数据
  3. HTTP的响应协议(S --> B)

    • HTTP的响应协议包括:4部分

      • 状态行

      • 响应头

      • 空白行

      • 响应体

  4. 怎么向服务器发送GET请求,怎么向服务器发送POST请求?

    • 只有一种情况可以发送POST请求:使用form表单,并且form标签中的method属性值为:method="post"。

    • 其他所有情况一律都是get请求

  5. GET请求和POST请求有什么区别?

    • get请求发送数据的时候,数据会挂在URI的后面,并且在URI后面添加一个"?","?"后面是数据。这样会导致发送的数据回显在浏览器的地址栏上。(get请求在"请求行"上发送数据)

    • post请求发送数据的时候,在请求体当中发送。不会回显到浏览器的地址栏上。也就是说post发送的数据,在浏览器地址栏上看不到。(post在"请求体"当中发送数据)

    • get请求只能发送普通的字符串。并且发送的字符串长度有限制,不同的浏览器限制不同。这个没有明确的规范。

    • get请求无法发送大数据量。

    • post请求可以发送任何类型的数据,包括普通字符串,流媒体等信息:视频、声音、图片。

    • post请求可以发送大数据量,理论上没有长度限制。

    • get请求在W3C中是这样说的:get请求比较适合从服务器端获取数据。

    • post请求在W3C中是这样说的:post请求比较适合向服务器端传送数据。

    • get请求是安全的。get请求是绝对安全的。为什么?因为get请求只是为了从服务器上获取数据。不会对服务器造成威胁。

    • post请求是危险的。为什么?因为post请求是向服务器提交数据,如果这些数据通过后门的方式进入到服务器当中,服务器是很危险的。另外post是为了提交数据,所以一般情况下拦截请求的时候,大部分会选择拦截(监听)post请求。

    • get请求支持缓存。

    • post请求不支持缓存。(POST是用来修改服务器端的资源的。)

      • post请求之后,服务器"响应的结果"不会被浏览器缓存起来。因为这个缓存没有意义。

模板方法设计模式

  1. 设计模式

    1. GoF设计模式(Gang of Four:4人组提出的设计模式)

    2. javaee设计模式:DAO DTO VO PO pojo......

HttpServlet源码分析

  1. 到目前为止我们接触了servlet规范中哪些接口?

    • jakarta.servlet.Servlet 核心接口(接口)

    • jakarta.servlet.ServletConfig Servlet配置信息接口(接口)

    • jakarta.servlet.ServletContext Servlet上下文接口(接口)

    • jakarta.servlet.ServletRequest Servlet请求接口(接口)

    • jakarta.servlet.ServletResponse Servlet响应接口(接口)

    • jakarta.servlet.ServletException Servlet异常(类)

    • jakarta.servlet.GenericServlet 标准通用的Servlet类(抽象类)

  2. http包下都有哪些类和接口呢?jakarta.servlet.http.*;

    • jakarta.servlet.http.HttpServlet (HTTP协议专用的Servlet类,抽象类)

    • jakarta.servlet.http.HttpServletRequest (HTTP协议专用的请求对象)

    • jakarta.servlet.http.HttpServletResponse (HTTP协议专用的响应对象)

  3. 回忆Servlet生命周期?

    • 用户第一次请求

      • Tomcat服务器通过反射机制,调用无参数构造方法。创建Servlet对象。(web.xml文件中配置的Servlet类对应的对象。)

      • Tomcat服务器调用Servlet对象的init方法完成初始化。

      • Tomcat服务器调用Servlet对象的service方法处理请求。

    • 用户第二次请求

      • Tomcat服务器调用Servlet对象的service方法处理请求。
    • 用户第三次请求

      • Tomcat服务器调用Servlet对象的service方法处理请求。
    • ....

      • Tomcat服务器调用Servlet对象的service方法处理请求。
    • 服务器关闭

      • Tomcat服务器调用Servlet对象的destroy方法,做销毁之前的准备工作。

      • Tomcat服务器销毁Servlet对象。

  4. 到今天我们终于得到了最终的一个Servlet类的开发步骤:

    • 第一步:编写一个Servlet类,直接继承HttpServlet

    • 第二步:重写doGet方法或者重写doPost方法,到底重写谁,javaweb程序员说了算。

    • 第三步:将Servlet类配置到web.xml文件当中。

    • 第四步:准备前端的页面(form表单),form表单中指定请求路径即可。

关于一个web站点的欢迎页面

  1. 怎么设置欢迎页面呢?

    • 第一步:我在IDEA工具的web目录下新建了一个文件login.html

    • 第二步:在web.xml文件中进行了以下的配置

      复制代码
       <welcome-file-list>
               <welcome-file>login.html</welcome-file>
           </welcome-file-list>
      • 注意:设置欢迎页面的时候,这个路径不需要以"/"开始。并且这个路径默认是从webapp的根下开始查找。
    • 第三步:启动服务器,浏览器地址栏输入地址

  2. 欢迎页可以是一个Servlet吗?

    • 当然可以。

    • 你不要多想,欢迎页就是一个资源,既然是一个资源,那么可以是静态资源,也可以是动态资源。

    • 静态资源:index.html welcome.html .....

    • 动态资源:Servlet类。

关于WEB-INF目录

  • 在WEB-INF目录下新建了一个文件:welcome.html

  • 打开浏览器访问:http://localhost:8080/servlet07/WEB-INF/welcome.html 出现了404错误。

  • 注意:放在WEB-INF目录下的资源是受保护的。在浏览器上不能够通过路径直接访问。所以像HTML、CSS、JS、image等静态资源一定要放到WEB-INF目录之外。

HttpServletRequest接口详解

  • HttpServletRequest是一个接口,全限定名称:jakarta.servlet.http.HttpServletRequest

  • HttpServletRequest接口是Servlet规范中的一员。

  • HttpServletRequest接口的父接口:ServletRequest

  • HttpServletRequest接口中有哪些常用的方法?

    • 怎么获取前端浏览器用户提交的数据?

      复制代码
       Map<String,String[]> getParameterMap() 这个是获取Map
       Enumeration<String> getParameterNames() 这个是获取Map集合中所有的key
       String[] getParameterValues(String name) 根据key获取Map集合的value
       String getParameter(String name)  获取value这个一维数组当中的第一个元素。这个方法最常用。
       // 以上的4个方法,和获取用户提交的数据有关系。
  • request对象实际上又称为"请求域"对象。

    • 应用域对象是什么?

      • ServletContext (Servlet上下文对象。所有的用户共享的数据&&数据量很小&&数据修改操作很少)

      • ServletContext当中有三个操作域的方法:

        复制代码
         void setAttribute(String name, Object obj); // 向域当中绑定数据。
         Object getAttribute(String name); // 从域当中根据name获取数据。
         void removeAttribute(String name); // 将域当中绑定的数据移除
         ​
         // 以上的操作类似于Map集合的操作。
         Map<String, Object> map;
         map.put("name", obj); // 向map集合中放key和value
         Object obj = map.get("name"); // 通过map集合的key获取value
         map.remove("name"); // 通过Map集合的key删除key和value这个键值对。
    • 你见过哪些缓存技术呢?

      • 字符串常量池

      • 整数型常量池 [-128~127]

      • 数据库连接池

      • 线程池(Tomcat服务器就是支持多线程的)

      • redis、mongoDB.....

使用纯Servlet做一个单表的CRUD操作

  1. 使用纯粹的Servlet完成单表【对部门的】的增删改查操作(B/S结构的。)

  2. 步骤

    1. 第一步:准备一张数据库表。(sql脚本)

    2. 第二步:准备一套HTML页面(项目原型)【前端开发工具使用HBuilder】

      1. 欢迎页面:index.html

      2. 列表页面:list.html(以列表页面为核心,展开其他操作。)

      3. 新增页面:add.html

      4. 修改页面:edit.html

      5. 详情页面:detail.html

    3. 第三步:只要这个操作连接了数据库,就表示一个独立的功能

      1. 查看部门列表

      2. 新增部门

      3. 删除部门

      4. 查看部门详细信息

      5. 跳转到修改页面

      6. 修改部门

    4. 第四步:在IDEA当中搭建开发环境

      1. 创建一个webapp(给这个webapp添加servlet-api.jar和jsp-api.jar到classpath当中。)

      2. 向webapp中添加连接数据库的jar包(mysql驱动)

        • 必须在WEB-INF目录下新建lib目录,然后将mysql的驱动jar包拷贝到这个lib目录下。这个目录名必须叫做lib,全部小写的。
      3. JDBC的工具类

      4. 将所有HTML页面拷贝到web目录下。

    5. 第五步:实现第一个功能:查看部门列表

      1. 第一:先修改前端页面的超链接,因为用户先点击的就是这个超链接。

      2. 第二:编写web.xml文件

      3. 第三:编写DeptListServlet类继承HttpServlet类。然后重写doGet方法。

      4. 第四:在DeptListServlet类的doGet方法中连接数据库,查询所有的部门,动态的展示部门列表页面.

      5. 第六步:查看部门详情。

    6. 第六步:查看部门详情

    7. 第七步:删除部门

    8. 第八步:新增部门

    9. 第九步:跳转到修改部门的页面

    10. 第十步:修改部门

在一个web应用中应该如何完成资源的跳转

  • 在一个web应用中可以通过两种方式:

    • 第一种方式:转发

    • 第二种方式:重定向

  • 区别:

    • 转发代码:

      复制代码
       // 获取请求转发器对象
       RequestDispatcher dispatcher = request.getRequestDispatcher("/dept/list");
       // 调用请求转发器对象的forward方法完成转发
       dispatcher.forward(request, response);
       ​
       // 合并一行代码
       request.getRequestDispatcher("/dept/list").forward(request, response);
       // 转发的时候是一次请求,不管你转发了多少次。都是一次请求。
       // AServlet转发到BServlet,再转发到CServlet,再转发到DServlet,不管转发了多少次,都在同一个request当中。
       // 这是因为调用forward方法的时候,会将当前的request和response对象传递给下一个Servlet。
    • 重定向代码:

      复制代码
       // 注意:路径上要加一个项目名。为什么?
       // 浏览器发送请求,请求路径上是需要添加项目名的。
       // 以下这一行代码会将请求路径“/oa/dept/list”发送给浏览器
       // 浏览器会自发的向服务器发送一次全新的请求:/oa/dept/list
       response.sendRedirect("/oa/dept/list");
    • 转发形式(一次请求)

    • 重定向形式(两次请求)

    • 转发和重定向的本质区别

      • 转发:是由WEB服务器来控制的。A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的。

      • 重定向:是浏览器完成的。具体跳转到哪个资源,是浏览器说了算

  • 转发:上一个Servlet当中向request域当中绑定了数据,希望从下一个Servlet当中把request域里面的数据取出来。存在浏览器的刷新问题

  • 重定向(使用较多):剩下所有的请求

将oa项目中的资源跳转修改为合适的跳转方式

  • 删除之后,重定向

  • 修改之后,重定向

  • 保存之后,重定向

  • 重定向:

    • 成功

    • 失败

Servlet注解,简化配置

  • oa项目中的web.xml文件

    • 只是一个单标的CRUD,没有复杂的业务逻辑。对于大项目来说web.xml文件回非常庞大;进行servlet对每一个配置,开发效率低;在web.xml文件中配置很少呗修改。

    • 将配置信息直接写到java类中

  • Servlet3.0版本之后,推出了各种Servlet基于注解式开发

    • 有一些需要变化的信息,还是要配置到web.xml文件中

    • 注解+配置文件 的开发模式

    • 我们的第一个注解:

      复制代码
       jakarta.servlet.annotation.WebServlet
    • 在Servlet类上使用:@WebServlet,WebServlet注解中有哪些属性呢?

      • name属性:用来指定Servlet的名字。等同于:<servlet-name>

      • urlPatterns属性:用来指定Servlet的映射路径。可以指定多个字符串。<url-pattern>

      • loadOnStartUp属性:用来指定在服务器启动阶段是否加载该Servlet。等同于:<load-on-startup>

      • value属性:当注解的属性名是value的时候,使用注解的时候,value属性名是可以省略的。

      • 注解对象的使用格式:

        • @注解名称(属性名=属性值, 属性名=属性值, 属性名=属性值....)

使用模板方法设计模式优化oa项目

  • 注解解决了配置文件的问题。但是oa项目仍然有臃肿的问题,一个简单的oa就写了6个Servlet。

  • Java程序中不要编写前端代码

JSP

  • JSP(JavaServer Pages)实际上就是一个Servlet

  • jsp问价第一次访问的时候比较慢,所以给客户演示时需要提前把所有的jsp文件先访问一遍

    • 要把jsp文件翻译生成java源文件

    • java源文件要编译生成class字节码文件

    • 然后通过class去创建servlet对象

    • 然后调用servlet对象的init方法

    • 最后调用servlet对象的service方法。

  • JSP与Servlet的区别

    • 职责不同:

      • Servlet:收集数据。(Servlet的强项是逻辑处理,业务处理,然后链接数据库,获取/收集数据。)

      • JSP:展示数据

  • JSP文件中编写的文字会翻译到servlet类的service方法的out.write里

  • JSP(不是默认UTF-8)的page指令:解决响应时的中文乱码问题

    复制代码
     <%@page contentType="text/html;charset=UTF-8" %>
  • JSP基础语法总结:

    • JSP中直接编写普通字符串

      • 翻译到service方法的out.write("这里")
    • <%%>

      • 翻译到service方法体内部,里面是一条一条的java语句。
    • <%! %>

      • 翻译到service方法之外。
    • <%= %>

      • 翻译到service方法体内部,输出的内容有变量。翻译为:out.print();
    • <%@page contentType="text/html;charset=UTF-8"%>

      • page指令,通过contentType属性用来设置响应的内容类型。
  • 使用Servlet + JSP完成oa项目的改造

    • 使用Servlet处理业务,收集数据

    • 使用JSP展示数据

  • 包名bean?

    • javabean(java的logo是一杯冒着热气的咖啡。javabean被翻译为:咖啡豆)

    • java是一杯咖啡,咖啡又是由一粒一粒的咖啡豆研磨而成。

    • 整个java程序中有很多bean的存在。由很多bean组成。

    • 实际上javabean你可以理解为符合某种规范的java类,比如:

      • 有无参数构造方法

      • 属性私有化

      • 对外提供公开的set和get方法

      • 实现java.io.Serializable接口

      • 重写toString

      • 重写hashCode+equals

    • javabean其实就是java中的实体类。负责数据的封装。

    • 由于javabean符合javabean规范,具有更强的通用性

  • 实现登录功能

    • 步骤1:数据库当中添加一个用户表:t_user

    • 步骤2:再实现一个登录页面。

    • 步骤3:后台要有一个对应的Servlet来处理登录的请求。

    • 步骤4:再提供一个登录失败的页面。

  • JSP指令

    • 指令分类

      • include指令:包含指令(静态包含,很少用)

      • taglib指令:引入标签库的指令

      • page指令:重点

    • 使用语法

      • <%@指令名 属性名=属性值 属性名=属性值 属性名=属性值......%>
  • JSP的九大内置对象

    • jakarta.servlet.jsp.PageContext pageContext 页面作用域

    • jakarta.servlet.http.HttpServletRequest request 请求作用域

    • jakarta.servlet.http.HttpSession session 会话作用域

    • jakarta.servlet.ServletContext application 应用作用域

      • pageContext < request < session < application

      • 以上四个作用域都有:setAttribute、getAttribute、removeAttribute方法。

      • 以上作用域的使用原则:尽可能使用小的域。

    • java.lang.Throwable exception

    • jakarta.servlet.ServletConfig config

    • java.lang.Object page (其实是this,当前的servlet对象)

    • jakarta.servlet.jsp.JspWriter out (负责输出)

    • jakarta.servlet.http.HttpServletResponse response (负责响应)

关于B/S结构系统的会话机制(session机制)

  • 一次会话:用户打开浏览器,进行一系列操作,然后最终将浏览器关闭(一次会话中包含多次请求)

  • 一次请求:用户在浏览器上点击了一下,然后到页面停下来

  • 在java的servlet规范当中,session对应的类名:HttpSession(jarkata.servlet.http.HttpSession)

  • session对象最主要的作用是:保存会话状态(用户登录成功了,这是一种登录成功的状态)

    • HTTP协议是一种无状态协议(降低服务器的压力)

    • request请求域(HttpServletRequest)、session会话域(HttpSession)、application域(ServletContext)

    • request < session < application

    • session实验原理:类似于map集合,集合中的key存储的是sessionid(cookie)

    • session销毁:超时or手动

  • 销毁session对象:

    复制代码
     session.invalidate();
  • cookie最终是保存在浏览器客户端上的。

    • 可以保存在运行内存中。(浏览器只要关闭cookie就消失了。)

    • 也可以保存在硬盘文件中。(永久保存。)

  • cookie有啥用呢?

    • cookie和session机制其实都是为了保存会话的状态。

    • cookie是将会话的状态保存在浏览器客户端上。(cookie数据存储在浏览器客户端上的。)

    • session是将会话的状态保存在服务器端上。(session对象是存储在服务器上。)

  • 十天免登录

    • 用户输入正确的用户名和密码,并且同时选择十天内免登录。登录成功后。浏览器客户端会保存一个cookie,这个cookie中保存了用户名和密码等信息,这个cookie是保存在硬盘文件当中的,十天有效

    • 怎么让cookie失效?

      • 十天过后自动失效。

      • 或者改密码。

      • 或者在客户端浏览器上清除cookie。

  • cookie机制和session机制其实都不属于java中的机制,实际上cookie机制和session机制都是HTTP协议的一部分。

  • 关于cookie的有效时间

    • 怎么用java设置cookie的有效时间

      • cookie.setMaxAge(60 * 60); 设置cookie在一小时之后失效。
    • 没有设置有效时间:默认保存在浏览器的运行内存中,浏览器关闭则cookie消失。

    • 只要设置cookie的有效时间 > 0,这个cookie一定会存储到硬盘文件当中。

    • 设置cookie的有效时间 = 0 呢?

      • cookie被删除,同名cookie被删除。
    • 设置cookie的有效时间 < 0 呢?

      • 保存在运行内存中。和不设置一样。
  • 关于cookie的path,cookie关联的路径:

  • 使用cookie实现十天内免登录功能

    • 先实现登录功能(登录成功、登录失败)

    • 前端页面修改

      • 给一个复选框:十天内免登录(选择or不选择)
    • 修改Servlet中的login方法

      • 选择免登录:Servlet的login方法中应该创建cookie,用来存储用户名和密码,并设置路径和有效期,将cookie响应给浏览器
    • 页面跳转

EL表达式

  • EL(Expression Language):表达式语言

    • 可代替JSP中的java代码,使程序看起来更加整洁、美观

    • 算是JSP语法的一部分

  • 作用

    • 从作用域中取数据->转换成字符串->输出到浏览器

    • 第一功效:从某个域中取数据。

      • 四个域:

        • pageContext

        • request

        • session

        • application

    • 第二功效:将取出的数据转成字符串。

      • 如果是一个java对象,也会自动调用java对象的toString方法将其转换成字符串。
    • 第三功效:将字符串输出到浏览器。

      • 和这个一样:<%= %>,将其输出到浏览器。
  • 语法格式:

    • ${表达式}
  • 掌握使用EL表达式,怎么从Map集合中取数据:

    • ${map.key}
  • 掌握使用EL表达式,怎么从数组和List集合中取数据:

    • ${数组[0]}

    • ${数组[1]}

    • ${list[0]}

  • EL表达式的运算符

    • 算术运算符

      • +、-、*、/、%
    • 关系运算符

      • == eq != > >= < <=
    • 逻辑运算符

      • ! && || not and or
    • 条件运算符

      • ? :
    • 取值运算符

      • \]和.

      • empty运算符的结果是boolean类型

      • ${empty param.username}

      • ${not empty param.username}

      • ${!empty param.password}

JSTL标签库

  • 概念

    • Java Standard Tag Lib(Java标准的标签库)

    • 结合EL一起使用:让JSP中的java代码小时

    • 实际上还是要执行java程序(java程序在jar包当中)

  • 使用步骤

    • 第一步:引入JSTL标签库对应的jar包

      第二步:在JSP中引入要使用标签库。(使用taglib指令引入标签库。)

      第三步:在需要使用标签的位置使用即可。表面使用的是标签,底层实际上还是java程序

  • 源码解析:配置文件tld解析

改造OA

  • Servlet + JSP + EL表达式 + JSTL标签。进行改造

  • 改造路径:在前端HTML代码中,有一个标签,叫做base标签

Filter过滤器

  • 原理:

    • 每一个Servlet类当中有重复编写的代码,通过filter则只用写一遍(公共代码):判断登录

    • 是一个java程序

    • filter可在Servlet目标程序执行之前or之后添加代码、过滤规则

  • 编写步骤

    • 第一步:编写java类实现一个接口:jarkata.servlet.Filter

      • init方法:在Filter对象第一次被创建之后调用,并且只调用一次。

      • doFilter方法:只要用户发送一次请求,则执行一次。在这个方法中编写过滤规则。

      • destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。

    • 第二步:在web.xml文件中对Filter进行配置或者使用注解:@WebFilter({"*.do"})

  • web.xml文件中配置的filter执行顺序:依靠filter-mapping标签的配置位置,越靠上优先级越高。

  • filter调用顺序:栈顺序结构

  • filter设计模式

    • 责任链设计模式:Filter的执行顺序是在程序运行阶段动态组合的

    • 核心思想:程序运行阶段,动态的组合程序的调用顺序

Listener监听器

  • 作用:

    • 在Servlet中,所有的监听器接口都是以"Listener"结尾

    • javaweb程序员的特殊的时刻想要执行这段代码,需要使用对应的监听器

  • 分类

    • jakarta.servlet包下:

      • ServletContextListener

      • ServletContextAttributeListener

      • ServletRequestListener

      • ServletRequestAttributeListener

    • jakarta.servlet.http包下:

      • HttpSessionListener

      • HttpSessionAttributeListener

      • HttpSessionBindingListener

      • HttpSessionIdListener

      • HttpSessionActivationListener

  • 实现步骤

    • 第一步:编写一个类实现ServletContextListener接口,并且实现里面的方法

    • 第二步:在web.xml文件中ServletContextListener进行配置or用注解,例如:@WebListener

  • 实现oa项目中当前登录在线的人数。

    • 什么代表着用户登录了?

      • session.setAttribute("user", userObj); User类型的对象只要往session中存储过,表示有新用户登录。
    • 什么代表着用户退出了?

      • session.removeAttribute("user"); User类型的对象从session域中移除了。

      • 或者有可能是session销毁了。(session超时)

相关推荐
唐叔在学习12 分钟前
就算没有服务器,我照样能够同步数据
后端·python·程序员
用户68545375977691 小时前
同步成本换并行度:多线程、协程、分片、MapReduce 怎么选才不踩坑
后端
javaTodo1 小时前
Claude Code 记忆机制详解:从 CLAUDE.md 到 Auto Memory,六层体系全拆解
后端
LSTM971 小时前
使用 C# 和 Spire.PDF 从 HTML 模板生成 PDF 的实用指南
后端
JaguarJack2 小时前
为什么 PHP 闭包要加 static?
后端·php·服务端
BingoGo2 小时前
为什么 PHP 闭包要加 static?
后端
是糖糖啊2 小时前
OpenClaw 从零到一实战指南(飞书接入)
前端·人工智能·后端
百度Geek说2 小时前
基于Spark的配置化离线反作弊系统
后端
后端AI实验室3 小时前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai