后端开发基础——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运算符

      • 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超时)

相关推荐
Java知识技术分享2 分钟前
SecureUtil.aes数据加密工具类
java·后端·intellij-idea
小丁爱养花14 分钟前
Spring MVC:设置响应
java·开发语言·前端
神洛华21 分钟前
Y3编辑器功能指引
java·数据库·编辑器
冯萦岚28 分钟前
R语言的图形用户界面
开发语言·后端·golang
{⌐■_■}35 分钟前
【GORM】事务,嵌套事务,保存点事务的使用,简单电商平台go案例
开发语言·jvm·后端·mysql·golang
李少兄37 分钟前
解决因JDK升级导致的`java.nio.file.NoSuchFileException`问题
java·python·nio
涛ing37 分钟前
19. C语言 共用体(Union)详解
java·linux·c语言·c++·vscode·算法·visual studio
次元工程师!39 分钟前
JAVA-IO模型的理解(BIO、NIO)
java·笔记·学习·nio·bio·io模型
C++小厨神1 小时前
Kotlin语言的正则表达式
开发语言·后端·golang
小猪咪piggy1 小时前
【JavaSE】(8) String 类
java·开发语言