JavaWeb杂记

编程入门 行业动态 更新时间:2024-10-25 16:23:56

JavaWeb<a href=https://www.elefans.com/category/jswz/34/1766767.html style=杂记"/>

JavaWeb杂记

JavaWeb

1、基本概念

1.1、前言

web开发

web:网页的意思:www.baidu

静态web

比如:html,css

提供给所有人看的,数据始终不会发生变化!

动态web

比如: 淘宝、B站,几乎所有的网站

提供给所有人看的,数据始终会发生变化(如B站的推荐),每个人在不同的时间,不同的地点看到的信息各不相同!

动态web的技术栈一般有Servlet/JSP,ASP,PHP

在Java中,动态web资源开发的技术统称为JavaWeb。

1.2、web应用程序

web应用程序:可以提供浏览器访问的程序;
a.html、b.html…多个web资源,这些web资源可以被外界访问,对外界提供服务。
我们能访问的任何一个页面或者资源(如:种子),都存在以这个世界上的某一个角落的计算机上。
URL:统一资源定位符
这个统一的web资源会被放在同一个文件夹下,web应用程序–(依赖)–>Tomcat:服务器
一个web应用由多部分组成(静态web,动态web)
html,css,js
jsp,servlet
java程序
jar包
配置文件(.properties)

web应用程序编写完成之后,若想提供给外界访问:需要一个服务器来统一管理;

1.3、静态web

.htm,.html 这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取。
静态web存在的缺点:
Web页面无法动态更新,所有用户看到的都是同一个页面
* 轮播图,点击特效:伪动态
* JavaScript[实际开发中用得最多]
* VBScript
无法和数据库交互(数据无法持久化,数据无法交互)

1.4、动态web

页面会动态展示:“Web页面展示的额效果因人而异”。
缺点:
假如服务器的动态web资源出现了错误,我们需要需要重写编写我们的“后台程序”,重新发布;
要停机维护。
Web页面可以动态更新,所有用户看到的都不是同一个页面
可以和数据库交互(数据持久化:注册,商品信息,用户信息(等可以往里存)…)

2、web服务器

2.1、技术讲解

ASP
介绍

ASP 是一项微软公司的技术,国内最早流行的动态web技术就是ASP!它在HTML中嵌入了VB的脚本,ASP + COM。

ASP即Active Server Pages,是Microsoft公司开发的服务器端脚本环境,可用来创建动态交互式网页并建立强大的web应用程序。

优点

简单、好用、开发效率高、速度快。

缺点

在ASP开发中,基本一个页面都有几千行的业务代码,页面及其混乱;维护成本高!

PHP
介绍

PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。PHP 是免费的,并且使用非常广泛。

优点

PHP开发速度很快,功能很强大,跨平台,代码很简单(70%的网站,WP去做的)。

WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。

缺点

无法承载大访问量的情况(局限性)

JSP/Servlet
介绍

JSP全称Java Server Pages,是一种动态网页开发技术。

Servlet 是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。

实际上jsp的本质还是servlet

2.2、web服务器

服务器是一种被动的操作,用来处理一些用户的请求和给用户一些相应信息;

IIS

IIS是微软公司的Web服务器。主要支持ASP语言环境。

Tomcat

Tomcat是Apache软件基金会的jakarta项目中的一个核心项目,最新的Servlet和JSP规范总能在Tomcat中得到体现,是目前比较流行的Web应用服务器。

Tomcat服务器是一个免费的开放源代码的Web应用程序,属于轻量级应用服务器。

可以配置启动的端口号
  • tomcat的默认端口号为:8080
  • mysql:3306
  • http:80
  • https:443
可以配置主机的名称
  • 默认的主机名为:localhost --> 127.0.0.1
  • 默认的网站应用存放的位置为:webapps文件夹
高难度面试题:
请您谈一谈网站是如何进行访问的?
  1. 输入一个域名,然后回车
  2. 检查本机的C:\Windows\System32\drivers\etc\hosts配置文件夹有没有这个域名映射
  • 有:直接返回对应的ip地址,有就直接访问
  • 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到

http://localhost:8080/docs/ tomcat文档页面
http://localhost:8080/examples/ tomcat各种例子(点击Source查看源码),建议参考

3、发布一个web网站

不会就先模仿

将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问

网站应该有的结构:

--webapps:Tomcat服务器的web目录-study(自己写的一个网站的目录名)-WEB-INF:-classes:放java程序-lib:web应用所依赖的jar包-web.xml:网站的配置文件-index.html:默认的首页-static:-css-style.css-js-img-...

4、Http

4.1、什么是Http

Http:超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。

  • 文本:html,字符串,…
  • 超文本:图片,音乐,视频,定位,地图,…

HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。

4.2、两个时代

http1.0

http/1.0:客户端可以与web服务器连接后,只能获得一个web资源,否则断开连接。

http2.0

http/1.1:客户端可以与web服务器连接后,可以获得多个web资源。

4.3、Http请求

以百度为例:

Request URL: /	# 请求地址
Request Method: GET	# 请求方法(get/post)
Status Code: 200 OK	# 状态码
Remote(远程) Address: 183.232.231.174:443
Referrer Policy: unsafe-url	Referrer的策略

unsafe-url策略:任意情况下,都发送当前页的全部地址到 Referrer,最宽松和不安全的策略。

1、请求行

请求行中的方式:GET
请求方式:Get,Post,HEAD,DELETE,PUT,TRACT,…
get:请求能够携带的参数比较少,大小有限制;会在浏览器的URL地址栏显示数据内容,不安全,但高效
post:请求能够携带的参数没有限制,大小没有有限制;不会在浏览器的URL地址栏显示数据内容,安全,但不高效

2、请求头/消息头
  • Accept:告诉浏览器,它所支持的数据类型
  • Accept-Encoding:支持哪种编码格式
  • Accept-Language:告诉浏览器,它的语言环境
  • Cache-Control:缓存控制
  • Connection:告诉浏览器,是断开还是保持连接
  • Host: 主机​

4.4、Http响应

服务器–响应给(Response)–>客户端

以百度为例:

Response Headers
Bdpagetype: 1
Bdqid: 0xd6af2b47000eb155
Cache-Control: private	# 缓存控制
Connection: keep-alive  # 连接:keep-alive保持连接
Content-Encoding: gzip	# 编码
Content-Type: text/html;charset=utf-8	# 类型
Date: Wed, 01 Sep 2021 14:30:11 GMT
Expires: Wed, 01 Sep 2021 14:30:11 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=19; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=34442_34496_31253_33848_34092_34106_26350_34425; path=/; domain=.baidu
Strict-Transport-Security: max-age=172800
Traceid: 1630506611054653569015469630828984578389
Transfer-Encoding: chunked
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1
1、响应体
  • Accept:告诉浏览器,它所支持的数据类型
  • Accept-Encoding:支持哪种编码格式
  • Accept-Language:告诉浏览器,它的语言环境
  • Cache-Control:缓存控制
  • Connection:告诉浏览器,是断开还是保持连接
  • Host: 主机
  • Reflush:告诉客户端,多久刷新一次
  • Location:让网页重新定位
2、响应状态码(重点)
  • 200:请求响应成功 200

  • 3xx:请求重定向位置去

  • 4xx:找不到资源

    • 404:资源不存在
  • 5xx:服务器代码错误 500 502(网关错误)

常见面试题

当您的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?

5、Maven

Maven(Java包管理工具)。

为什么要学习Maven这个技术?

  1. 在JavaWeb开发中,需要使用大量的jar包,这些jar包需要我们手动导入;
  2. 如何能够让一个东西自动帮我导入和配置这些jar包。
  3. 由此,Maven诞生了!

Maven是一个采用纯Java编写的开源项目管理工具。Maven采用了一种被称之为**project object model (POM)**概念来管理项目,所有的项目配置信息都被定义在一个叫做POM.xml的文件中,通过该文件,Maven可以管理项目的整个声明周期,包括编译,构建,测试,发布,报告等等。目前Apache下绝大多数项目都已经采用Maven进行管理。而Maven本身还支持多种插件,可以方便更灵活的控制项目。一句话:Maven是一个项目管理和构建工具,主要做编译、测试、报告、打包、部署等操作完成项目的构建。Maven不仅是构建工具,还是一个依赖管理工具和项目管理工具,它提供了中央仓库,能帮我自动下载构件。

5.1、Maven项目架构管理工具

我们目前用它来就是方便导入jar包的。Maven核心思想:约定大于配置。

有约束,不要去违反,Maven会要求你如何去编写我们的java代码,必须按照这个规范!

5.2、下载安装Maven

官网:/

下载:.cgi

下载完成后解压即可

5.3、配置环境变量

在我们的系统环境变量中,按如下配置进行配置:

  • M2_HOME Maven:目录下的bin目录
  • MAVEN_HOME :Maven的目录
  • 在系统的Path中配置 %MAVEN_HOME%\bin

测试Maven是否安装成功,保证必须配置完毕:cmd下键入mvn -version命令。

5.4、配置镜像

配置镜像(镜像(Mirroring)是一种文件存储形式,是冗余的一种类型,一个磁盘上的数据在另一个磁盘上存在一个完全相同的副本即为镜像。),使用默认仓库下载jar包会比较慢,所以配置一个阿里云镜像

作用:加速我们的下载,国内建议使用阿里云镜像。

