文章目录

四. tomcat服务器(web项目代码的容器)CS和BS的异同点新建项目-部署-运行-访问新建web项目,在tomcat部署运行和访问

在idea新建java web项目web项目的配置lib文件夹和artifact的关系部署进一步说明什么叫web项目

四:JDBC和DAOjava se + 数据库项目实战一些概念

项目架构项目需求

五. servelet一个简单的例子xxxServlet类xxxServlet类实现第一个功能-获取来自客户端的数据http request(http请求)获取数据重写继承的哪一个方法以及实例化哪一个xxxServlet类xxxServlet类的设计对请求-响应执行顺序的理解

xxxServlet类实现第二个功能-调用DAO完成对数据库的操作xxxServlet类实现第三个功能-在控制台打印相应的操作成功

处理http request中的中文乱码Servlet的继承树和service方法继承树service方法

servlet的生命周期servlet的初始化时机tomcat容器与servlet

http协议会话-session-http是无状态的http是无状态的会话跟踪session保存作用域

服务器端转发和客户端重定向服务器端转发客户端重定向

thymeleaf为什么使用thymeleaf配置thymeleaf的步骤如何实现大量统一格式的数据在html页面的展示

回顾servlet保存作用域作用域解释HttpServletRequest容器HttpSession容器ServletContext容器

绝对路径和相对路径区分超链接和超文本引用

正式进入后端

四. tomcat服务器(web项目代码的容器)

CS和BS的异同点

CS:client-server架构模式 充分利用客户端机器的资源,减轻服务器的负荷(将一部分安全要求不高额计算或者存储任务放在客户端,减轻服务器压力以及减轻网络负荷)

但是,客户端需要单独安装,也需要升级维护(成本较高,以前的升级很麻烦,打补丁包,可能有多个)

BS:browser-server架构模式 不需要单独安装客户端

但是所有的计算、存储任务都在服务器吨,服务器负荷重。同时,计算结果要通过网络传输给用户,因此浏览器和服务器会进行频繁的网络通信,网络负荷重

新建项目-部署-运行-访问

tomcat是服务器端的一个webcontainer,免费,体积小,性能还行

可以在tomcat中安装项目,这个过程又叫做“部署”deploy,也就是把写好的程序拷贝到相应的项目目录下

项目名称又叫做context root

bin:可执行文件目录 conf:配置文件目录 lib:tomcat使用java和C开发,依赖 logs:日志 webapps:部署项目的空间,早期做法,现在可以自定义,workspace work:项目的目录

配置环境变量 tomcat中的bin/start.bat需要jvm,因此需要告诉tomcat服务器jdk的位置(jre包含在jdk中)。也就是在环境变量中创建JDK_HOME

启动tomcat服务(就像mysql服务器),访问主页 先启动bin/start.bat,然后输入url,http://localhost:8080/ 注意不是https,而是http,如果是前者,报错 启动start.bat之后,可以看到一个进程msedge.exe占用了8080端口 使用netstat -ano|findstr 8080命令可以查看

新建web项目,在tomcat部署

在webapps文件夹下,新建文件夹baidu,作为web项目目录

在baidu目录下新建文件夹WEB-INF,目录名全部大写

一个web项目基本结构就是这样

运行和访问

在baidu目录下导入项目文件 然后重启start.bat,也就是tomcat服务,再在浏览器输入http://localhost:8080/baidu/demo09.html就可以看到 这是很激动人心的时刻,就是说我们从客户端访问到了服务器的资源 曾经的我们打开.html文件是在本地,打开页面之后,其地址是 现在资源的地址变成了http://localhost:8080/baidu/demo09.html

localhost:8080通过ip地址和端口号定位到某台计算机上的tomcat服务器 baidu/demo09.html通过路径定位到服务器上的项目

舒服了,这才是互联网

在idea新建java web项目

(1)在idea中配置tomcat服务器。就是首先得让idea找到tomcat

(2)添加框架支持。自动将我们的java module变成web application。帮我们创建了web项目的文件目录 相比于前面我们直接在tomcat安装路径下创建的目录还是有区别 tomcat/webapps/baidu目录下默认会有一个WEB-INF文件夹,我们的项目和WEB-INF在同一级目录 (3)编辑web工程的结构(edit configuration) 也就是加上本地或者远程的tomcat服务器 左起第二个框,是select run/debug configuration,这个地方要选对,如果是java se程序,那么就是程序名;如果是java web项目,就是你配置的服务器名