5.5、本地仓库

建立一个仓库:localRepository

<localRepository>E:\apache-maven-3.8.2\maven-repo</localRepository>

5.6、在IDEA中使用Maven

  1. 启动IDEA
  2. 创建一个MavenWeb项目(使用模板)
  3. 等待初始化完毕
  4. 查看maven仓库中多了什么东西
  5. IDEA中的maven设置
  6. 到这里为止,Maven在IDEA中的配置和使用就OK了!

5.7、创建一个普通的Maven项目(干净的,不勾选模板)

5.8、标记文件夹功能

5.9、在IDEA中配置Tomcat

1.Edit Configurations
2.点击+号,选择Tomcat(local)
3.解决警告问题

为什么有这个问题:我们访问一个网站,需要指定一个文件夹的名字。

4.启动tomcat

5.10、pom文件

pom.xml是Maven的核心配置文件

5.11、IDEA操作

maven由于是约定大于配置,所以可能遇到我们写的配置文件,无法被导出或者生效的问题,解决方法:

在pom.xml文件中,通过<build>中配置<resources>

<!--在build中配置resources , 来防止我们资源导出失败的问题-->
<build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes></resource></resources>
</build>

5.12、IDEA中Maven项目的目录树

5.13、解决遇到的问题

1.Maven与JDK版本不兼容,导致无法导入东西
2.Tomcat闪退
3.IDEA中每次都要重复配置Maven 在IDEA的全局默认配置中去配置
4.Maven项目中Tomcat无法配置
5.Maven默认web项目中的web.xml版本问题
6.替换成IDEA中tomcat版本((IDEA生成的中的web.xml))和webapps(中的web.xml)一致
7.Maven仓库的使用

Maven公共仓库地址:/

6、Servlet

6.1、Servlet简介

Servlet就是SUN公司开发动态web的一门技术。SUN公司在这些API中提供了一个接口叫做:Servlet

如果你想开发一个Servlet程序,只需要完成两个小步骤:

1、编写一个类,继承Servlet接口

2、把开发好的Java类部署到web服务器中

把实现了Servlet接口的Java程序叫做:Servlet

6.2、HelloServlet

Servlet接口在SUN公司有两个默认的实现类:HttpServlet和GenericServlet

  1. 构建一个Maven项目,删除里面的src目录,以后我们的学习就在这个项目里面建立Moudel
  2. 关于Maven父子工程的理解:

父项目中有:

<modules><module>servlet-01</module>
</modules>

父项目中的java子项目可以直接使用,类似于:son extends father

  1. Maven环境优化

    1. 修改web.xml文件为最新的
    2. 将maven的结构构建搭配完整
  2. 编写一个Servlet程序

    1. 编写一个普通类
    2. 这个普通类去继承Servlet接口,这里我们直接继承HttpServlet
  3. 编写Servlet的映射

    为什么要写映射?

    我们写的是Java程序,但是要通过浏览器去访问,而浏览器需要连接web服务器,所以需要在web服务中(在webapps目录下的web.xml文件中)注册我们写的Servlet,还需要给它写一个浏览器能够访问的路径。

  4. 配置Tomcat
    注意:需要配置项目发布的路径

  5. 启动测试

6.3、Servlet原理

Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:

6.4、Mapping问题

  1. 一个Servlet请求可以指定一个映射 /hello
  2. 一个Servlet请求可以指定多个映射 /hello/test
  3. 一个Servlet请求可以指定通用映射 /hello/
  4. 默认请求路径 /
  5. 指定一些后缀或者前缀等 .do
  6. 优先级问题

指定了固有的映射优先级最高(/hello),如果找不到就会走默认的处理请求(/)

6.5、ServletContext

web容器启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表当前的web应用

1、共享数据

在这个Servlet中保存的数据可以在另一个Servlet中拿到。

1.创建一个放置数据的Servlet类
context.setAttribute("username",username);// 将一个数据存在了ServletContext中;名字为:"username",值为:username
2.再创建一个读取数据的Servlet类
String username = (String) context.getAttribute("username");
resp.getWriter().print("名字:" + username);
3.配置web.xml
4.测试访问结果
2、获取(web.xml中的)初始化参数

在web.xml配置初始化参数,在Servlet类中获取初始化参数

<!--配置一些web应用初始化参数-->
<context-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/jbpowernode</param-value>
</context-param>
3、请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入了ServletDemo04");ServletContext context = this.getServletContext();/*RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gP");//"/gP"为转发的请求路径requestDispatcher.forward(req,resp);//调用forward方法实现转发*/context.getRequestDispatcher("/gP").forward(req,resp);
}
RequestDispatcher接口的include()方法与forward()方法的区别:
  • RequestDispatcher接口所定义的forward()方法可以将HTTP请求转送给其他Web资源(例如Servlet、JSP或HTML)进行处理,并产生HTTP回应。

  • RequestDispatcher接口的include()方法与forward()方法非常类似,唯一的不同在于:利用include()方法将HTTP请求转送给其他Servlet后,被调用的Servlet虽然可以处理这个HTTP请求,但是最后的主导权仍然是在原来的Servlet。

  • RequestDispatcher是一个Web资源的包装器,可以用来把当前request传递到该资源,或者把新的资源包括到当前响应中。

由于jsp:include只能指定固定的jsp文件名,不能动态指定jsp文件名。我们需要把jsp:include翻译为Java code - RequestDispatcher.include();

4、读取资源文件
Properties

在java目录下新建properties

在resources目录下新建properties

发现都被打包到了同一个路径下:classes,我们俗称这个路径为classpath

6.6、HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletRequest对象。

1、简单分类

负责向浏览器发送数据的方法:

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

负责向浏览器发送响应头的方法:

void setCharacterEncoding(String var1);void setContentLength(int var1);void setContentLengthLong(long var1);void setContentType(String var1);void setDateHeader(String var1, long var2);void addDateHeader(String var1, long var2);void setHeader(String var1, String var2);void addHeader(String var1, String var2);void setIntHeader(String var1, int var2);void addIntHeader(String var1, int var2);
响应的状态码
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2、常见应用
1.向浏览器输出消息
2.下载文件
1.获取下载文件的路径2.下载的文件名是什么3.设置想办法让浏览器能够支持下载我们需要的东西4.获取下载文件的输出流5.创建缓冲区6.获取OutputStream对象7.将FileOutputStream流写到buffer缓冲区8.使用OutputStream将缓冲区的数据输出到客户端
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/* 下载文件*///              1.获取下载文件的路径String realPath = "E:\\JavaWeb_Servlet\\Response\\src\\main\\resources\\test.JPG";System.out.println("获取的下载文件的路径:" + realPath);//          2.下载的文件名是什么String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);//极其精妙的方法,注意!//          3.设置想办法让浏览器能够支持下载我们需要的东西,中文文件名URLEncoder.encode编码,否则可能乱码resp.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));//          4.获取下载文件的输出流FileInputStream in = new FileInputStream(realPath);//          5.创建缓冲区int len = 0;byte[] buffer = new byte[1024];//          6.获取OutputStream对象ServletOutputStream out = resp.getOutputStream();//          7.将FileOutputStream流写到buffer缓冲区//              8.使用OutputStream将缓冲区的数据输出到客户端while ((len = in.read(buffer)) > 0) {out.write(buffer,0,len);}//              9.关闭流in.close();out.close();
}@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);
}
3、验证码功能

验证怎么来的?