点击下拉菜单,可以编辑当前选中的configuration 然后就可以进行部署等相关设置

(4)部署web项目 也是在edit configuration中完成部署

web项目的配置

有几个比较重要的按键: (1)右键module,add framework support, 添加框架支持,比如说让一个java se module变成一个java web module (2)file->project structure,对整个项目的设置进行调整 挺恶心的,全是英文

facets:本意是方面,部分。可以用于添加框架支持。比如说将一个java se module变成一个java web module web项目还需要部署到tomcat服务器中。更准确地说,一个项目要能够部署到服务器中,就必须按照规范先变成一个web项目(创建标准格式的目录),然后再部署到服务器。

之前我们是在tomcat安装目录下的webapps目录下去创建了一个项目文件夹baidu,然后在baidu目录下创建了一个WEB-INF文件夹,接着将项目源码放在和WEB-INF同一级目录下。完成以后,先启动tomcat服务器,然后就可以通过url=http://localhost:8888/baidu/hello.html在浏览器访问到相应的资源

在idea中,web项目的目录结构都不一样了。并不是将源代码部署到服务器,而是将一个部署包部署到tomcat。这个部署包叫做artifact,本意是指人工制品。

artifacts:web项目部署包。

lib文件夹和artifact的关系

lib是我们自定义的依赖,artifact是部署包,artifact中包含了引用lib的信息

先有artifact,如果之后有了新的依赖,必须手动更新artifact。要么删掉重建,要么fix

为了写DAO,或者引入数据库连接池,我们都写过依赖。不管是idea还是eclipse,都由我们自己创建了一个叫做lib的文件夹,然后将相应的驱动直接复制到这个lib文件夹下

接着就有区别了: 对于eclipse,右键驱动,选择build path 对于idea,右键lib文件夹,选择add as library,直接将这个lib文件夹变成依赖

对于idea,module之前是不共享依赖的。因此需要对每一个module添加这个依赖 还是project stucture,选择module,选中module,找右边的dependencies来添加依赖

部署

准备好web项目,依赖,部署包之后,就准备开始部署到tomcat服务器了

这个时候就可以edit configuration了

先添加tomcat服务器 再将artifact部署包部署,也就是添加artifact 下面有个application context,他的值就是一个路径,这个路径会被添加到server选项卡的URL的值得后面

URL的值默认是http://localhost:8080,默认访问的顺序是 这是在tomcat服务器中的默认设置,在config/web.xml中设置好的

假设 application context=/pro,那么URL=http://localhost:8080/pro

进一步说明

什么叫web项目

第一印象里,web项目是说项目里边必须包含web相关的固定格式的目录。在project structure里,我们可以看到web项目的module里边包含web 具体来说,有了web意味着什么呢??有什么变化??? 位置1是WEB-INF中web.xml文件的地址,叫做deployment description 位置2是web文件夹的地址,叫做web resource directory 位置3是src文件夹的地址,叫做source roots 这样看下来,不就是把web项目重要的三类资源的起始目录给记录下来了吗

四:JDBC和DAO

虽然前面已经学习过这两部分内容,但是我们需要在java web的背景下再回顾

JDBC:实现通过java控制数据库 DAO:管理代码的一种方式。将操作数据库的原子操作封装在BaseDAO中 然后针对每一张数据表设计对应的映射类,接口,DAO

在引入java web以前,我们学习到的java se的知识已经可以支撑应用软件的基本开发

SSM:spring, springmvc, mabatis

java se + 数据库项目实战

一些概念

之前,我们是将数据表的映射类放在了java bean里边,但是我们对java bean的元素有相当严格的界定。现在是将映射类放在pojo里边

POJO是Plain OrdinaryJava Object的缩写,实质上可以理解为简单的实体类,顾名思义POJO类的作用是方便程序员使用数据库中的数据表,对于广大的程序员,可以很方便的将POJO类当做对象来进行使用,当然也是可以方便的调用其get,set方法。POJO类也给我们在struts框架中的配置带来了很大的方便

JavaBean则比 POJO复杂很多, Java Bean 是可复用的组件,对 Java Bean 并没有严格的规范,理论上讲,任何一个 Java 类都可以是一个 Bean。但是,javabean还是有一些必要的结构: (1)通常情况下,由于 Java Bean 是被容器所创建(如 Tomcat) 的,所以 Java Bean 应具有一个无参的构造器 (2)实现 Serializable 接口用于实现 Bean 的持久性 (3)不能被跨进程访问

一般在web应用程序中建立一个数据库的映射对象时,我们只能称它为POJO。POJO(Plain Old Java Object)这个名字用来强调它是一个普通java对象,而不是一个特殊的对象,其主要用来指代那些没有遵从特定的Java对象模型、约定或框架(如EJB)的Java对象。理想地讲,一个POJO是一个不受任何限制的Java对象(除了Java语言规范)

项目架构

BaseDAO类:通用的增删改查操作 xxxDAO接口:针对某一张数据表的原子操作,使用继承与BaseDAO的方法实现 xxxDAOImpl类:重写xxxDAO接口中的所有方法

然后在具体的业务模块,我们会设计大量的业务方法,这些业务方法由xxxDAO接口定义的原子操作来实现

总结:业务方法由xxxDAOImpl类实现类中的原子操作实现,xxxDAOImpl实现类中的原子操作由BaseDAO中的原子操作实现

项目需求

有这样一个场景:在下单的时候,订单表中显示谁在什么时间买了什么东西 而具体买了什么在另外一张表 订单详情表 呈现: 这样一来就产生了一个新的需求:需要获取订单表的id来访问订单详情表的某一条记录。而BaseDAO中通用的增删改这一原子操作是不返回id的

需求:在增加数据完成后返回自增列的值 之前我都忽略了一点,conn.preparedStatemetn是有返回值的,返回int

一个新知识,conn.preparedStatemetn的重载方法返回一个ResultSet实例,但是方法的参数要增加 对于删和改没有上面这一需求,只针对增这一操作。因此,我们需要解析字符串sql,看是不是以insert开头。调用下面的方法进行解析sql.trim().toUpperCase().startsWith("INSERT") trim方法,去掉字符串首尾空格;toUpperCase方法,将字符串全转为大写;startsWith方法,从首字母开始匹配,看是否能匹配到目标字符串

五. servelet

在后端编程中,我们需要一些逻辑结构,比如servlet(server applet,服务器连接器,applet的本意是小程序),JSP

HTML:页面的结构 CSS: 页面的美化 JS:页面的行为 JQuery:封装了JS VUE:封装了JS(简单) React:封装了JS

TOMCAT:服务器 xml:可以自定义标签,用来写配置文件 JSON:服务器向浏览器传数据以JSON的格式,轻量级,更易解析 servlet:用于和浏览器交互,tomcat中最重要的组件获取请求,处理请求,响应请求 filter:过滤器,比如说购物车点击购买,会先看是否登录等等 listener:监听器,监听用户的操作 HTTP:浏览器和服务器交互需要遵循的协议 JSP:java服务器页面,响应请求显示的页面,动态页面 EL,JSTL:用于提高JSP的开发效率

会话控制:服务器无法区分请求的来源,通过会话控制区分请求来自于哪个服务器

Ajax:实现异步请求。比如说网站注册,输入完用户名,后面就会判断是否通过,此时我们并没有主动点击注册

一个简单的例子

经过前面对于tomcat服务器的学习,我们知道,当启动tomcat服务器且服务器中有相应的资源时,我们可以通过浏览器输入url(统一资源定位符)打开相应的文件 比如说有这样一个.html文件

Title

名称:

价格:

库存:

备注:

(1)通过url,向服务器发起请求 (2)服务器响应请求,返回响应的数据 (3)当我们点击添加按钮,客户端又向服务器发起请求.同时传给服务器的还包括此次进行的操作action,填写好的数据 (4)服务器需要有组件来获取请求,处理请求,响应请求。这个组件就是servlet。从实际代码角度看,我们需要专门设计一个类,用以处理action。比如action = add,那就设计一个叫做AddServlet的类(添加服务器端小程序)

这个类的作用是: 获取来自客户端的数据 调用DAO完成对数据库的操作 在控制台打印相应的操作成功

(5)这个组件可以调用DAO,向数据库服务器中添加数据

xxxServlet类

一个普通的xxxServlet类是无法完成以下功能的: 获取来自客户端的数据 调用DAO完成对数据库的操作 在控制台打印相应的操作成功

服务器厂商,比如说tomcat,会提供一个父类HttpServlet,自定义的xxxServlet类去继承这个父类。这个父类的声明为:public abstract class HttpServlet extends javax.servlet.GenericServlet ,是一个抽象父类