前端实现
<template>
<divclass="ValidCode disabled-select":style="`width:${width}; height:${height}`"@click="refreshCode"><spanv-for="(item, index) in codeList":key="index":style="getStyle(item)">{{ item.code }}</span></div>
</template><script>export default {name: 'ValidCode',model: {prop: 'value',event: 'input',},props: {width: {type: String,default: '100px',},height: {type: String,default: '40px',},length: {type: Number,default: 4,},refresh: {type: Number,},},data() {return {codeList: [],}},watch: {refresh() {this.createdCode()},},mounted() {this.createdCode()},methods: {refreshCode() {this.createdCode()},createdCode() {const len = this.lengthconst codeList = []const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789'const charsLen = chars.length// 生成for (let i = 0; i < len; i++) {const rgb = [Math.round(Math.random() * 220),Math.round(Math.random() * 240),Math.round(Math.random() * 200),]codeList.push({code: chars.charAt(Math.floor(Math.random() * charsLen)),color: `rgb(${rgb})`,fontSize: `${10 + (+[Math.floor(Math.random() * 10)] + 6)}px`,padding: `${[Math.floor(Math.random() * 10)]}px`,transform: `rotate(${Math.floor(Math.random() * 90) - Math.floor(Math.random() * 90)}deg)`,})}// 指向this.codeList = codeList// 将当前数据派发出去// console.log(codeList.map(item => item.code).join(''))this.$emit('input', codeList.map((item) => item.code).join(''))},getStyle(data) {return `color: ${data.color}; font-size: ${data.fontSize}; padding: ${data.padding}; transform: ${data.transform}`},},}
</script><style scoped>.ValidCode {display: flex;justify-content: center;align-items: center;cursor: pointer;}.ValidCode span {display: inline-block;}
</style>
后端实现

需要用到java的图片类,生成一个图片

public class ImageServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//如何让浏览器3秒自动刷新一次resp.setHeader("refresh","3");//在内存中创建一个图片BufferedImage image = new BufferedImage(50, 20, BufferedImage.TYPE_INT_RGB);//得到图片Graphics2D g = (Graphics2D) image.getGraphics(); //笔//设置图片背景颜色g.setColor(Color.white);g.fillRect(0,0,50,20);//给图片写数据g.setColor(Color.BLUE);g.setFont(new Font(null,Font.BOLD,20));g.drawString(makeNum(),0,20);//告诉浏览器,这个请求用图片的方式打开resp.setContentType("image/jpg");//网站存在缓存,不让浏览器缓存resp.setDateHeader("expires",-1);resp.setHeader("Cache.Control","no-cache");resp.setHeader("Pragma","no-cache");//把图片写给浏览器ImageIO.write(image, "jpg", resp.getOutputStream());}//生成随机数private String makeNum(){Random random = new Random();String num = random.nextInt(9999) + "";StringBuffer sb = new StringBuffer();for (int i = 0; i < 4-num.length(); i++) {sb.append("0"); // 用0填充不满4位的数,保证最终返回的num一定是4位}num = sb.toString() + num;return num;}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
4、实现重定向

一个web资源(B)收到客户端(A)请求后,它会通知客户端(A)去访问另一个web资源©,这个过程叫重定向。

创建场景:

用户登录

void sendRedirect(String var1) throws IOException;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/**//*resp.setHeader("Location","/r/img");resp.setStatus(SC_MOVED_TEMPORARILY);//响应状态码302的常量*///重定向一个页面resp.sendRedirect("/r/img");//重定向}
5.面试题:请您聊一聊重定向和转发的区别:
相同点

页面都会实现跳转

不同点
  • 请求转发的时候,url不会发生变化

  • 重定向的时候,url地址栏会发生变化

public class RequestTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//System.out.println("进入这个请求了!");//控制台出现这个,说明进入了这个请求//处理请求,需要使用Request对象String username = req.getParameter("username");String password = req.getParameter("password");System.out.println(username + ":" + password);//重定向 eg:resp.sendRedirect("/r/img");//重定向//重定向一定要注意路径问题,否则会出现404;resp.sendRedirect("/r/success.jsp");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
<%--jsp文件头设置了编码格式--%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%--顺便设置--%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<html><body><h2>Hello World!</h2><%--这里的提交的路径,需要寻找到项目的路径--%><%--${pageContext.request.contextPath}代表当前的项目--%><form action="${pageContext.request.contextPath}/login" method="get" >用户名:<input type="text" name="username" > <br>密码:<input type="password" name="password" > <br><input type="submit"></form></body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><%--顺便设置--%><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>LoginSuccess</title></head><body><h1>Success!</h1></body>
</html>

请求和响应是一一对应的关系。

6.7、HttpServletRequest

  • 如果想要获取客户端请求过来的参数:HttpServletRequest

  • 如果想要给客户端响应一些信息:HttpServletResponse

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息都会被封装到HttpServletRequest,提供通过这个HttpServletRequest对象的方法,获得客户端的所有信息。

1、获取前端传递的参数

HttpServletRequest.getParameter(参数名),可以获得form表单中传递的参数,或ajax或url中传递过来的参数,如果通过form表单传递,需要form表单中的input框的 name属性的值和传递给getParameter的参数名保持一致,大小写也要一致。

@Controller
@RequestMapping("/")
public class UserController {private UserService us;@ResponseBody@RequestMapping("loginForm")public void login(HttpServletRequest req, HttpServletResponse rsp) throws IOException{String userName=req.getParameter("username").trim();//trim() 删除字符串前后的空格String passWord=req.getParameter("password").trim();String userInfo = us.check(userName, passWord);String[] result = new String[1];//从返回值中取出用户名存到result中if (userInfo != "false") {result[0]= "true";}else {result[0]= "false";}User user = new User();user.setUserName(userName);req.getSession().setAttribute("user",user);//增加回显用户名req.getSession().setAttribute("sessionAdminUserName",userName);rsp.setContentType("application/json");rsp.setCharacterEncoding("utf-8");// 首先把字符串转成 JSONArray对象JSONArray jsonArray = JSONArray.fromObject(result);JSONObject jsobjcet = new JSONObject();jsobjcet.put("data", jsonArray); try {rsp.getWriter().write(jsobjcet.toString());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
}
2、请求转发
public class LoginServlet  extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//HttpServletRequest对象防止中文乱码问题之解决方法req.setCharacterEncoding("utf-8");//HttpServletResponse对象防止中文乱码问题之解决方法一resp.setCharacterEncoding("utf-8");//设置HttpServletResponse使用utf-8编码resp.setHeader("Content-Type","text/html;charset=utf-8");//通知浏览器使用utf-8编码//解决方法二//resp.setContentType("text/html;charset=utf-8");//包含方法一的两个功能//首先获取前端传递的参数String username = req.getParameter("username");//获取用户名信息String password = req.getParameter("password");//获取密码信息String[] hobbys= req.getParameterValues("hobbys");//获取多选框信息System.out.println("================================");//后台接收中文乱码问题System.out.println(username);System.out.println(password);/*Arrays.toString()作用:方便地输出数组。这个方法是是用来将数组转换成String类型输出的,入参可以是long,float,double,int,boolean,byte,object型的数组。*/System.out.println(Arrays.toString(hobbys));System.out.println("================================");//通过请求转发//这里的 / 代表当前的web应用System.out.println("路径" + req.getContextPath());req.getRequestDispatcher("/success.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
3、请求转发和重定向的区别
相同点

页面都会实现跳转

不同点
  • 请求转发的时候,url不会发生变化 307

  • 重定向的时候,url地址栏会发生变化 302

7、Session和Cookie

由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session。

  • Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
  • Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。

7.1、会话

会话:用户打开了一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器。这个过程称之为会话。

有状态会话:一个学生来过教室,当他下一次再来教室,我们会知道这个同学曾经来过,这种称之为有状态会话。

一个网站,怎么证明你来过?
  1. 服务端给客户端一个信件,客户端下一次访问服务端带上信件就可以了; cookie
  2. 服务器登记你来过了,下一次你来的时候,我匹配你;session

7.2、保存会话的两种技术

cookie
  • cookie是一种客户端技术 (响应,请求)。大多数的应用都是用 Cookie 来实现Session跟踪的。

  • Cookie: —>常见的应用场景是:自动登录的

session
  • session是一种服务器技术,利用这个技术可以保存用户的会话信息。我们可以把信息或者数据放在Session中。Session是保存在服务端的,有一个唯一标识。

常见场景:网站登录之后,你下一次不用再登录了,第二次访问就自动帮你信息给填上了,能够方便用户。

7.3、Cookie

  1. 从请求中拿到Cookie信息

  2. 服务器响应给客户端Cookie

//获得Cookie
Cookie[] cookies = req.getCookies();//这里返回数组,说明Cookie可能存在多个
cookie.getName();//获得cookie中的键key
cookie.getValue();//获得cookie中的值value
//服务器给客户端响应一个Cookie
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis() + "");
//设置cookie的有效期
cookie.setMaxAge(24*60*60);//一天
resp.addCookie(cookie);//响应给客户端一个cookie

cookie一般会保存在本地的用户目录下AppData文件夹中

一个网站cookie是否存在上限。细节问题

  • 一个Cookie只能保存一个信息;(Cookie(String name, String value));
  • 一个web站点可以给浏览器发送多个cookie,每个站点最多存放20个cookie;
  • Cookie大小有限制,限制为4KB;
  • 上限大概为300(浏览器上限)
删除Cookie
  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效期时间为0;// 这种效率较高
中文数据怎么传递?
  • new String(byte[],"UTF-8")是新建了一个UTF-8编码的字符串;

  • URLEncoder.encode(“”,“UTF-8”)不只是按UTF-8编码生成一个字符串,还将其中的不安全字符做了转码处理。

推荐用URLEncoder。

编码
URLEncoder.encode("希德","utf-8");// 编码
解码
URLDecoder.decode(cookie.getValue(),"utf-8");// 解码

7.4、Session(重点)

什么是Session?

服务器会给每一个用户(浏览器)创建一个Session对象;

一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在;

场景:用户登录之后,整个网站它都可以访问。—> 保存用户的信息;保存购物车的信息(一般用Session)

Session和Cookie的区别:
  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)

  • Session是把用户的数据写到用户独占的Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)

  • Session对象由服务器创建;Session是服务器端的

使用场景:
  • 保存一个登录用户的信息;

  • 购物车信息;

  • 在整个网站中经常使用的数据,将它保存在Session中(就不用每次去get了);

使用Session
//存Session
public class SessionDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");//得到Session对象HttpSession session = req.getSession();//往Session存东西/*将数据存在了ServletContext中,最好不要用,使用Session存放即可!ServletContext context = this.getServletContext();//Servlet上下文context.setAttribute("username",username);*/session.setAttribute("Person",new Person("莱维",707));//获取Session的idString sessionId = session.getId();//判断Session是不是新创建if(session.isNew()){//如果Session是新创建的,响应相关信息//获取响应的输出流 注意:write是往外写;print是打印resp.getWriter().write("session创建成功! " + " ID:" + sessionId);}else {resp.getWriter().write("session已经在服务器中存在了! "+ " ID:" + sessionId);}//Session创建的时候做了什么事情?/*Cookie cookie = new Cookie("JSESSIONID",sessionId);//jsessionid就是用来判断当前用户对应于哪个session//把cookie响应回去resp.addCookie(cookie);*/}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
//取Session
public class SessionDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//解决乱码问题req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");//得到Session对象HttpSession session = req.getSession();//从session中取东西Person person = (Person) session.getAttribute("Person");System.out.println(person.toString());}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
//注销Session
public class SessionDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获得SessionHttpSession session = req.getSession();//取消Session存的东西session.removeAttribute("Person");//手动注销session,跟关闭浏览器是一样的效果session.invalidate();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
会话自动过期:在web.xml中配置
<!--设置Session的默认失效时间-->
<session-config><!--15分钟后自动失效,以分钟为单位--><session-timeout>15</session-timeout>
</session-config>

8、JSP

8.1、JSP —> 前端知识(HTML + CSS + JS)

JSP是Java Server Page(Java服务器端页面)的缩写,是一种Web服务设计标准,用于开发动态Web。JSP以Java技术为基础,JSP是基于Java Servlet以及整个Java体系的Web开发技术,利用这一技术可以建立安全,跨平台的先进动态网站。具有动态页面和静态页面分离,能够脱离平台的束缚以及编译后运行等优点。

浏览器可以直接运行html页面,但是不能直接运行jsp页面,jsp是需要在拥有jsp引擎的服务器中运行的,例如tomcat服务器。

最大特点:

  • 写JSP就像写HTML

  • JSP和HTML的区别

    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入Java代码,为用户提供动态数据

8.2、JSP和Java Servlet的关系

jsp页面第一次被访问的时候,会被tomcat服务器编译成一个java类,这个java默认继承HttpJspBase类,而HttpJspBase类是HttpServlet的子类。

我们编写的jsp页面最终就被tomcat服务器编译成了一个HttpServlet的子类,所以说jsp本身就是一个servlet。

简单的讲,一个jsp页面就是一个servlet。
Java Servlet
public final class test_jsp extends org.apache.jasper.runtime.HttpJspBaseimplements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {private static final javax.servlet.jsp.JspFactory _jspxFactory =javax.servlet.jsp.JspFactory.getDefaultFactory();private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;private static final java.util.Set<java.lang.String> _jspx_imports_packages;private static final java.util.Set<java.lang.String> _jspx_imports_classes;static {_jspx_imports_packages = new java.util.HashSet<>();_jspx_imports_packages.add("javax.servlet");_jspx_imports_packages.add("javax.servlet.http");_jspx_imports_packages.add("javax.servlet.jsp");_jspx_imports_classes = null;}private volatile javax.el.ExpressionFactory _el_expressionfactory;private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;public java.util.Map<java.lang.String,java.lang.Long> getDependants() {return _jspx_dependants;}public java.util.Set<java.lang.String> getPackageImports() {return _jspx_imports_packages;}public java.util.Set<java.lang.String> getClassImports() {return _jspx_imports_classes;}public javax.el.ExpressionFactory _jsp_getExpressionFactory() {if (_el_expressionfactory == null) {synchronized (this) {if (_el_expressionfactory == null) {_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();}}}return _el_expressionfactory;}public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {if (_jsp_instancemanager == null) {synchronized (this) {if (_jsp_instancemanager == null) {_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());}}}return _jsp_instancemanager;}public void _jspInit() {}public void _jspDestroy() {}public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)throws java.io.IOException, javax.servlet.ServletException {final java.lang.String _jspx_method = request.getMethod();if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");return;}final javax.servlet.jsp.PageContext pageContext;javax.servlet.http.HttpSession session = null;final javax.servlet.ServletContext application;final javax.servlet.ServletConfig config;javax.servlet.jsp.JspWriter out = null;final java.lang.Object page = this;javax.servlet.jsp.JspWriter _jspx_out = null;javax.servlet.jsp.PageContext _jspx_page_context = null;try {response.setContentType("text/html");pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);_jspx_page_context = pageContext;application = pageContext.getServletContext();config = pageContext.getServletConfig();session = pageContext.getSession();out = pageContext.getOut();_jspx_out = out;//使用io流把生成的html页面代码一行一行写回给浏览器的out.write("<html>\r\n");out.write("<body>\r\n");out.write("<h2>Hello World!</h2>\r\n");out.write("</body>\r\n");out.write("</html>\r\n");} catch (java.lang.Throwable t) {if (!(t instanceof javax.servlet.jsp.SkipPageException)){out = _jspx_out;if (out != null && out.getBufferSize() != 0)try {if (response.isCommitted()) {out.flush();} else {out.clearBuffer();}} catch (java.io.IOException e) {}if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);else throw new ServletException(t);}} finally {_jspxFactory.releasePageContext(_jspx_page_context);}}
}
JSP
<html><body><h2>Hello World!</h2></body>
</html>

Java Servlet是Java语言的一部分,提供了用于服务器编程的API。Java Servlet就是编写在服务器端创建对象的java类,习惯上称为Servlet类,Servlet类的对象习惯上称为一个servlet。

Java Servlet的最大缺点是不能有效管理页面的逻辑部分和页面的输出部分,导致Servlet类的代码非常混乱,单独用Java Servlet来管理网站变成一件很困难的事情。

为了克服Java Servlet的缺点,SUN公司用Java Servlet作为基础,推出了Java Server Page。JSP技术屏蔽了servlet创建的过程。JSP只是Java Servlet技术的一个成功应用。

JSP本质上就是一个Servlet(只不过封装了许多东西)
//初始化
public void _jspInit() {//JSP容器第一次装载jsp文件时调用一次
}
//销毁
public void _jspDestroy() {//jsp文件被修改时,JSP容器会销毁旧的jsp文件对应的对象,重新装载一次更新后的jsp文件的内容(只调用一次)。
}
//JSPService服务
public void _jspService(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {
}// 每当服务器接收到对该jsp的请求,都需要调用一次该方法一次。
1.判断请求
2.内置了一些对象
final javax.servlet.jsp.PageContext pageContext;//页面上下文
javax.servlet.http.HttpSession session = null;
//session对象
final javax.servlet.ServletContext application;//applicationContext
final javax.servlet.ServletConfig config;//config配置
javax.servlet.jsp.JspWriter out = null;//out输出对象
final java.lang.Object page = this;//page:当前页
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
HttpServletRequest request;//请求
HttpServletResponse response;//响应
3.输出页面前增加的代码
	  response.setContentType("text/html");//设置文本响应的页面类型pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true);_jspx_page_context = pageContext;application = pageContext.getServletContext();config = pageContext.getServletConfig();session = pageContext.getSession();out = pageContext.getOut();_jspx_out = out;
4.以上的这些对象我们可以直接在JSP页面中使用

8.3、JSP原理

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

当服务器上的一个JSP页面被第一次请求执行时,服务器上的JSP引擎首先将JSP页面文转译为一个Java文件,并编译这个Java文件生成字节码文件,然后执行字节码文件响应客户的请求。而当这个JSP页面再次被请求执行时,JSP引擎将直接执行字节码文件(这也是JSP比ASP速度快的一个原因)。而JSP页面的首次执行往往有服务器管理者来执行。(如果对JSP页面进行了修改、执行,那么Tomcat服务器会生成新的字节码文件)

8.4、JSP基础语法

任何语言都有自己的语法,Java有,JSP也有,JSP作为Java技术的一种应用,它拥有自己扩充的语法。Java的所有语法,JSP都支持。

JSP表达式 (Java表达式)

可以在"<%=“和”%>“之间插入一个表达式(注意:不可插入语句,”<%=“是一个完整的符号,”<%“和”="之间不能有空格),这个表达式必须能求值。表达式的值有服务器负责计算,并将计算结果用字符串形式发送到用户端显示。

<%--JSP表达式用来将程序的计算结果,输出到客户端<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
EL表达式

JSP中${}是EL表达式的常规表示方式

EL表达式获取作用域数据

  • 作用域对象:pageContext request session application
  • 作用域数据:我们使用setAttribute方法存储的数据
获取:
  • 普通字符串数据 ${键名}
  • 对象数据${键名.属性名}
  • 集合数据
    • list集合 ${键名[角标]}
    • Map集合 ${map集合作用域存储的键名.map集合存储的数据的键名}

作用域数据查找顺序:如果找到了则不再查找,如果找不到,继续查找下一个作用域,如果四个作用域中都没有则什么都不显示。

pageContext–>request–>session–>application

指定作用域获取数据:

  • ${pageScope.键名} 指明获取pageContext作用域中的数据
  • ${requestScope.键名} 指明获取request作用域中的数据
  • ${sessionScope.键名} 指明获取session作用域中的数据
  • ${applicationScope.键名} 指明获取application作用域中的数据
JSP脚本片段(Java程序片)

可以在"<%“和”%>"之间插入Java程序片。一个JSP页面可以有许多程序片,这些程序片将被JSP引擎按顺序执行。

在程序片中声明的变量称作JSP页面的局部变量。局部变量的有效范围与其声明的位置有关,即局部变量在JSP页面后续的所有程序片以及表达式部分内有效。

<%--JSP脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <= 100 ; i++) {sum += i;
}
out.println("<h1>Sum="+ sum + "</h1>");
%>
脚本片段的再实现