实际上服务器厂商会提供JSP和servlet等许多结构的相关API,都在安装路径的lib文件夹中,我们在使用的时候需要手动导入需要的依赖(dependency)

xxxServlet类实现第一个功能-获取来自客户端的数据

http request(http请求)

万事万物皆对象,http请求也被封装为对象,封装到HttpServletRequest类,这个类来自javax.servlet.http,由服务器厂商提供

获取数据

以前学习计算机网络的时候,知道http报文中携带了数据,他们按照固定的格式排列,服务器提供的API中的抽象类HttpServletRequest提供了getParameter方法来解析http报文

传入getParameter方法的参数就来自于.html文件中的name属性的值

重写继承的哪一个方法以及实例化哪一个xxxServlet类

在上面的.html文件中,我们是这样声明表单的

重写哪一个方法: 由method属性的值决定。服务器提供的API中的抽象类HttpServletRequest提供了doXxx方法。如果method=“post”,那么就重写doPost方法

实例化哪一个xxxServlet类: 在WEB-INF文件夹下,有一个web.xml文件,在里边建立action属性的值与xxxServlet的映射关系。比如说,当获取到action的值为add时,就实例化AddServlet类

AddServlet

com.atguigu.servlets.AddServlet

AddServlet

/add

xxxServlet类的设计

/**

* @ClassName:AddServlet

* @Package:com.atguigu.servlets

* @Description:用以获取请求,处理请求,响应请求

*

* @Author:jjcale

* @Version:v1.0

*/

public class AddServlet extends HttpServlet {

/**

* 客户端向服务器端上传数据的一种方法叫post,method=post

* 重写这个doPost()方法

*/

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//客户端返回的数据包括属性name的值,这个值有好几个,fname,price,fcount,remark

String fname = request.getParameter("fname");

String priceStr = request.getParameter("price");

Integer price = Integer.parseInt(priceStr);

String fcountStr = request.getParameter("fcount");

Integer fcount = Integer.parseInt(fcountStr);

String remark = request.getParameter("remark");

System.out.println("fname is " + fname + " price is " + price + " fcount is " + fcount + " rema" +

"rk is " + remark);

}

}

对请求-响应执行顺序的理解

这个地方直觉上还是挺乱的

我的理解是: (1)执行web项目,不像是一个java se项目,我在某一个程序里边点击run就行了。反正在idea里边,直接点击run就可以,我在.html, .java都直接运行过 (2)注意,我的localhost既是服务器所在的主机,也是客户端所在的主机 (3)首先,我们的web项目通过配置,部署,它是事先知道tomcat的位置的,localhost:8080 (4)启动项目,就相当于客户端发起了请求,请求访问http://localhost:8080/pro07/add.html这一资源 (5)服务器先启动,连接客户端,然后响应 (6)客户端输入相关的数据,点击添加。action属性的值为add,这又是一个http请求。一点击添加,我们在浏览器的检查的网络里边,可以看到一个叫add的请求

从这里就能看出后端为什么要懂一些前端,像add,post这两个关键字在后端要用,add用于设计子类AddServlet,post用于重写doPost方法 这个请求的具体信息如下: (7)此时,AddServlet类就该获取请求(获取数据)。我们在doPost方法打印了获取到的数据 (8)然后处理请求,比如说增加数据库的数据 (9)响应请求,比如说弹窗,操作成功

xxxServlet类实现第二个功能-调用DAO完成对数据库的操作

前面设计的xxxServlet类只是打印了从请求中提取的数据,这些数据实际上都可以写入数据库了

有前述内容可知,我们通过xxxDAO这一结构完成与数据库的交互

@Override

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String fname = request.getParameter("fname");

String priceStr = request.getParameter("price");

Integer price = Integer.parseInt(priceStr);

String fcountStr = request.getParameter("fcount");

Integer fcount = Integer.parseInt(fcountStr);

String remark = request.getParameter("remark");

FruitDAO fruitDAO = new FruitDAOImpl();

boolean flag = fruitDAO.addFruit(new Fruit(0 , fname , price , fcount , remark));

System.out.println(flag ? "添加成功!" : "添加失败!");

}

xxxServlet类实现第三个功能-在控制台打印相应的操作成功

@Override

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println(flag ? "添加成功!" : "添加失败!");

}