一个JSP页面中的Java程序片会按其在页面中的顺序被执行,而且某个Java程序片中声明的局部变量在其后续的所有Java程序片以及表达式部分内都有效。利用Java程序片的这个性质,有时可以将一个Java程序片分割成几个Java程序片,然后在这些Java程序片之间插入其他标记元素,在程序片中插入HTML标记的技巧对于灵活显示数据是非常重要的。

<%--在Java代码中嵌入一些HTML元素--%>
<%
for (int i = 0; i < 3; i++) {%>
<h1>Hello World! <%= i%> </h1>
<%
}
%>
JSP注释
  1. java格式注释

    编译器会忽略掉此类注释中的内容(客户端的源码看不见)

    <%-- JSP注释;可多行 --%> 
    <%// java 单行注释 %>
    <%/* java multi lines comments */%> 
    <%/**java 特有的注释*/%>
    
  2. html风格注释
    编译器会执行此类注释中的代码(客户端的源码看得见)

    <!-- html风格注释 --> 等价于out.println("<!-- html风格注释 -->") 
    

    这种注释方式不好的地方就是当页面注释信息太多的时候会增大服务器的负荷。

    还有注释信息需要在网络上传输,从而降低效率;内部程序员的测试数据一般不能写在这种注释中,以免泄露。

JSP声明(Java声明)

在"<%!“和”%>"标记符号之间声明变量和方法。

在"<%!“和”%>“之间声明的变量在整个JSP页面内都有效,与”<%!"、"%>“标记符号在JSP页面中所在的书写位置无关,但习惯上把”<%!"、"%>"标记符号写在JSP页面的前面。任何一个用户对JSP页面成员变量操作的结果,都会影响其他用户。

在"<%!“和”%>"标记符号之间定义方法,所定义的方法在整个JSP页面都有效,可以在Java程序片中被调用。方法内声明的变量只在该方法内有效。

<%!static {System.out.println("Login Servlet...");
}
private int globalVar = 0;
public void fangFa(){System.out.println("进入了一个方法!");
}
%>

8.5、JSP指令

page指令的import属性:
在Jsp页面中,Jsp引擎会自动导入下面的包
java.lang.*
javax.servlet.*
javax.servlet.jsp.*
javax.servlet.http.*
可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号(,)分隔page指令的errorPage属性和isErrorPage属性:
errorPage属性:该属性用于指定处理当前JSP页面异常错误的另一个页面,指定的JSP错误处理页面必须设置errorPage属性的属性值是一个url字符串。
isErrorPage属性:该属性可以将当前JSP页面设置成错误处理页面来处理另一个JSP页面的错误,也就是异常处理。
注意:如果设置该属性,那么在web.xml文件中定义的任何错误页面都将被忽略,而优先使用该属性定义的错误处理页面。
isErrorPage属性:该属性可以将当前JSP页面设置成错误处理页面来处理另一个JSP页面的错误,也就是异常处理。它指定当前页面是否为处理错误的页面!当该属性为true时,这个页面会设置状态码为500!在web.xml中使用<error-page>标签为整个web应用设置错误处理页面。如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。
page指令

page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。

@include指令

@include可以包含任意的文件,当然,只是把文件的内容包含进来。include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。

语法:<%@ include file=“relativeURL”%>,其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前web应用。

静态包含是将全部内容包含进来之后,再进行处理,属于先包含后处理。

8.6、JSP标签

<%--@ include会将两个页面合二为一--%>
<%--include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。--%>
<%--include指令标记--%>
<%@ include file="common/header.jsp" %><%--该指令只有一个file属性,用于指定要包含的文件的路径,可以是相对路径,也可以是绝对路径,但是不可以是通过<%=%>表达式所代表的文件--%>
<%--小技巧:在应用include指令进行文件包含时,为了使整个页面的层次结构不发生冲突,建议在被包含页面中将<html>、<body>等标记删除。因为在包含该页面的(主体)文件中已经指定了这些标记。--%>
<h1>网页主体</h1>
<%@ include file="common/footer.jsp"%><hr/><%--JSP标签--%>
<%--<%@ include file="relativeURL"%>,其中的file属性用于指定被引入文件的路径。路径以"/"开头,表示代表当前web应用。--%>
<%--jsp:include拼接页面,本质还是三个页面--%>
<%--<jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。--%>
<%--include动作标记--%>
<jsp:include page="/common/header.jsp"/><%--/common/header.jsp的第一个 / 代表Web路径--%>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>
jsp:include标签

jsp:include标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:
<jsp:include page=“relativeURL | <%=expression%>” flush=“true|false” />
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。

jsp:forward标签

例如:<jsp:forward page=“xxx”/>,用来转发到指定页面
例如在a.jsp中存在如下内容:<jsp:fowrad page=“b.jsp”/>a.jsp中的内容不会显示在浏览器上,而只是显示b.jsp的内容。而且在jsp:forwad标签下面的内容不会被执行。

动态包含就是指先将各个页面分别处理,处理完之后再将处理后的结果包含进来。

8.7、九大内置对象

  • 在jsp中无需声明即可直接使用的9个对象
    • out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
    • config(ServletConfig):对应“真身”中的ServletConfig;
    • page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象,引用为Object类型;它代表JSP被编译成Servlet,可以使用它来调用Servlet类中所定义的方法;page对象表示当前一个JSP页面,可以理解为一个对象本身,即:把一个JSP当作一个对象来看待。page对象在开发中几乎不用,了解一下即可
    • pageContext(PageContext):页面上下文对象,它是最后一个没讲的域对象;存东西;pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象(容器),可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
    • exception(Throwable):只有在错误页面(即在页面指令中设置:<%@page isErrorPage=“true”%>)中可以使用这个对象;
    • request(HttpServletRequest):即HttpServletRequest类的对象;存东西
    • response(HttpServletResponse):即HttpServletResponse类的对象;
    • application(ServletContext):即ServletContext类的对象;存东西
    • session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。存东西
常用内置对象
  1. 输出输入对象:request对象、response对象、out对象

  2. 通信控制对象:pageContext对象、session对象、application对象

  3. Servlet对象:page对象、config对象

  4. 错误处理对象:exception对象

通过pageContext获得其他对象
  • getException方法返回exception隐式对象
  • getPage方法返回page隐式对象
  • getRequest方法返回request隐式对象
  • getResponse方法返回response隐式对象
  • getServletConfig方法返回config隐式对象
  • getServletContext方法返回application隐式对象
  • getSession方法返回session隐式对象
  • getOut方法返回out隐式对象
pageContext对象的常用方法
public void setAttribute(java.lang.String name,java.lang.Object value)
public java.lang.Object getAttribute(java.lang.String name)
public void removeAttribute(java.lang.String name)
public java.lang.Object findAttribute(java.lang.String name)
JSP四大域
  • ServletContext:整个应用程序。
  • session:整个会话(一个会话中只有一个用户)。
  • request:一个请求链!
  • pageContext:一个jsp页面!这个域是在当前jsp页面和当前jsp页面中使用的标签之间共享数据!
pageContext.setAttribute("name1","莱维");//使用pageContext对象,设置pageContext对象的属性//保存的数据只在一个页面中有效
request.setAttribute("name2","希德");//使用request对象,设置request对象的属性//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","张渊");//使用session对象,设置session对象的属性//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器的过程
application.setAttribute("name4","少阿");//使用application对象,设置application对象的属性//保存的数据在整个浏览器中有效,从打开服务器到关闭服务器的过程

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻;request属性范围表示在一次服务器跳转中有效,只要是服务器跳转,则设置的request属性可以一直传递下去。

session:客户端向服务器发送请求,产生的数据,用户看完了一会儿还有用,比如:购物车(开发中使用Hystrix技术);session设置的属性不管如何跳转,都可以取得的。当然,session只针对一个用户

appplication:客户端向服务器发送请求,产生的数据,用户看完了,其他用户还可能使用,比如:聊天数据;因为application属性范围是在服务器上设置的一个属性,所以一旦设置之后任何用户都可以浏览到此属性。

8.8、JSP标签、JSTL标签、EL表达式

EL表达式
<!-- EL表达式依赖 -->
<dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.4</version>
</dependency>

EL全名为Expression Language,它是可以在JSP页面中直接使用的语言!EL出现的目的是要替代jsp页面中脚本的编写。所有EL都是以"${“为起始、以”}"为结尾的。

${param.name} == request.getParam("name")
${name} == request.getAttribute("name").
getParam是表单的值或者是url中传来的值,如/login.action?attid=${attId}
getAttribute是设置在requestScope里的值
request.getparameter是action或者其它类(后台)获得页面中传过来的参数,有下面几种方法:
1.form里的表单控件的内容
2.get方法中?传的参数如user.do?age=1
request.getAttibute()通常是在页面里用。获得action或者其它类后台setAttreibute里的值,但一般是用el来获取的。
  • 获取数据
  • 执行运算
  • 获取web开发的常用对象
  • 调用Java方法(一般不用,比较麻烦)
JSP标签
<%--JSP标签--%>
<%--<%@ include file="relativeURL"%>,其中的file属性用于指定被引入文件的路径。路径以"/"开头,表示代表当前web应用。--%>
<%--jsp:include拼接页面,本质还是三个页面--%>
<%--<jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。--%>
<%--include动作标记--%>
<jsp:include page="/common/header.jsp"/><%--/common/header.jsp的第一个 / 代表Web路径--%><jsp:include page="/common/footer.jsp"/>
<jsp:forward page="/JSPTag2.jsp"><jsp:param name="name" value="zhangsan"/><jsp:param name="age" value="18"/>
</jsp:forward>
<%--当使用<jsp:include>和<jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数。--%>
<%--<jsp:param>标签的name属性用于指定参数名,value属性用于指定参数值。--%>
<%--<jsp:forward>标签用于把请求转发给另外一个资源。--%>
JSTL标签
<!-- JSTL表达式依赖 -->
<dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version>
</dependency>

JSTL(JavaServer Pages Standard Tag Library,JSP标准标签库)是一个JSP标签集合,它封装了JSP应用的通用核心功能。JSTL标签的使用就是为弥补HTML标签的不足;它自定义了许多标签,可以供我们使用,标签的功能和Java代码一样。

JSTL支持通用的、结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签。 除了这些,它还提供了一个框架来使用集成JSTL的自定义标签。

<form action="coreif.jsp" method="get"><input type="text" name="username" value="${param.username}" ><input type="submit" value="登录">
</form>
<%--${param.name}和${name}的区别${param.name} == request.getParam("name")${name} == request.getAttribute("name")getParam是表单的值或者是url中传来的值,如/login.action?attid=${attId}
getAttribute是设置在requestScope里的值,${name}是全域查找,${name} 会查找从小到大(pageContext,servletRequest,httpSession,servletContext)作用域中的attribute--%><%--判断如果提交的用户名是管理员,则登录成功--%>
<%--<%if (request.getParameter("username").equals("lsf")) {out.print("登录成功!");}
%>--%>
<%--使用JSTL核心标签<c:if test="条件1" var="name" [scope="page|request|session|application"]></c:if>--%>
<%--<c:out> 用来显示数据对象(字符串、表达式)的内容或结果--%>
<c:if test="${param.username == 'lsf'}" var="isLsf"><c:out value="欢迎您管理员!"/>
</c:if>
<c:out value="${isLsf}"/>
<%--定义一个变量score,值为150--%>
<c:set var="score" value="150" /><%--<c:choose>标签与Java switch语句的功能一样,用于在众多选项中做出选择。switch语句中有case,而<c:choose>标签中对应有<c:when>,switch语句中有default,而<c:choose>标签中有<c:otherwise>。--%>
<c:choose><c:when test="${score >= 100}">您的成绩为:优秀</c:when><c:when test="${score >= 90}">您的成绩为:良好</c:when><c:when test="${score >= 80}">您的成绩为:中上</c:when><c:when test="${score >= 70}">您的成绩为:中下</c:when><c:when test="${score >= 60}">您的成绩为:及格</c:when><c:otherwise>您的成绩为:不及格</c:otherwise>
</c:choose>
<%--<c:forEach>标签是更加通用的标签,因为它迭代一个集合中的对象。--%>
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"Jack");
people.add(2,"李林");
people.add(3,"露西");
people.add(4,"莱维");
request.setAttribute("list",people);
/*for (String person : people) {System.out.println(person);}*/
%>
<%--<c:forEach>标签有如下属性:var     代表当前条目的变量名称;或每一次遍历出来的变量items    要被循环的信息;或要遍历的对象--%>
<c:forEach var="person" items="${list}" ><c:out value="${person}" /> <br>
</c:forEach><hr/><%--<c:forEach>标签有如下属性:begin	开始的元素(0=第一个元素,1=第二个元素)end	最后一个元素(0=第一个元素,1=第二个元素)step	每一次迭代的步长--%>
<c:forEach var="person" items="${list}" begin="1" end="3" step="2" ><c:out value="${person}" /><br/>
</c:forEach>

可以分为4大类和JSTL函数

  • 核心标签

    <%@ taglib prefix="c" uri="" %>
    

    JSTL标签库使用步骤:

    1. 引入对应的taglib

    2. 使用其中的方法

    3. 在Tomcat(E:\tomact8\apache-tomcat-8.5.63\lib)也需要引入JSTL的包,否则会报错:JSTL解析错误。

      <%--EL表达式获取表单中的数据${param.参数名}
      --%>
      <form action="coreif.jsp" method="get"><input type="text" name="username" value="${param.username}" ><input type="submit" value="登录">
      </form><%--判断如果提交的用户名是管理员,则登录成功--%>
      <%--<%if (request.getParameter("username").equals("lsf")) {out.print("登录成功!");}
      %>
      --%>
      <%--使用JSTL核心标签<c:if test="条件1" var="name"[scope="page|request|session|application"]></c:if>--%>
      <c:if test="${param.username == 'lsf'}" var="isLsf"><c:out value="欢迎您管理员!"/>
      </c:if>
      <c:out value="${isLsf}"/>
      
  • 格式化标签

    <%@ taglib prefix="fmt" uri="" %>
    
  • SQL标签

    <%@ taglib prefix="sql" uri="" %>
  • XML标签

    <%@ taglib prefix="x" uri="" %>
    
  • JSTL函数

    <%@ taglib prefix="fn" uri="" %>
    

8.9、JavaBean

一、什么是JavaBean
实体类

1、这个类必须具有一个公共的(public)无参构造函数;
2、所有属性私有化(private);
3、私有化的属性必须通过public类型的方法(getter和setter)暴露给其他程序,并且方法的命名也必须遵循一定的命名规范。
4、这个类应是可序列化的。(比如可以实现Serializable 接口,用于实现bean的持久性)

实现 Serializable 接口用于实现 Bean 的持久性(Bean的含义是可重复使用的Java组件)。

一般用来和数据库的字段做映射 ORM(对象关系映射)

ORM:

数据库和Java的映射关系:

数据库Java
字段类中的属性
行记录类的一个对象

假设数据库中有一张表:People表

idnameageaddress
1莱维36东方之塔
2希德40西方之林
3少阿22乌托邦

class People {//People类private int id;//id属性private String name;//name属性private int age;//age属性private String address;//address属性
}
class Test {Person person = new Person(1,"莱维",36,"东方之塔");//对象1Person person = new Person(1,"希德",40,"西方之林");//对象2Person person = new Person(1,"少阿",22,"乌托邦");//对象3
}
JavaBean在Jsp中的引用
  1. jsp:useBean标记:

在jsp中使用jsp:useBean标签来实例化一个Java类的对象。

<jsp:useBean id=“name” class=“classname” scope=“page|request|session|application”/>

id:代表jsp页面中的实例对象 通过这个对象引用类中的成员,如,id=“wq”, wq.成员()。

class: 代表JavaBean类,如: class=“com.Test”,引用com包中的Test类; 。

scope:指明了javabean的生存时间。

  1. jsp:setProperty标签

name属性用于指定JavaBean对象的名称

property属性用于指定JavaBean实例对象的属性名

value属性用于指定JavaBean对象的某个属性的值,value的值可以是字符串,也可以是表达式。为字符串时,该值会自动转化为JavaBean属性相应的类型,如果value的值是一个表达式,那么该表达式的计算结果必须与所要设置的JavaBean属性的类型一致。

param属性用于将JavaBean实例对象的某个属性值设置为一个请求参数值,该属性值同样会自动转换成要设置的JavaBean属性的类型。

  1. jsp:getProperty标签

jsp:getProperty标签用于读取JavaBean对象的属性,也就是调用JavaBean对象的getter方法,然后将读取的属性值转换成字符串后插入进输出的响应正文中。

name属性用于指定JavaBean实例对象的名称,其值应与jsp:useBean标签的id属性值相同。
property属性用于指定JavaBean实例对象的属性名

JavaBean在J2EE开发中,通常用于封装数据,对于遵循以上写法的JavaBean组件,其它程序可以通过反射技术实例化JavaBean对象,并且通过反射那些遵守命名规范的方法,从而获知JavaBean的属性,进而调用其属性保存数据。

对于简单的JavaBean也有几个名词:

(1)VO:与简单Java对象对应,专门用于传递值的操作上。

(2)POJO:简单Java对象。****当一个POJO可序列化,有一个无参的构造函数,使用getter和setter方法来访问属性时,他就是一个JavaBean。****

(3)TO:传输对象,进行远程传输时,对象所在的类必须实现java.io.Serializable接口。

PO :persistent object持久对象。通俗点讲,就是将对象与关系数据库绑定,用对象来表示关系数据。可以看成是与数据库中的表相映射的java对象。

1、有时也被称为Data对象,对应数据库中的entity,可以简单认为一个PO对应数据库中的一条记录。
2、在hibernate持久化框架中与insert/delet操作密切相关。
3、PO中不应该包含任何对数据库的操作。
4、PO的属性是跟数据库表的字段一一对应的。
5、PO对象需要实现序列化接口。

public class User {private long id;private String name;public void setId(long id) {this.id = id;}public void setName(String name) {this.name = name;}public long getId() {return id;}public String getName() {return name;}} 

9、MVC三层架构

什么是MVC?

MVCModel-View-Controller,模型—视图—控制器模式)用于表示一种软件架构模式。它把软件系统分为三个基本部分:模型(Model)视图(View)控制器(Controller)

对于Spring这样的框架,(View\Web)表示层调用控制层(Controller),控制层调用业务层(Service),业务层调用数据访问层(Dao)

MVC是一个架构模式,它分离了表现与交互。