处理http request中的中文乱码

背景:如果在名称一栏输入中文,AddServlet类捕获到的值就会是乱码 这是因为HttpServletRequest这个类的实例默认不支持中文造成的

我们知道method有两种值,一个是post,一个是默认情况的get

tomcat8之前,设置编码:

1)get请求方式:

//get方式目前不需要设置编码(基于tomcat8)

//如果是get请求发送的中文数据,转码稍微有点麻烦(tomcat8之前)

String fname = request.getParameter("fname");

//1.将字符串打散成字节数组

byte[] bytes = fname.getBytes("ISO-8859-1");

//2.将字节数组按照设定的编码重新组装成字符串

fname = new String(bytes,"UTF-8");

2)post请求方式:

request.setCharacterEncoding("UTF-8");

tomcat8开始,设置编码,只需要针对post方式

request.setCharacterEncoding("UTF-8");

Servlet的继承树和service方法

继承树

1. 继承关系

javax.servlet.Servlet接口

javax.servlet.GenericServlet抽象类

javax.servlet.http.HttpServlet抽象子类

XxxServlet子类(对应增删改查)

service方法

当服务器收到http request的时候,自动调用service方法

2. 相关方法

javax.servlet.Servlet接口:

void init(config) - 初始化方法

void service(request,response) - 服务方法

void destory() - 销毁方法

javax.servlet.GenericServlet抽象类:

void service(request,response) - 仍然是抽象的

javax.servlet.http.HttpServlet 抽象子类:

void service(request,response) - 不是抽象的

1. String method = req.getMethod(); 获取请求的方式

2. 各种if判断,根据请求方式不同,决定去调用不同的do方法

if (method.equals("GET")) {

this.doGet(req,resp);

} else if (method.equals("HEAD")) {

this.doHead(req, resp);

} else if (method.equals("POST")) {

this.doPost(req, resp);

} else if (method.equals("PUT")) {

3. 在HttpServlet这个抽象类中,do方法都差不多:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

String protocol = req.getProtocol();

String msg = lStrings.getString("http.method_get_not_supported");

if (protocol.endsWith("1.1")) {

resp.sendError(405, msg);

} else {

resp.sendError(400, msg);

}

}

3.小结:

1) 继承关系: HttpServlet -> GenericServlet -> Servlet

2) Servlet中的核心方法: init() , service() , destroy()

3) 服务方法: 当有请求过来时,service方法会自动响应(其实是tomcat容器调用的)

在HttpServlet中我们会去分析请求的方式:到底是get、post、head还是delete等等

然后再决定调用的是哪个do开头的方法

那么在HttpServlet中这些do方法默认都是405的实现风格-要我们子类去实现对应的方法,否则默认会报405错误

4) 因此,我们在新建Servlet时,我们才会去考虑请求方法,从而决定重写哪个do方法

servlet的生命周期

获取,处理,响应请求

看起来web项目不像java se项目,有非常明显的入口程序。比如说之前那个fruit项目,我们就是在view.java这个程序启动整个系统

而web项目,我在.html可以启动,在AddServlet.java可以启动,这就说明底层控制着整个java web程序的执行顺序,这个底层就是tomcat容器

servlet的生命周期也就和Servlet中的核心方法: init() , service() , destroy()直接相关

1) 生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init(),service(),destroy()

2) 默认情况下:

第一次接收请求时,这个Servlet会进行实例化(调用构造方法)、初始化(调用init())、然后服务(调用service())

从第二次请求开始,每一次都是服务

当容器关闭时,其中的所有的servlet实例会被销毁,调用销毁方法

3) 通过案例我们发现:

- Servlet实例tomcat只会创建一个,所有的请求都是这个实例去响应。

- 默认情况下,第一次请求时,tomcat才会去实例化,初始化,然后再服务.这样的好处是什么? 提高系统的启动速度 。 这样的缺点是什么? 第一次请求时,耗时较长。

- 因此得出结论: 如果需要提高系统的启动速度,当前默认情况就是这样。如果需要提高响应速度,我们应该设置Servlet的初始化时机。

servlet的初始化时机

Servlet的初始化时机:

- 默认是第一次接收请求时,实例化,初始化

- 我们可以通过来设置servlet启动的先后顺序,数 字越小,启动越靠前,最小值0

load-on-startup这个标签的值是一个无量纲的数,表示程度

tomcat容器与servlet

Servlet在容器中是:单例的、线程不安全的

- 单例:所有的请求都是同一个实例去响应

- 线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断。但是在中间某个时机,另一个线程改变了这个成员变量的值,从而导致第一个线程的执行路径发生了变化

- 我们已经知道了servlet是线程不安全的,给我们的启发是: 尽量的不要在servlet中定义成员变量。如果不得不定义成员变量,那么不要去:①不要去修改成员变量的值 ②不要去根据成员变量的值做一些逻辑判断

注意,并不是servlet总共只有一个实例,而是对于XxxServlet类只有一个实例,如果有AddServlet类,DeleteServlet类,那么他们俩分别只能有一个实例

http协议

实际产生的一个http请求

1) Http 称之为 超文本传输协议

2) Http是无状态的

3) Http请求响应包含两个部分:请求和响应

- 请求:

请求包含三个部分: 1.请求行 ; 2.请求消息头 ; 3.请求主体

1)请求行包含是三个信息: 1. 请求的方式 ; 2.请求的URL ; 3.请求的协议(一般都是HTTP1.1)

2)请求消息头中包含了很多客户端需要告诉服务器的信息,比如:我的浏览器型号、版本、我能接收的内容的类型、我给你发的内容的类型、内容的长度等等

3)请求体,三种情况

get方式,没有请求体,但是有一个queryString,比如?nation=USA&name=jim

post方式,有请求体,form data

json格式,有请求体,request payload

- 响应:

响应也包含三本: 1. 响应行 ; 2.响应头 ; 3.响应体

1)响应行包含三个信息:1.协议 2.响应状态码(200) 3.响应状态(ok)

2)响应头:包含了服务器的信息;服务器发送给浏览器的信息(内容的媒体类型、编码、内容长度等)