模型、视图、控制器各自的分工:

  • 视图View是用户看到并与之交互的界面。
  • 模型Model表示业务数据,并提供数据给视图。
  • 控制器Controller接受用户的输入并调用模型和视图去完成用户的需求。

Dao层:操作数据库

service层:业务层

9.1、早期的MVC三层架构

用户直接访问控制层,控制层就可以直接操作数据库。

servlet--CRUD--->数据库 servlet直接操作数据库(JDBC代码写在servlet里)
弊端:程序十分臃肿,不利于维护。
这时servlet中的代码主要负责:处理请求、响应;视图跳转、处理JDBC;处理业务代码;处理逻辑代码。架构的思想:“没有什么是“加一层”解决不了的!如果一层不行,就再加一层!”

9.2、MVC三层架构

Model
  • 业务处理:会产生业务逻辑(Service层)

  • 数据持久层:负责CRUD(增删改查)(DAO层)

View
  • 展示数据
  • 提供链接(,,…),发起Servlet请求
Controller(目前Controller是Servlet,以后是用其他东西做的)
  • 接收用户请求:(req:请求参数、Session信息…)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

    登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数。username、password...)--->交给业务层处理登录业务(判断用户名、密码是否正确;事务)--->Dao层查询用户名、密码是否正确--->数据库。
    

10、过滤器Filter(重点)

通过Filter技术,对web服务器管理的所有web资源:例如JSP, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

过滤器用来过滤网站的数据。

过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理,
通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理。

应用场景

  • 自动登录
  • 统一设置编码格式
  • 访问权限控制
  • 敏感字符过滤等

Filter开发步骤

  1. 导包
<dependencies><!--Servlet依赖--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><!--JSP依赖--><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.3</version></dependency><!-- EL表达式依赖 --><dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>2.2.4</version></dependency><!--JSTL表达式依赖--><dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version></dependency><!--standard标签库依赖--><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency><!--连接数据库依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency>
</dependencies>
  1. 编写过滤器

注意:导包不要错。

定义一个类,并继承javax.servlet.Filter接口。

  1. 实现Filter接口,重写对应的方法即可。

init方法在Web容器启动时就会执行,doFilter在每个Servlet请求的时候执行。

public class CharacterEncodingFilter implements Filter {//注意实现的是javax.servlet.Filter//初始化 web服务启动就已经初始化了,因为它要随时等待过滤对象出现。/*初始化方法  接收一个FilterConfig类型的参数 该参数是对Filter的一些配置*/public void init(FilterConfig filterConfig) throws ServletException {System.out.println("测试:CharacterEncodingFilter初始化");}//chain是“链”的意思/*在web应用中,你可以部署多个过滤器,这些过滤器组成过滤器链,过滤器链中的每一个过滤器负责特定的操作和任务,客户端的请求在这些过滤器之间传递,直到目标资源。在请求资源时,过滤器链中的过滤器将依次对请求进行处理,并将请求传递给下一个过滤器,直到目标资源,在发送响应时,则按照相反的顺序对响应进行处理,直到客户端。1.过滤器中所有的代码,在过滤特定请求的时候都会执行2.必须要让过滤器继续通行chain.doFilter(req,resp);*/public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {/*过滤方法 主要是对request和response进行一些处理,然后交给下一个过滤器或Servlet处理*///如处理中文乱码问题req.setCharacterEncoding("utf-8");resp.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf-8");System.out.println("CharacterEncodingFilter执行前");//通过chain放行对象chain.doFilter(req,resp);//进入下一个过滤器//chain.doFilter(req,resp);/的作用是让请求继续走,如果不写,程序到这里就被拦截/*** 在doFilter()方法中,在chain.doFilter()之前的代码,一般是对request执行的过滤操作;* 在chain.doFilter()后面的代码,一般是对response执行的操作;* chain.doFiter()执行下一个过滤器或者业务处理器。* 如果在doFilter()方法中,不写chain.doFilter(),业务无法继续往下处理;*/System.out.println("CharacterEncodingFilter执行后");}//销毁 web服务器关闭的时候,过滤器会销毁public void destroy() {/*销毁时调用*/System.out.println("测试:CharacterEncodingFilter销毁");}}
  1. 在web.xml中配置filter过滤器。
<!--在实现一个过滤器后,需要在web.xml进行配置,通过<filter>和<filter-mapping>元素来完成-->
<!--<filter>元素用于在web应用程序中声明一个过滤器。-->
<filter><!--<description> <display-name> <icon>元素的作用是相同的。--><!--<filter-name>元素用于指定过滤器的名字,该元素的内容不能为空。--><filter-name>CharacterEncodingFilter</filter-name><!--<filter-class>元素指定过滤器的完整的限定类名。--><filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class><!--<init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值,在过滤器中可以使用FilterConfig对象获取这些初始化参数-->
</filter>
<!--<filter-mapping>元素用于指定过滤器关联的URL或者Servlet。-->
<filter-mapping><!--<filter-name>子元素的值必须是在<filter>元素中声明过的过滤器的名字--><filter-name>CharacterEncodingFilter</filter-name><!--Servlet2.5规范允许<url-pattern>和<servlet-name>元素出现多次,之前的规范只允许一个<filter-mapping>元素包含一个<url-pattern>或者一个<servlet-name>子元素。Servlet2.5规范还允许为<servlet-name>元素指定*号,来匹配所有的Servlet。--><!--<url-pattern>元素和<servlet-name>元素可以选择一个,<url-pattern>元素指定过滤关联的URL样式,<servlet-name>元素指定过滤器对应的Servlet。用户在访问<url-pattern>元素指定的URL上的资源或者<servlet-name>元素指定的Servlet时,该过滤器才会被容器调用。--><!--“>/servlet/*”表示只要是>/servlet的任何请求,都会经过这个过滤器--><url-pattern>/servlet/*</url-pattern><!--<filter-mapping>还可以包含0到4个<dispatcher>元素,<dispatcher>元素指定过滤器对应的请求方式,可以是REQUEST INCLUDE FORWARD ERROR四种之一或者多种,默认是REQUEST。REQUEST:当用户直接访问页面时,web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或者forward()方法访问时,那么该过滤器将不会被调用。INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用,除此之外,过滤器不会被调用。FORWARD:如果目标资源时通过RequestDispatcher的forward()方法访问时,那么该过滤器将会被调用,除此之外,过滤器不会被调用。ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。-->
</filter-mapping>

11、监听器Listener

jservlet规范包括三个技术点:servlet ;listener ;filter;监听器就是监听某个对象的的状态变化的组件。

监听器的相关概念事件源:

  • 被监听的对象(三个域对象 request,session,servletContext)。
  • 监听器:监听事件源对象, 事件源对象的状态的变化都会触发监听器 。
  • 注册监听器:将监听器与事件源进行绑定。
  • 响应行为:监听器监听到事件源的状态变化时,所涉及的功能代码(程序员编写代码)。

分类:

按照被监听的对象划分:ServletRequest域 ;HttpSession域 ;ServletContext域。

按照监听的内容分:监听域对象的创建与销毁的;监听域对象的属性变化的。

监听器开发步骤

  1. 编写一个监听器

    实现监听器的接口(监听器的接口有很多),并重写里面的方法

    //在线人数监听,统计在线人数————统计Session
    public class OnlineCountListener implements HttpSessionListener {//创建Session监听 监听:”看‘您’的一举一动“//一旦创建Session就会触发一次这个事件//代表HttpSessionEvent Session事件的一个对象public void sessionCreated(HttpSessionEvent httpSessionEvent) {ServletContext ctx = httpSessionEvent.getSession().getServletContext();System.out.println(httpSessionEvent.getSession().getId());Integer onlineCount = (Integer) ctx.getAttribute("onlineCount");if (onlineCount == null){onlineCount = new Integer(1);}else {int count = onlineCount.intValue();onlineCount = new Integer(count + 1);}ctx.setAttribute("onlineCount",onlineCount);}//销毁Session监听//一旦销毁Session就会触发一次这个事件public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {ServletContext ctx = httpSessionEvent.getSession().getServletContext();Integer onlineCount = (Integer) ctx.getAttribute("onlineCount");if (onlineCount == null){onlineCount = new Integer(0);}else {int count = onlineCount.intValue();onlineCount = new Integer(count - 1);}ctx.setAttribute("onlineCount",onlineCount);}/*** Session销毁的两种情况:*  1.手动销毁*      httpSessionEvent.getSession().invalidate();*  2.自动销毁*      在web.xml配置Session自动销毁时间*/}
    
    1. 在web.xml中注册监听器

      <!--注册监听器-->
      <session-config><session-timeout>1</session-timeout><!--Session销毁时间:以分钟为单位-->
      </session-config>
      
      1. 看情况是否使用

12、过滤器、监听器的常见应用

监听器·:GUI编程中经常使用

public class TestPanel {public static void main(String[] args) {//创建一个JFrame容器窗口JFrame frame = new JFrame("中秋节快乐!");//定义一个Panel面板组件Panel panel = new Panel(null);//不为面板设置布局方式frame.setLayout(null);//设置窗体的布局frame.setBounds(300,300,500,500);//设置窗体坐标frame.setBackground(new Color(0,0,255));//设置窗体背景颜色panel.setBounds(50,50,300,300);//设置面板的坐标panel.setBackground(new Color(100,255,100));//设置面板背景颜色frame.add(panel);//向窗体中加入面板组件frame.setVisible(true);//设置窗体可见//监听事件,监听关闭窗口事件frame.addWindowListener(new WindowAdapter() {//事件监听器之WindowAdapter类(针对窗口事件)@Overridepublic void windowClosing(WindowEvent e) {super.windowClosing(e);}});}
}

用户登录之后才能进入主页!用户注销后就不能进入主页了!

  1. 用户登录后,向Session中存放用户的信息
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
  1. 进入主页的时候,要判断用户是否已经登录;要求在过滤器中实现
// 过滤器://ServletRequest转化为HttpServletRequest,通过HttpServletRequest才能拿到session/*** HttpServletRequest继承自ServletRequest*      ServletRequest ——强转——> HttpServletRequest* HttpServletRequest比ServletRequest多了一些针对于Http协议的方法。 例如:*      getHeader(), getMethod() , getSession()*/HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
if (request.getSession().getAttribute(Constant.USER_SESSION) == null){response.sendRedirect("/error.jsp");
}
chain.doFilter(req,resp);//让请求继续往下走,如果不写,程序到这里就会被拦截停止
}

13、JDBC

JDBC是一套用于执行SQL语句的JavaAPI。JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据。

执行流程:

  • 连接数据源,如:数据库。
  • 为数据库传递查询和更新指令。
  • 处理数据库响应并返回的结果。

JDBC 编程步骤

什么是JDBC:java连接数据库

需要jar包的支持

  • java.sql

  • javax.sql

  • mysql-connector-java-xxx.jar连接驱动(重点)

JDBC的本质是一套接口。

环境搭建

创建表
drop table if exists users;
CREATE TABLE users(id INT PRIMARY KEY,`name` VARCHAR(40),`password` VARCHAR(40),email VARCHAR(60),birthday DATE
);INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(1,'莱维','142857','lw@lsf','1893-12-26');
INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(2,'希德','142857','xd@lsf','1898-03-05 ');
INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(3,'光蓉','142857','gr@lsf','1328-10-21');
INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(4,'张渊','142857','zy@lsf','1907-12-05');
INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(5,'唐欧','142857','to@lsf','1893-12-26');
INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(6,'少阿','142857','se@lsf','1886-12-01');
INSERT INTO users(id,`name`,`password`,email,birthday) VALUES(7,'华明','142857','hm@lsf','1882-12-18');SELECT * FROM users;
导入数据库依赖
<!--mysql驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
</dependency>
IDEA中连接数据库

JDBC固定步骤

配置初始信息
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=true";
String username = "root";
String password = "root";
1.加载驱动程序
Class.forName(driverClass)
//加载MySql驱动
Class.forName("com.mysql.jdbc.Driver")
//加载Oracle驱动
Class.forName("oracle.jdbc.driver.OracleDriver")
2.获得数据库连接
Connection connection = DriverManager.getConnection(url, username, password);
3.创建Statement对象:用它来做CRUD
Statement statement = connection.createStatement();
4.编写SQL(根据业务,不同的SQL)
String sql = "select * from users;";
5.执行SQL
ResultSet resultSet = statement.executeQuery(sql);
6.关闭连接
Statement存在SQL注入问题;
PreparedStatement解决了SQL注入问题。
package com.kuang.test;import java.sql.*;/*** @author: lsf* @date: 2021/9/15 21:13* @description:*/
public class TestJdbc {public static void main(String[] args) throws ClassNotFoundException, SQLException {//初始配置信息/*** mysql 连接url中useUnicode=true&characterEncoding=UTF-8 的作用:指定字符的编码、解码格式。** 注意:在xml配置文件中配置数据库url时,要使用&的转义字符也就是&amp;* 例如:<property name="url" value="jdbc:mysql://localhost:3306/email?useUnicode=true&amp;characterEncoding=UTF-8" />** useSSL=true 安全连接* 连接语句后加上“useSSL=‘true’” ,就可以连接到数据库了。更高版本*/String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=true";String username = "root";String password = "root";//1.加载驱动/*Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。*/Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动//2.连接数据库,代表数据库Connection connection = DriverManager.getConnection(url, username, password);//3.向数据库发送语句的Statement对象 用它来做CRUDStatement statement = connection.createStatement();//4.编写SQLString sql = "select * from users;";//5.执行查询SQL,得到结果集ResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()){System.out.println("id=" + resultSet.getObject("id"));System.out.println("name=" + resultSet.getObject("name"));System.out.println("password=" + resultSet.getObject("password"));System.out.println("email=" + resultSet.getObject("email"));System.out.println("birthday=" + resultSet.getObject("birthday"));}//6.关闭连接,释放资源。先开后关resultSet.close();statement.close();connection.close();}
}
预编译SQL
public static void main(String[] args) throws Exception {//初始配置信息String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=true";String username = "root";String password = "root";//1.加载驱动/*Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。*/Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动//2.连接数据库,代表数据库Connection connection = DriverManager.getConnection(url, username, password);//3.编写SQLString sql = "insert into users(id, name, password, email, birthday) values(?,?,?,?,?);";//String sql = "delete from users where id = 4";//4.预编译sqlPreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,4);//给第一个占位符 ? 赋值 1//注意“主键”不能重复preparedStatement.setString(2,"doctor");//给第二个占位符 ? 赋值 1preparedStatement.setString(3,"147258");//给第三个占位符 ? 赋值 1preparedStatement.setString(4,"zy@lsf");//给第四个占位符 ? 赋值 1preparedStatement.setDate(5,new java.sql.Date(new java.util.Date().getTime()));//给第五个占位符 ? 赋值 1int i = preparedStatement.executeUpdate();if(i > 0){System.out.println("插入成功@");}//5.关闭连接preparedStatement.close();connection.close();
}

事务

/***  JDBC事务机制:1、JDBC中的事务是自动提交的。什么是自动提交?只要执行任意的DML语句(insert delete update),则自动提交一次。这是JDBC默认的事务行为。但是在实际的业务当中。通常是N条DML语句共同联合才能完成的。必须保证它们这些DML语句在同一个事务中同时成功或者失败。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。*/
//重点:三行代码(这里只是伪代码,便于着重)
try{conn.setAutoCommit(false);//开启事务...connmit();//手动提交事务
} catch(Exception e){if(conn != null){conn.rollback();//手动回滚事务}
}

一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务经典事务:转账

junit单元测试

依赖
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version>
</dependency>
简单使用
@Test注解: 测试是需要运行来完成的。

在测试方法上方加@Test注解来完成测试,只要是加该注解的方法,可以单独运行此方法来完成测试。@Test注解只有在方法上有效,只要加了这个注解的方法就可以直接运行。

public class TestJdbc2 {@Testpublic void test(){System.out.println("Hello!");}
}

成功

模拟失败

public class TestJdbc2 {@Testpublic void test(){System.out.println(1 / 0);}
}

搭建一个环境来测试事务

System.out.println("birthday=" + resultSet.getObject("birthday"));}//6.关闭连接,释放资源。先开后关resultSet.close();statement.close();connection.close();
}

}


#### 预编译SQL```java
public static void main(String[] args) throws Exception {//初始配置信息String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useSSL=true";String username = "root";String password = "root";//1.加载驱动/*Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。*/Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动//2.连接数据库,代表数据库Connection connection = DriverManager.getConnection(url, username, password);//3.编写SQLString sql = "insert into users(id, name, password, email, birthday) values(?,?,?,?,?);";//String sql = "delete from users where id = 4";//4.预编译sqlPreparedStatement preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,4);//给第一个占位符 ? 赋值 1//注意“主键”不能重复preparedStatement.setString(2,"doctor");//给第二个占位符 ? 赋值 1preparedStatement.setString(3,"147258");//给第三个占位符 ? 赋值 1preparedStatement.setString(4,"zy@lsf");//给第四个占位符 ? 赋值 1preparedStatement.setDate(5,new java.sql.Date(new java.util.Date().getTime()));//给第五个占位符 ? 赋值 1int i = preparedStatement.executeUpdate();if(i > 0){System.out.println("插入成功@");}//5.关闭连接preparedStatement.close();connection.close();
}

事务

/***  JDBC事务机制:1、JDBC中的事务是自动提交的。什么是自动提交?只要执行任意的DML语句(insert delete update),则自动提交一次。这是JDBC默认的事务行为。但是在实际的业务当中。通常是N条DML语句共同联合才能完成的。必须保证它们这些DML语句在同一个事务中同时成功或者失败。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。*/
//重点:三行代码(这里只是伪代码,便于着重)
try{conn.setAutoCommit(false);//开启事务...connmit();//手动提交事务
} catch(Exception e){if(conn != null){conn.rollback();//手动回滚事务}
}

一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务经典事务:转账

junit单元测试

依赖
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version>
</dependency>
简单使用
@Test注解: 测试是需要运行来完成的。

在测试方法上方加@Test注解来完成测试,只要是加该注解的方法,可以单独运行此方法来完成测试。@Test注解只有在方法上有效,只要加了这个注解的方法就可以直接运行。

public class TestJdbc2 {@Testpublic void test(){System.out.println("Hello!");}
}

成功

模拟失败

public class TestJdbc2 {@Testpublic void test(){System.out.println(1 / 0);}
}

搭建一个环境来测试事务

更多推荐

JavaWeb杂记

本文发布于:2024-03-10 04:17:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726989.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:杂记   JavaWeb

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!