3)响应体:响应的实际内容(比如请求add.html页面时,响应的内容就是

会话-session-http是无状态的

物联网淑慧试用:传输层,会话层,表示层,应用层

万物皆对象,会话也是一个类,HttpSession类

http是无状态的

- HTTP 无状态:服务器无法判断这两次请求是同一个客户端发过来的,还是不同的客户端发过来的

- 无状态带来的现实问题:第一次请求是添加商品到购物车,第二次请求是结账;如果这两次请求服务器无法区分是同一个用户的,那么就会导致混乱

- 通过会话跟踪技术来解决无状态的问题。

会话跟踪

客户端请求,服务器响应,这就像谈话一样,这种场景被定义为一个会话

会话跟踪技术

- 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端

- 下次客户端给服务器发请求时,会把sessionID带给服务器,那么服务器就能获取到了,那么服务器就判断这一次请求和上次某次请求是同一个客户端,从而能够区分开客户端

- 常用的API:

request.getSession() -> 获取当前的会话,没有则创建一个新的会话

request.getSession(true) -> 效果和不带参数相同

request.getSession(false) -> 获取当前会话,没有则返回null,不会创建新的

session.getId() -> 获取sessionID

session.isNew() -> 判断当前session是否是新的

session.getMaxInactiveInterval() -> session的非激活间隔时长,默认1800秒

session.setMaxInactiveInterval()

session.invalidate() -> 强制性让会话立即失效

....

session保存作用域

前面说了,会话就是HttpSession类,那么类里边有属性很正常吧

每个客户端实例化了一个HttpSession类,同时呢,也实例化了一个xxxServlet类

- session保存作用域是和具体的某一个session对应的

- 常用的API:

void session.setAttribute(k,v)

Object session.getAttribute(k)

void removeAttribute(k)

服务器端转发和客户端重定向

两种资源跳转的方式

服务器端转发

上面说了,服务器端只会实例化一个servlet,由这个实例来为所有的请求提供服务。如果是这样,从哪里来的服务器端转发呢????

这里说的是两个组件,不是两个servlet;但是处理请求的不都是servlet吗??

服务器内部转发 : request.getRequestDispatcher("...").forward(request,response);

- 一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端是不知道的

- 地址栏没有变化

客户端重定向

服务器的组件让客户端立即向指定的组件发起请求

客户端重定向: response.sendRedirect("....");

- 两次请求响应的过程。客户端肯定知道请求URL有变化

- 地址栏有变化

thymeleaf

thyme:百里香,有吉祥如意的意思

一种视图模板技术,可以实现在html中显示数据库中的真实信息,和springboot完美整合

在静态页面.html文件上加载java内存中的数据这一过程被称之为渲染

thymeleaf就是用来帮助进行渲染的一个技术

渲染的英文是render,在底层源码中设计了一个render方法

为什么使用thymeleaf

背景:假设要将数据库中的数据展示在html页面

我们肯定是不希望将取出的记录一条一条的写到静态页面上,而是说,我取出一百条记录,通过一些操作,可以让他直接显示在页面上

配置thymeleaf的步骤

添加thymeleaf的jar包:有一大堆jar包 注意,新建的依赖文件夹,也就是lib,需要右键->add as library

新建一个Servlet类ViewBaseServlet:这个类继承了HttpServlet类

public class ViewBaseServlet extends HttpServlet {

private TemplateEngine templateEngine;

@Override

public void init() throws ServletException {

// 1.获取ServletContext对象

ServletContext servletContext = this.getServletContext();

// 2.创建Thymeleaf解析器对象

ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

// 3.给解析器对象设置参数

// ①HTML是默认模式,明确设置是为了代码更容易理解

templateResolver.setTemplateMode(TemplateMode.HTML);

// ②设置前缀

String viewPrefix = servletContext.getInitParameter("view-prefix");

templateResolver.setPrefix(viewPrefix);

// ③设置后缀

String viewSuffix = servletContext.getInitParameter("view-suffix");

templateResolver.setSuffix(viewSuffix);

// ④设置缓存过期时间(毫秒)

templateResolver.setCacheTTLMs(60000L);

// ⑤设置是否缓存

templateResolver.setCacheable(true);

// ⑥设置服务器端编码方式

templateResolver.setCharacterEncoding("utf-8");

// 4.创建模板引擎对象

templateEngine = new TemplateEngine();

// 5.给模板引擎对象设置模板解析器

templateEngine.setTemplateResolver(templateResolver);

}

protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {

// 1.设置响应体内容类型和字符集

resp.setContentType("text/html;charset=UTF-8");

// 2.创建WebContext对象

WebContext webContext = new WebContext(req, resp, getServletContext());

// 3.处理模板数据

templateEngine.process(templateName, webContext, resp.getWriter());

}

}

在web.xml文件中添加配置,ViewBaseServlet类中的init方法会使用这两个参数 - 配置前缀 view-prefix - 配置后缀 view-suffix

view-prefix

//前缀就是web这个根目录

/

view-suffix

//后缀就是.html,相当于说去找这个.html文件

.html

使得我们的Servlet继承ViewBaseServlet,在这个例子中,我们设计了一个IndexServlet类

//servlet从3.0版本开始支持使用注解完成在xml文件中的注册

@WebServlet("/index")

public class IndexServlet extends ViewBaseServlet {

@Override

public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {

FruitDAO fruitDAO = new FruitDAOImpl();

List fruitList = fruitDAO.getFruirList();

//保存到session作用域

HttpSession session = request.getSession() ;

session.setAttribute("fruitList",fruitList);

//此处的视图名称是 index

//那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去

//逻辑视图名称 : index

//物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix

//所以真实的视图名称是: / index .html

super.processTemplate("index",request,response);

}

}

根据逻辑视图名称 得到 物理视图名称:说白了就是将一个不带后缀的文件名变成一个相对路径,这个路径必须定位到一个文件 //此处的视图名称是 index //那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去 //逻辑视图名称 : index //物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix //所以真实的视图名称是: / index .html super.processTemplate(“index”,request,response);

使用thymeleaf的标签 th:if , th:unless , th:each , th:text

//为了使用thymeleaf,需要添加这么一个表头

欢迎使用水果库存后台管理系统

名称单价库存操作
对不起,库存为空!
苹果520服务器 JAVAWEB(二)tomcat,ides配置javaweb,servlet  第1张

如何实现大量统一格式的数据在html页面的展示

如果是一般的高级程序语言,我想肯定能脱口而出,就是用循环嘛

在这就懵逼了。html不同于之前遇到的高级程序语言,我们没有看到经典的流程控制相关的语法

但在前面说明使用thymeleaf的背景时,我们提到已经提前获取到sql查询的结果,需要通过一些操作将查询结果一条一条的展示出来

从上面的html代码可以看到,他妈的,居然用的是循环,意料之外又在情理之中

th:each="fruit : ${session.fruitList}"

session.fruitList,我们将装查询结果的容器储存到会话中 fruit,每次从容器中取出一条记录储存到变量fruit

回顾

review:

1. post提交方式下的设置编码,防止中文乱码

request.setCharacterEncoding("utf-8");

get提交方式,tomcat8开始,编码不需要设置

tomcat8之前,get方式设置比较麻烦:

String fname = request.getParameter("fname");

byte[] bytes = fname.getBytes("iso-8859-1");

fname = new String(bytes,"UTF-8");

2. Servlet继承关系以及生命周期

1) Servlet接口 : init() , service() , destroy()

GenericServlet抽象子类: abstract service();

HttpServlet抽象子类:实现了service方法,在service方法内部通过request.getMethod()来判断请求的方式,

然后根据请求的方式去调用内部的do方法。每一个do方法进行了简单实现,主要是如果请求方式不符合,则报405错误。

目的是让我们的Servlet子类去重写对应的方法(如果重写的不对,则使用父类的405错误实现)

2) 生命周期:实例化、初始化、服务、销毁

- Tomcat负责维护Servlet实例的生命周期

- 每个Servlet在Tomcat容器中只有一个实例,它是线程不安全的

- Servlet的启动时机:

- Servlet3.0开始支持注解: @WebServlet

3. HTTP协议:

1) 由 Request 和 Response 两部分组成

2) 请求包含了三部分:请求行、请求消息头、请求主体: 普通的get方式请求-query string;post方式- form data ; json格式 - request payload

3) 响应包含了三部分:响应行、响应消息头、响应主体

4. HttpSession

1) HttpSession :表示 会话

2) 为什么需要HttpSession , 原因是因为 Http协议是无状态的

3) Session保存作用域 :一次会话范围都有效 ; void session.setAttribute(k,v) ,Object session.getAttribute(k)

4) 其他的API: session.getId() , session.isNew() , session.getCreationTime() , session.invalidate() 等等

5. 服务器端转发和客户端重定向

1) 服务器端转发 : request.getRequestDispatcher("index.html").forward(request,response);

2) 客户端重定向: response.sendRedirect("index.html");

6. thymeleaf的部分标签

1) 使用步骤: 添加jar , 新建ViewBaseServlet(有两个方法) , 配置两个 : view-prefix , view-suffix

2) 部分标签: , , ,

servlet保存作用域

从我最开始学习会话的时候,我就没明白这个保存作用域是什么意思。从代码层面来看,有一个HttpSession类,这个类的实例可以存储其他类型的实例,感觉上HttpSession类有点像是一个容器

但你要说这是个作用域,听起来就很奇怪,很反直觉

作用域解释

于是,我搜索到了这样一样说法, 几乎所有web应用容器都提供了四种类似Map的结构:application session request page,通过向着这四个对象放入数据,从而实现数据的共享

这些说法真的是越来越抽象,不说人话啊!!! web容器:就是一个程序。特指服务器程序,比如说tomcat也可以叫tomcat容器

因此,上面那个说法翻译一下就是,tomcat服务器提供了四种类似于哈希表的类: application:整个应用 对应servlet中ServletContext类

session:会话    对应servlet中HttpSession类

request:一次请求  对应servlet中的HttpServletRequest类

page:当前页面 对应servlet中的PageContext类

pageContext:当前页面有效 (页面跳转后无效)

request:同一次请求有效(请求转发后有效;重定向后无效)

session:同一次会话有效(关闭/切换浏览器后无效 ; 默认30分钟有效期)

appliation:全局有效 (切换浏览器 仍然有效) 服务器开着就有效,切换客户端

结论:所以说,作用域指的是,web容器提供的四个类Map容器类实例的作用范围

HttpServletRequest容器

HttpServletRequest实例的作用范围在一次请求之内,因此,上面的示例中,第二次请求是无法取到数据的

模拟不同请求:可以使用客户端重定向

HttpSession容器

模拟不同会话:

ServletContext容器

模拟不同的客户端:换一台IP地址不同的设备或者直接换一个浏览器

绝对路径和相对路径

href:hyper reference超文本引用

区分超链接和超文本引用

超链接:将网页的选中部分作为跳转到另一个网页的入口,通过点击实现跳转 超文本引用:用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本

从实际使用来看,超链接需要用户主动点击才能跳转,超文本引用写好以后,在运行时会自动引用链接的内容,用户不能主动点击

好文推荐

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: