JavaWeb
文章目录
- JavaWeb
- 1、基本概念
- 2.1、web服务器
- 3.1 Tomcat:(摘自百度百科)
- 4、HTTP
- 5、Maven
- 6、Servlet
- 7、Cookie、Session
- 8、JSP
- 9、JavaBean
- 10、MVC三层架构
- 11、Filter
- 12、监听器
- 13、过滤器、监听器常见应用
- 14、JDBC
请点击这里 获取本文代码
1、基本概念
web 开发:
-
web,网页,例如 : www.baidu.com
-
静态web
- html,css
- 提供给所有人看的数据,且始终不会变换
-
动态web
- 淘宝,等几乎所有网站
- 提供给所有人看的数据始终会发生变化的,每个人在不同的时间不同的地点看到的信息是不同的
- 技术栈:Servlet/JSP,ASP,PHP
在Java中动态web资源开发的技术都称为javaweb;
1.2、web应用程序
web应用程序:可以提供浏览器访问的程序;
-
html文件,a.html、b.html等多个资源,这些web资源可以被外界访问,对外界提供服务;
-
我们能访问到的任何一个页面或者资源都存在于世界上的某一个计算机中
-
URL:统一资源定位符
-
这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat服务器
-
一个web应用由多部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- java程序
- jar包
- 配置文件(Properties)
web应用程序编写完毕后,如果想要提供给外界访问,需要一个服务器来统一管理
1.3 静态web
- *.html, *.htm,这些都是网页的后缀,如果服务器上一直存在这些东西,我们就能直接进行读取,
- 静态web存在的缺点
- Web页面无法动态更新,所有用户看到的都是同一个页面
- 轮播图:点击特效:伪动态
- javascript[在实际开发中使用的最多]
- VBscript
- 它无法和数据库交互(数据无法持久化,用户无法交互)
- Web页面无法动态更新,所有用户看到的都是同一个页面
1.4、动态web
页面会动态:“web的页面展示的效果每个人都不同";
缺点
- 如果加入服务器的动态web资源出现了错误,那么需要重新编写后台程序,重新发布:
- 如停机维护
优点:
-
web页面可以动态更新,所有的用户看到的界面都不是同一个页面
-
它可以与数据库交互
2.1、web服务器
基于ASP,JSP,php
JSP/Servlet:
B/S:浏览器和服务器
C/S:客户端和服务器
- sun公司主推的B/S架构
- 基于Java语言的(所有的大公司或者一些开源组件都是java写的)
- 可以承载三高问题的影响
- 语法像ASP,ASP–> JSP,加强市场强度;
2.2 web 服务器
服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;
IIS
微软的:ASP,windows中自带
3.1 Tomcat:(摘自百度百科)
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。
tomcat的默认端口号:8080
mysql的默认端口:3306
http 的默认端口:80
https默认端口:443
<!-- 1 可以在路径:C:\Windows\System32\drivers\etc\hosts文件下配置本机域名 -->
<!--在E:\Dev_Language\apache-tomcat-8.0.20\conf\server.xml 文件下配置tomcat的端口号和主机名称。-->
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- 默认的主机名:localhost -> 127.0.0.1 -->
<!-- 默认网站应用存放的位置为:wabapps
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
请你谈谈网站时如何进行访问的?
1、输入一个域名:回车
2、检查本机的C:\Windows\System32\drivers\hosts配置文件下有没有这个域名映射:
1.有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
2.没有去DNS服务器找,找到的话就返回,找不到就返回找不到
4.可以配置环境变量(可选项)
3.4、发布一个web网站
将自己写的网站,放到服务器(Tomcat)中指定的web应用文件夹下(webapps)下,就可以访问了,网站的基本结构:
-- webapps: Tomcat服务器web目录
-ROOT
-ruasibstudy:网站目录名
-WEB-INF
-classes : java程序
-lib:web应用所依赖的jar包
-web.xml
-index.html 默认的首页
-static
-css
-style.css
-js
-img
- .....
HTTP协议:面试
Maven :构建工具
- maven安装包
Servlet入门
-
Helloword
-
Servlet配置
-
原理
4、HTTP
4.1 什么是https?
超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。
- 文本:html,字符串,~…
- 超文本:图片,音乐,视频,定位,地图…
- 端口:80
https: 安全的超文本传输协议
- 端口:443
4.2 、 两个时代
-
http1.0
- HTTP/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
-
http2.0
- HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源
4.3、 Http请求
- 客户端-- 发请求(Request) --> 服务器
百度:
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET 请求方法:get方法、post方法
Status Code: 200 OK 状态码:200
Remote Address: 14.215.177.38:443 百度的地址 + 端口
Cache-Control: private 缓存控制
Connection: keep-alive 连接方式:保持连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 文件类型:html,以及文件编码:utf-8
Date: Mon, 28 Jun 2021 01:43:29 GMT
Expires: Mon, 28 Jun 2021 01:43:28 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=386; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=33801_33966_31254_34113_33607_34134_34119; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1624844609018818305012084217433091881680
Transfer-Encoding: chunked
X-Ua-Compatible: IE=Edge,chrome=1
1、请求行
- 请求行中的请求方式:GET
- 请求方式:Get,Post,HEAD,DELETE,put,tract…
- get :请求能够携带的方式较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post : 请求能够携带的参数没有限制,大小没有限制,不会再浏览器的URL地址显示数据内容,安全,但不高效。
2、消息头:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 告诉浏览器它所支持的数据类型
Accept-Encoding: gzip, deflate, br 支持哪种编码格式 :GBK、utf-8、GB2312、iso8859-1
Accept-Language: zh-CN,zh;q=0.9 告诉六拉起。他的语言环境
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉浏览器,请求完成的是断开连接和保持连接
HOST : 主机ip地址以及端口
4.4、Http响应
-
服务器–响应—客户端
百度:
Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Origin: * Cache-Control: no-cache Connection: keep-alive Content-Length: 0 Content-Type: image/gif Date: Mon, 28 Jun 2021 01:43:31 GMT Pragma: no-cache Server: nginx/1.8.0 Set-Cookie: BAIDUID_BFESS=C23FC53DC981E34B8842BF60593436D4:FG=1; Path=/; Domain=baidu.com; Expires=Tue, 28 Jun 2022 01:43:31 GMT; Max-Age=31536000; Secure; SameSite=None Set-Cookie: BDUSS_BFESS=k5GNVdXeXBCSjl3NUE0Z3hvSTVCT3NEUk5TakhjYXhLS3dQc2dNQWIyOTIwTTVnSVFBQUFBJCQAAAAAAAAAAAEAAABpXVFFXzEydgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZDp2B2Q6dgY; Path=/; Domain=baidu.com; Expires=Thu, 26 Jun 2031 01:43:31 GMT; Max-Age=315360000; HttpOnly; Secure; SameSite=None Tracecode: 26119272462803688714062809
1.响应体
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 告诉浏览器它所支持的数据类型 Accept-Encoding: gzip, deflate, br 支持哪种编码格式 :GBK、utf-8、GB2312、iso8859-1 Accept-Language: zh-CN,zh;q=0.9 告诉六拉起。他的语言环境 Cache-Control: max-age=0 缓存控制 Connection: keep-alive 告诉浏览器,请求完成的是断开连接和保持连接 HOST : 主机ip地址以及端口 Refresh: 告诉客户端,多久刷新一次; Location:让网页重新定位;
2、 响应状态码
200 : 请求响应成功
3xx :请求重定向
- 重新到服务器给的新位置去
4xx :找不 到资源 404
- 资源不存在
5xx : 服务器代码错误 500, 502 : 网关错误
常见面试题:
当你的浏览器中地址输入地址并回车的一瞬间到页面能够显示回来,经历了什么?
5、Maven
5.1 为什么要学这个技术?
1、再javaweb开发中,需要使用大量的jar包,我们手动去导入;
2、如何能够让一个东西自动帮我导入和配置这个jar包
5.2 下载安装
下载解压即可;
提示:电脑上的所有环境都放在一个文件夹下,方便管理
5.3 配置环境变量
再我们的系统环境变量下,配置如下:
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置: %MAVEN_HOME%\bin
测试maven是否安装成功,保证必须配置完毕!
5.4 阿里云镜像
-
镜像:mirrors
<mirror> <id>nexus-aliyun</id> <mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
5.5 本地仓库:
在本地的仓库,远程仓库:
建立本地仓库:
<localRepository>E:\Dev_Language\JAVA\maven\apache-maven-3.6.2\maven-repo</localRepository>
5.6、在IDEA使用Maven
1、启动IDEA
2、创建一个MavenWeb项目
3 然后等待项目初始化完成
4 查看仓库文件
5 idea中的maven设置
在这里maven在idea中配置的maven就ok了
5.7 Maven创建一个普通的maven项目
一个干净的maven
一个带模板的maven
5.8 设置文件目录结构:
5.9 在idea中配置tomcat
解决警告信息:
必须要解决这个问题:为什么会有这个问题?因为我们访问一个网站需要指定一个文件夹名字
5.10 pom文件
pom.xml 是maven的核心配置文件。
<?xml version="1.0" encoding="UTF-8"?>
<!--maven的版本和头文件-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--这里就是我们刚刚配置的GAV 即 groupId 组id,artifactId 项目名称 ,version 版本-->
<groupId>com.ruasib</groupId>
<artifactId>javaweb-01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 项目的打包方式
jar:java应用
war:javaWeb应用
-->
<packaging>war</packaging>
<!-- 项目名称 -->
<name>javaweb-01-maven Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<!-- 配置 -->
<properties>
<!-- 项目的默认构建编码-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 编码版本-->
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<!--项目依赖-->
<dependencies>
<dependency>
<!-- 具体依赖的jar包配置文件-->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--项目构建的用的东西-->
<build>
<finalName>javaweb-01-maven</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
5.11 Maven存在的资源导出问题
由于maven他的约定大于配置,我们可能遇到我们写的配置文件,无法被导出或者生效的问题
解决办法:
<!-- 将下列代码放入pom.xml文件中-->
<!-- 在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<!-- 在src/main/resources 目录下可以包含properties、xml文件-->
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<!-- 在src/main/java 目录下可以包含properties、xml文件-->
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!-- 关闭自动过滤-->
<filtering>false</filtering>
</resource>
</resources>
</build>
5.12 idea操作
5.13 Maven 仓库的使用
https://mvnrepository.com/
Java Servlet API
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
6、Servlet
常见的HTTP状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
HTTP content-type 资料来源:菜鸟教程
Content-Type(内容类型),一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。
Content-Type 标头告诉客户端实际返回的内容的内容类型。
语法格式:
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
常见的媒体格式类型如下:
- text/html : HTML格式
- text/plain :纯文本格式
- text/xml : XML格式
- image/gif :gif图片格式
- image/jpeg :jpg图片格式
- image/png:png图片格式
以application开头的媒体格式类型:
- application/xhtml+xml :XHTML格式
- application/xml: XML数据格式
- application/atom+xml :Atom XML聚合格式
- application/json: JSON数据格式
- application/pdf:pdf格式
- application/msword : Word文档格式
- application/octet-stream : 二进制流数据(如常见的文件下载)
- application/x-www-form-urlencoded : 中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
- multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
6.1、Servlet简介
-
Servlet就是sun公司开发动态web的一门技术
-
Sun在这些API中提供一个接口叫做Servlet,如果你想开发Servlet程序,只需要完成两个步骤:
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器中。
实现了Servlet接口的java程序叫做,Servlet
6.2、HelloServlet
Servlet在sun公司有两个默认的实现类:HttpServelt,GenericServlet
-
构建一个普通的maven项目,删掉除了配置文件外的所有东西,即删除src目录下的所有文件,以后学习就在这个项目中建立Moudel;这个空的项目就是maven的主工程;
-
关于maven父子工程的理解:
父工程的pom.xml文件中,有以下代码,而其中的,servlet-01就是其子工程
<modules>
<module>servlet-01</module>
</modules>
其中父项目的java子项目可以直接使用
-
Maven环境优化
- 修改web.xml为最新
- 将maven的结构搭建完整
-
编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口,这里直接基础
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("hello,servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 编写Servlet的映射
为什么需要映射:我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能访问的路径;
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.ruasib.servlet.HelloServlet</servlet-class>
</servlet>
<!-- Servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>\hello</url-pattern>
</servlet-mapping>
</web-app>
-
配置Tomcat
注意:配置项目发布的路径就可以了
- 启动测试,ok
6.3、Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求后会:
6.4、Mapping 问题
-
一个Servlet可以指定一个映射路径:
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>servlet-01</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <!-- 浏览器访问方式:localhost:8080/s1/haha --> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/haha</url-pattern> </servlet-mapping> </web-app>
-
一个Servlet可以指定多个映射路径
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>servlet-01</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <!-- 浏览器访问方式:localhost:8080/s1/haha --> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/haha</url-pattern> </servlet-mapping> <!-- 浏览器访问方式:localhost:8080/s1/haha1 --> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/haha1</url-pattern> </servlet-mapping> <!-- 浏览器访问方式:localhost:8080/s1/haha2 --> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/haha2</url-pattern> </servlet-mapping> </web-app>
-
一个Servlet可以指定通用映射路径
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>servlet-01</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <!-- 浏览器访问方式:localhost:8080/s1/haha/... 意思:在/haha下的任意 路径下都会走这个Servlet --> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/haha/*</url-pattern> </servlet-mapping> </web-app>
-
默认请求路径
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>servlet-01</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <!-- 浏览器访问方式:localhost:8080/s1/... 意思:在任意路径下都会走这个Servlet --> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
-
指定以下后缀或者前缀等等…
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>servlet-01</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <!--会报错: .*前面不能加项目映射的路径--> <url-pattern>/haha/*.ruasib</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <!--会报错: .*前面不能加项目映射的路径--> <url-pattern>/haha/*.ruasib</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <!--任何以ruasib为后缀的请求路径都执行该Servlet--> <url-pattern>*.ruasib</url-pattern> </servlet-mapping> </web-app>
-
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<!-- 404:错误请求--> <servlet> <servlet-name>servlet-01</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>servlet-01</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
6.5、ServletContext
web容器在启动的时候,他会为每个web程序创建一个对应的ServletContext,它代表了当前的web应用;
共享数据
在这个Servlet中保存的数据,可以在另外一个servlet中拿到
// 将数据写入ServletContext
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter(String name); 初始化参数
// this.getServletConfig() Servlet配置
// this.getServletContext(); Servlet上下文对象
ServletContext servletContext = this.getServletContext();
String username = "ruasib"; // 数据
// 将一个数据保存在ServletContext中,键为username,值为username(变量)
servletContext.setAttribute("username",username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
// 从ServletContext中获取数据
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
// 将数据从contetx中按照键“username”来获取到对应的值(数据)
String username = (String)context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字="+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.ruasib.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.ruasib.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
获取初始化参数
// 获取在web.xml文件中的<context-param>标签的名为url的参数的数据
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 读取在web.xml文件中得到的xml参数
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<!-- 配置context的初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.ruasib.servlet.ServletDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
</web-app>
请求转发
// 转发类
package com.ruasib.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求转发
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
// 获取转发的请求路径
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
// 调用forward实现请求转发
requestDispatcher.forward(req,resp);
// 第二种方式:实现请求转发
// context.getRequestDispatcher("/gp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
// 转发目的地
package com.ruasib.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("进入了ServletDemo03");
System.out.println("进入了ServletDemo03");
// 读取在web.xml文件中得到的xml参数
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<!-- ServletDemo3-->
<!-- 配置context的初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.ruasib.servlet.ServletDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
<!-- ServletDemo4-->
<servlet>
<servlet-name>sd4</servlet-name>
<servlet-class>com.ruasib.servlet.ServletDemo4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd4</servlet-name>
<url-pattern>/sd4</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
读取资源文件
Properties文件
- 在Java目录下新建aa.properties
- 在resources目录下新建db.properties
发现:在没有解决Maven存在的资源导出问题时后,会将java目录下的文件无法被导出到target目录下,Maven存在的资源导出问题解决方案5.11章节中
当解决了Maven存在的资源导出问题后,重新生成文件,发现:两个目录下的properties文件都被打包到了同一个路径下:classes,我们俗称这个路径为classpath;
- 思路:需要一个文件流从
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class propertiesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// `/`代表当前web应用
// 读取目录 target/servlet-02-1.0-SNAPSHOT//WEB-INF/classes/db.properties 的文件
// InputStream inputStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
// 读取目录 target/servlet-02-1.0-SNAPSHOT//WEB-INF/classes/WEB-INF/classes/com/ruasib/servlet/aa.properties 的文件
InputStream inputStream = this.getServletContext().getResourceAsStream(
"/WEB-INF/classes/com/ruasib/servlet/aa.properties");
Properties prop = new Properties();
prop.load(inputStream);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
resp.getWriter().print(username+":"+password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_4_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<!--propertiesServlet-->
<servlet>
<servlet-name>sd5</servlet-name>
<servlet-class>com.ruasib.servlet.propertiesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd5</servlet-name>
<url-pattern>/sd5</url-pattern>
</servlet-mapping>
</web-app>
# db.properties
username=ruasib
password=123456
# aa.properties
username=hasib
password=xcvbnm
文件结构:
运行结果:
6.6、HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表HttpServletRequest对象,代表响应的一个HttpServletResponse;
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应一些信息:找HttpServletResponse
1、简单分类
负责向浏览器发送数据的方法:
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法:
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentType(String var1);
void sendRedirect(String var1) throws IOException;
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);
void setStatus(int var1);
响应的状态码:
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;
常见应用
-
向浏览器输出消息
-
下载文件
- 要获取下载文件的路径
- 下载的文件名是什么?
- 设置想办法让浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
package com.ruasib.servlet; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; public class FileDownServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 获取要下载文件的路径 String realPath = "D:\\java_workplace\\javaweb\\javaweb-servlet\\response\\" + "target\\response-1.0-SNAPSHOT\\WEB-INF\\classes\\莉雅.jpg"; System.out.println("要下载的文件路径:"+realPath); //2. 下载的文件名是什么? // 最后一个 // 后的 String fileName = realPath.substring(realPath.lastIndexOf("\\")+1); //3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,使用URLEncoder.encode对中文文件名进行编码, resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8")); //4. 获取下载文件的输入流 FileInputStream in = new FileInputStream(realPath); //5. 创建缓冲区 int len = 0; byte[] buf = new byte[1024]; //6. 获取OutputStream对象 ServletOutputStream out = resp.getOutputStream(); //7. 将FileOutputStream流写入到buffer缓冲区 // 使用OutputStream将缓冲区中的数据输出到客户端 while((len=in.read(buf))!=-1){ out.write(buf,0,len); } in.close(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行--> <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>down</servlet-name> <servlet-class>com.ruasib.servlet.FileDownServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>down</servlet-name> <url-pattern>/down</url-pattern> </servlet-mapping> </web-app>
-
生成验证码
package com.ruasib.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置客户端每隔3秒自动刷新页面
resp.setHeader("refresh","3");
// 创建带缓冲区的图片对象,就相当于创建一个画板
BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
// 使用笔画出图片
Graphics2D graphics2D = (Graphics2D) image.getGraphics(); // 笔
// 设置笔的颜色
graphics2D.setColor(Color.white);
graphics2D.fillRect(0,0,80,20);
// 给图片写数据
graphics2D.setColor(Color.BLUE);
graphics2D.setFont(new Font(null,Font.BOLD,20));
graphics2D.drawString(makeNum(),0,20);
// 将图片返回到客户端
resp.setContentType("image/jpg");
// 网站存在缓存 ,不让网站缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
// 将图片写给浏览器
boolean write = ImageIO.write(image,"jpg",resp.getOutputStream());
}
private String makeNum() {
Random random = new Random();
String num = random.nextInt(9999)+"";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4 - num.length(); i++) {
sb.append(0);
}
return sb.toString()+ num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>img</servlet-name>
<servlet-class>com.ruasib.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>img</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
2、实现重定向
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// // 实现重定向
// resp.setHeader("Location","/res/img");
// // 重定向状态码:302
// resp.setStatus(302);// HttpServletResponse.SC_FOUND
resp.sendRedirect("/res/img"); // 重定向
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>img</servlet-name>
<servlet-class>com.ruasib.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>img</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>rs</servlet-name>
<servlet-class>com.ruasib.servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>rs</servlet-name>
<url-pattern>/rs</url-pattern>
</servlet-mapping>
</web-app>
面试题:请你聊聊重定向和转发的区别?
相同点:
- 页面都会跳转
不同点:
- 请求转发时,url不会发生变化
- 重定向时,url地址栏会发生变化
转发和重定向
转发特点:
1.一次请求
2.地址不变
3.一个请求只有一个request,A和B可以通过他共享数据
4.只能转发到项目内部的资源
重定向的特点
1.二次请求
2.地址不变
3.二个请求有两个request,A和B无法通过他共享数据
4.可以重定向到项目外部的资源
test
小测试
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
// 重定向 ,一定要主要路径,否则404
resp.sendRedirect("/res/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>request</servlet-name>
<servlet-class>com.ruasib.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>request</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
<%--index.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<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"/>
<input type="submit">
</form>
</body>
</html>
<%-- success.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>success</h1>
</body>
</html>
运行结果:
6.7、 HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
获取前端参数,并请求转发
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println("=========================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("=========================");
// / 表示当前web项目
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.ruasib.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
<%--index.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h1>登录</h1>
<div style="text-align: center">
<form action="${pageContext.request.contextPath}/login" method="post">
用户名:<label>
<input type="text" name="username" value="">
<br>
密码:<input type="password" name="password" value=""><br>
爱好:
<input type="checkbox" name="hobby" value="女孩">女孩
<input type="checkbox" name="hobby" value="代码">代码
<input type="checkbox" name="hobby" value="唱歌">唱歌
<input type="checkbox" name="hobby" value="电影">电影
</label>
<input type="submit">
</form>
</div>
</body>
</html>
<%--success.jsp--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>
7、Cookie、Session
7.1、会话(Session)
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称为会话。
有状态会话:一个客户端来访问过服务器,下次再访问,服务器会知道这个客户端城景来过,称为有状态会话
一个网站,服务器怎么知道客户端访问过?
1、服务端给客户端一个信件,客户端下次访问带上信件就可以了(cookie)
2、服务器登记你来过了,下次来的时候服务器来匹配客户端;(session)
7.2、保存会话的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息,我们可以将信息或者数据放在Session中。
常见案例:网站登录后,就不需要再登录了。第二次访问直接上去了。
7.3、Cookie
- 从请求中拿到Cookie信息
- 服务器响应给客户端cookie
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
// 保存用户上一次访问的时间
public class CookieDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 服务器,告诉你,你来的时间,把这个时间封装成一个信件,你下次带来,我就知道你来了
// 解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
// 获取输出流
PrintWriter out = resp.getWriter();
//Cookie, 服务器从客户端获取到
Cookie[] cookies = req.getCookies();// 这里返回数组,说明Cookie可能存在多个
// 判断Cookie是否存在
if (cookies!=null){
// 如果存在,则取出数组中的Cookie
out.write("你上一次访问的时间是:");
for (Cookie cookie:cookies
) {
if(cookie.getName().equals("lastLoginTime")){
// 获取Cookie的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toString());
}
}
}else {
out.write("这是你第一次访问本站");
}
// 服务端给客户端响应Cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis()+"");
// 设置 cookie最长的存活时间 ,即有效期为以 1 天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo1</servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo1</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
</web-app>
cookie:一般会保存再本地用户目录下appdata;
一个网站cookie是否存在上限?
- 一个cookie只能保存一个信息;
- 一个web站点可以给浏览器发送多个cookie,每个站点最多存放20个cookie;
- cookie大小有限制 ,4kb;
- 300个cookie为浏览器存放上限
删除Cookie:
- 不设置有效期,关闭浏览器就会自动失效;
- 设置有效期时间为0
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CookieDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建一个cookie,名字要和要删除的cookie一样
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 设置cookie的有效期为0
cookie.setMaxAge(0);
// 响应cookie给客户端
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo2</servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo2</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
先通过/c1
路径生成cookie,后通过\c2
路径删除cookie,由下列两图片看出cookie已经被删除
解决中文编码问题:
// 通过使用URLEncoder.encode("阿迪", "utf-8")函数,进行编码,
// 使用 URLDecoder.decode("阿迪","utf-8")函数,进行解码
// 上述两个方法,传入的参数都是字符串,第一个参数为要进行编码/解码的数据,第二个参数是需要转换成的编码类型
package com.ruasib.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class CookieDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
System.out.println("123");
// 获取 输出流
PrintWriter out = resp.getWriter();
// 获取cookie
Cookie[] cookies = req.getCookies();
// 判断是否有cookie
if (cookies != null){
out.write("上一次访问时间是:");
// 遍历查找cookie
for (Cookie cookie :cookies
) {
System.out.println(cookie.getName());
if(cookie.getName().equals("name")){
String value = URLDecoder.decode(cookie.getValue(),"utf-8");
out.write(value);
System.out.println(value);
}
}
}else{
out.write("第一次访问");
}
// 新建一个cookie
Cookie cookie = new Cookie("name", URLEncoder.encode("阿达","utf-8"));
cookie.setMaxAge(24*60*60);
// 给客户端响应cookie
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo3</servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo3</servlet-name>
<url-pattern>/c3</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
获取到了浏览器的所有cookie
7.4、Session(重点)
<!-- 配置session的失效时间,以分钟为单位-->
<session-config>
<!-- 设置15分钟后,session自动失效-->
<session-timeout>15</session-timeout>
</session-config>
什么是Session:
- 服务器会给每一个用户(浏览器)创建一个Seesion对象
- 一个Session独占一个服务器,只要服务器没有关闭,这个服务器就存在
- 用户登录之后,整个网站它都可以访问;常用于:1.保存用户信息,2.保存购物车信息等等
Session与Cookie的区别:
- cookie是把用户的数据写给用户的浏览器,浏览器保存
- session 是把用户的数据写到用户独占session中,服务端保存,(保存重要的信息,减少服务器资源的浪费)
- session对象由服务器创建
使用场景:
- 保存一个登录用户的信息
- 购物车信息
- 在整个网站中经常使用的数据,我们将它保存在Session中
往session中存数据
package com.ruasib.session;
import com.ruasib.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class SessionDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 往sessoion中存对象
// 解决乱码问题
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
req.setCharacterEncoding("utf-8");
// 获取session对象
HttpSession session = req.getSession();
// 往session中存数据
session.setAttribute("person",new Person());
// 获取session的id
String sessionId = session.getId();
if (session.isNew()){
resp.getWriter().write("session创建,Id="+sessionId);
}else {
resp.getWriter().write("session已经在服务器中存在,Id="+sessionId);
}
// Session 创建的时候做了什么事情:
// Cookie cookie = new Cookie("JSESSIONID",sessionId);
// resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
往session中存和取对象
通过setAttribute(key,value)方法存对象,getAttribute(key)方法取对象,其中key-value为键值对,简单来说,就是一个key只能对应一个value, 比如 ”person“ 就是key ,value 就是 Person 对象
package com.ruasib.session;
import com.ruasib.pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.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());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
删除session中的数据,注销session
注销session后,服务器会自动销毁当前的sessionID,然后生成一个新的sessionID
package com.ruasib.session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
// 获取session对象
HttpSession session = req.getSession();
// 将person从session中删除
session.removeAttribute("person");
// 手动注销session,将session注销后,会自动生成一个新的sessionId
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
以上3个Servlet类的配置文件
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>CookieDemo1</servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo1</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CookieDemo2</servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo2</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CookieDemo3</servlet-name>
<servlet-class>com.ruasib.servlet.CookieDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CookieDemo3</servlet-name>
<url-pattern>/c3</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SessionDemo1</servlet-name>
<servlet-class>com.ruasib.session.SessionDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionDemo1</servlet-name>
<url-pattern>/s1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SessionDemo2</servlet-name>
<servlet-class>com.ruasib.session.SessionDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionDemo2</servlet-name>
<url-pattern>/s2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SessionDemo3</servlet-name>
<servlet-class>com.ruasib.session.SessionDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SessionDemo3</servlet-name>
<url-pattern>/s3</url-pattern>
</servlet-mapping>
<!-- 配置session的失效时间,以分钟为单位-->
<session-config>
<!-- 设置15分钟后,session自动失效-->
<session-timeout>15</session-timeout>
</session-config>
</web-app>
8、JSP
8.1、什么是JSP
Java Server Pages: java 服务端端页面,也和Servlet 一样,用于动态Web 技术!
最大的特点:
- 写jsp就像写HTML
- 区别:
- HTML只能给用户提供静态的数据
- JSP页面中可以嵌入java代码,为用户提供动态数据
8.2、JSP 原理
思路:JSP到底怎么执行的
-
在代码层面没有任何问题
-
服务器内部工作
Tomcat中有一个work目录;
在IDEA中使用Tomcat的话会在IDEA的Tomcat中生成一个work目录
一般位于C盘下的用户文件夹下的Admin下的.Intellijidea下存在一个index_jsp.class,
注意:
- AppData是隐藏文件,如果不打开显示隐藏文件是无法看到该文件夹的
- 如果你的项目没有发布到服务器并且没有访问过对应的路径下的
jsp
文件,那么你的项目是无法找到编译后的xxx_jsp.class
文件的
没有发布项目的时候该目录下的状态
发布项目并访问相应路径后的状态
C:\Users\asd\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-session-cookie_2\work\Catalina\localhost\ROOT\org\apache\jsp
C:\Users\asd\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Unnamed_javaweb-session-cookie_2\work
// asd 为电脑的管理员名
// 其中,Unnamed_javaweb-session-cookie_2 是我当前运行的项目
// 当打开该路径下的文件夹,会发现页面打开文件到最后一个文件时jsp页面转变成了java类
在你安装的tomcat中work目录下,会存放将默认的jsp文件编译成class的文件:
E:\Dev_Language\Tomcat\apache-tomcat-8.0.20\work\Catalina\localhost\ROOT\org\apache\jsp
浏览器向服务器发送请求,不过访问什么资源,其实都是在访问Servlet
JSP最终也会被转换成一个java类,其本质就是一个Servlet
// 初始化
public void _jspInit() {}
// 销毁
protected void _jspDestroy() {}
public abstract void _jspService(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException;
1.判断请求
2.内置一些对象
final javax.servlet.jsp.PageContext pageContext;// 页面上下文
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.http.HttpSession session = null // session
HttpServletRequest req // 请求
HttpServletResponse resp // 响应
3、输出页面增加的代码
response.setContentType("text/html; charset=UTF-8"); // 设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, false, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
4.以上的这些对象可以直接在jsp页面中直接使用
在JSP页面中:
只要是java代码就会原封不动的输出;
如果是HTML代码,就会转化为:
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>$Title$</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write(" $END$\n");
将上面类似的代码输出到前端。
8.3、JSP的基础语法
任何语言都有自己的语法,java有。jsp作为java技术的一种应用也有,它用于一些自己扩充的语法,java所有所有语法都支持!
基本模板代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>标题</title>
</head>
<body>
<%-- 代码 --%>
</body>
</html>
JSP表达式
<%--
JSP 表达式
作用:用来输出数据 输出到客户端
语法:<%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
JSP脚本片段
<%--
JSP 脚本片段
--%>
<%
int sum = 0;
for (int i = 0; i<=100;i++){
sum += i;
}
out.print("<h1>sum="+sum+"</h1>");
%>
<hr>
<%--在java代码直接嵌入HTML--%>
<%
int x = 10;
out.print(x);
%>
<p>这是一个JSP文档</p>
<%
int y = 5;
out.print(y);
%>
<hr>
<%--在Java代码中嵌入HTML元素,并且将java代码分割--%>
<%
for (int i = 0; i < 3; i++) {
%>
<h2>Hello,world <%= i %></h2>
<%
}
%>
jsp声明
会被编译到JSP生成java的类中!其他的jsp
脚本片段会被生成到_jspService
方法中。在jsp
中嵌入java代码即可
<%--
JSP声明 将变量,方法定义到类中
--%>
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void ruasib(){
System.out.println("进入了方法ruasib");
}
%>
执行代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
JSP 表达式
作用:用来输出数据 输出到客户端
语法:<%= 变量或表达式%>
--%>
<%= new java.util.Date()%>
<hr/>
<%--
JSP 脚本片段
--%>
<%
int sum = 0;
for (int i = 0; i<=100;i++){
sum += i;
}
out.print("<h1>sum="+sum+"</h1>");
%>
<hr>
<%--在java代码直接嵌入HTML--%>
<%
int x = 10;
out.print(x);
%>
<p>这是一个JSP文档</p>
<%
int y = 5;
out.print(y);
%>
<hr>
<%--在Java代码中嵌入HTML元素,将java代码分割--%>
<%
for (int i = 0; i < 3; i++) {
%>
<h2>Hello,world <%= i %></h2>
<%
}
%>
<hr>
<%--
JSP声明 将变量,方法定义到类中 使用 <%! 要定义到类中的方法或者变量 %>
--%>
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void ruasib(){
System.out.println("进入了方法ruasib");
}
%>
</body>
</html>
查看生成的xxx_jsp.class
结果如下:
控制台输出:
自定义错误页面
<%-- jsp2.jsp : 发生错误的页面--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--定义发生错误页面后的跳转目标--%>
<%@page errorPage="error/err.jsp" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int i = 1/0;
%>
</body>
</html>
<%--500.jsp :发生错误后跳转进来的页面--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>自定义错误页面</h1>
<img src="../img/500.jpg" alt="">
</body>
</html>
文件结构:
运行结果:
通过配置web.xml
文件来配置错误页面
<!--web.xml 特别注意:复制时请将此行删除,并且不能留空行-->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<%--404页面错误--%>
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<%--500页面错误--%>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
</web-app>
对应的jsp文件
<!-- 404.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<img src="../img/404.jpg" alt="">
</body>
</html>
<!-- 500.jsp 在上面 -->
运行结果:
遇到的问题:图片无法加载出来
原因:
在web项目发布以后,idea会在target
目录下导出你的文件,然后在浏览器访问你的数据时,访问的是你target
目录下的文件。比如我的上面说的无法加载出来的404.jpg
图片,就是因为maven
存在资源导出问题,资源导出问题解决方案,在我发布的5.11
章节中。
或者直接将target目录下没有的文件全部复制到相应的位置就能解决了
当target
目录下存在404.jpg
后,就能看到图片了
8.4、JSP指令和标签
指令 | 描述 |
---|---|
<%@ page … %> | 定义页面的依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include … %> | 包含其他文件 |
<%@ taglib … %> | 引入标签库的定义,可以是自定义标签 |
标签 | 描述 |
---|---|
jsp:include | 用于在当前页面中包含静态或动态资源 |
jsp:useBean | 寻找和初始化一个JavaBean组件 |
jsp:setProperty | 设置 JavaBean组件的值 |
jsp:getProperty | 将 JavaBean组件的值插入到 output中 |
jsp:forward | 从一个JSP文件向另一个文件传递一个包含用户请求的request对象 |
jsp:plugin | 用于在生成的HTML页面中包含Applet和JavaBean对象 |
jsp:element | 动态创建一个XML元素 |
jsp:attribute | 定义动态创建的XML元素的属性 |
jsp:body | 定义动态创建的XML元素的主体 |
jsp:text | 用于封装模板数据 |
<!--jsp3.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- @include 会将 两个页面合二为一--%>
<%-- 网页的头--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%-- 网页的尾--%>
<%@include file="common/footer.jsp"%>
<hr>
<%--jsp标签
jsp:include : 拼接页面,本质还是3个页面
--%>
<%-- 网页的头--%>
<jsp:include page="common/header.jsp"/>
<h1>网页主体</h1>
<%-- 网页的尾--%>
<jsp:include page="common/footer.jsp"/>
</body>
</html>
<!--header.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>i am header</h1>
<!--footer.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>i am footer</h1>
文件结构:
运行结果:
8.5、JSP内置对象
对象 | 描述 |
---|---|
request | HttpServletRequest类的实例 |
response | HttpServletResponse类的实例 |
out | PrintWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
exception | exception 类的对象,代表发生错误的 JSP 页面中对应的异常对象 |
存取数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 内置对象--%>
<%
// 保存的数据中只在一个页面中有效
pageContext.setAttribute("name1","阿迪1");
// 保存的数据只在一次请求中有效,请求转发会携带这个数据
request.setAttribute("name2","阿迪2");
// 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器,
session.setAttribute("name3","阿迪3");
// 保存的数据在服务器中有效,从打开服务器到关闭服务器
application.setAttribute("name4","阿迪4");
%>
<%--
脚本片段中的代码,会被原封不动的生成到 xxx_jsp.java中
要求:这里的代码必须要跟Java的语法一致
--%>
<%
//从 pageContext取出,我们通过寻找的方式来找出其中的数据
// 从底层到高层(作用域):page -> request -> session -> application
// 双亲委派机制:
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5"); // 不存在
%>
<%--
注意:EL表达式 ` ${ 变量或者表达式} ` 等价于 ` <%= 变量或者表达式 %> `
--%>
<h1>页面一,存数据的页面</h1>
<h1>EL 表达式取出的值:</h1>
<h4>${name1}</h4>
<h4>${name2}</h4>
<h4>${name3}</h4>
<h4>${name4}</h4>
<h4 style="color: yellow">${name5}</h4>
<h4 style="color: red"><%= name5%></h4>
</body>
</html>
setAttribut方法
<%
// 对setAttribut方法进行扩展,四个作用域
pageContext.setAttribute("age1","1",PageContext.PAGE_SCOPE);
// 等价于 pageContext.setAttribute("age1","1");
pageContext.setAttribute("age2","2",PageContext.REQUEST_SCOPE);
// 等价于 request.setAttribute("age2","2");
pageContext.setAttribute("age3","3",PageContext.SESSION_SCOPE);
// 等价于 session.setAttribute("age3","3");
pageContext.setAttribute("age4","4",PageContext.APPLICATION_SCOPE);
// 等价于 application.setAttribute("age4","4");
%>
request: 客户端向服务器发送请求,产生数据,用户看完就没用了,比如新闻,用户看完就没用的;
session: 客户端向服务端发送请求,产生的数据,用户用完以后还要用,比如购物车
application: 客户端向服务端发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如聊天数据;
一般这些作用域可以跟页面跳转方法配合使用pageContext.forward(s);
s就是你要跳转的页面,在跳转之前可以往这些容器中存数据,然后再别的页面取出数据。
8.6、JSP标签、JSTL标签、EL表达式
maven 导入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--servlet 依赖-->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<!--jsp 依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!--jstl 依赖-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard 标签库-->
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
</project>
EL表达式:${ }
- 获取数据
- 执行运算
- 获取web开发的常用对象
- 调用java方法
<!--jspTag1.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>JspTag1.jsp</h1>
<jsp:forward page="jspTag2.jsp">
<jsp:param name="name" value="ruasib"/>
<jsp:param name="age" value="20"/>
</jsp:forward>
</body>
</html>
<!--jspTag2.jsp-->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>jspTag2.jsp</h1>
名字:<%= (String) request.getParameter("name")%>
年龄:<%= (String) request.getParameter("age")%>
</body>
</html>
<%
User user = (User) request.getSession().getAttribute("userSession");
%>
<%= user.getUserName()%>
<!--等价于-->
${userSession.userName}
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和java代码一样
JSTL标签类别
- 核心标签
核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
标签 | 描述 |
---|---|
<c:out> | 用于在JSP中显示数据,就像<%= … > |
<c:set> | 用于保存数据 |
<c:remove> | 用于删除数据 |
<c:catch> | 用来处理产生错误的异常状况,并且将错误信息储存起来 |
<c:if> | 与我们在一般程序中用的if一样 |
<c:choose> | 本身只当做<c:when> 和<c:otherwise> 的父标签 |
<c:when> | <c:choose> 的子标签,用来判断条件是否成立 |
<c:otherwise> | <c:choose> 的子标签,接在<c:when> 标签后,当<c:when> 标签判断为false 时被执行 |
<c:import> | 检索一个绝对或相对 URL,然后将其内容暴露给页面 |
<c:forEach> | 基础迭代标签,接受多种集合类型 |
<c:forTokens> | 根据指定的分隔符来分隔内容并迭代输出 |
<c:param> | 用来给包含或重定向的页面传递参数 |
<c:redirect> | 重定向至一个新的URL. |
<c:url> | 使用可选的查询参数来创造一个URL |
如需详细了解请移步菜鸟教程
- 格式化标签
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
- SQL 标签
JSTL SQL标签库提供了与关系型数据库(Oracle,MySQL,SQL Server等等)进行交互的标签。引用SQL标签库的语法如下:
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
- XML 标签
JSTL XML标签库提供了创建和操作XML文档的标签。引用XML标签库的语法如下:
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
- JSTL 函数
JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
JSTL标签库使用步骤
- 引入对应的
taglib
- 使用其中的方法
- 在tomcat中也需要引入jstl的包,否则会报错:jstl解析错误
<%-- jstl 标签 <c:if>的使用 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>if 测试</h4>
<form action="coreIf.jsp" method="get">
<%--
使用EL表达式获取表单中的数据
语法:${param.参数名}
--%>
<label>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</label>
</form>
<%--判断如果用户名是管理员,则登录成功--%>
<%-- 登录java代码实现
<%
if (request.getParameter("username").equals("admin")){
out.print("登录成功");
}
%>
--%>
<%--判断如果提交的用户是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎你"></c:out>
</c:if>
<c:out value="${isAdmin}"></c:out>
</body>
</html>
<%--
jstl 标签 <c:set >、<c:choose>、<c:when>的使用
其中 <c:choose>、<c:when> 配合使用与switch有些类似
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%-- 定义一个变量叫 socre ,设置值为 85--%>
<c:set var="score" value="85"></c:set>
<c:choose>
<c:when test="${score>=90}">
你的成绩优秀
</c:when>
<c:when test="${score>=80}">
你的成绩良好
</c:when>
<c:when test="${score>=60}">
你的成绩一般
</c:when>
<c:when test="${score<60}">
你的成绩不及格
</c:when>
</c:choose>
</body>
</html>
<%-- jstl 标签 <c:forEach>的使用 --%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="java.util.ArrayList" %><%--
Created by IntelliJ IDEA.
User: asd
Date: 2021/7/3
Time: 21:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
// 定义集合,将数据存入集合
ArrayList<String> people = new ArrayList<String>();
people.add("张三");
people.add("李四");
people.add("王五");
people.add("赵六");
people.add("前七");
request.setAttribute("list",people);
%>
<%--
var = "people" 定义一个变量, people
items = "${list}}" 要遍历的对象 list
等价于java代码:
for (String people:list) {
out.print(people);
}
--%>
<c:forEach var="people" items="${list}">
名字:<c:out value="${people}"></c:out> <br>
</c:forEach>
<hr>
<%--
var="people" 定义一个变量,people
items="${list}" ,要遍历的对象,list
begin="1" , 开始遍历的位置
end="3" , 结束遍历的位置
step="2" , 步长
等价于java代码:
ArrayList<String> people = new ArrayList<String>();
people.add("张三");
people.add("李四");
people.add("王五");
people.add("赵六");
people.add("前七");
request.setAttribute("list",people);
people = (ArrayList<String>) request.getAttribute("list");
for (int i = 1; i <= 3; i+=2) {
String temp = people.get(i);
out.println(temp);
}
--%>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
名字:<c:out value="${people}"></c:out> <br>
</c:forEach>
</body>
</html>
9、JavaBean
实体类
JAVABean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对于的get/set方法
一般用来和数据库的字段做映射:ORM
ORM:对象关系映射
- 表—>类
- 字段–>属性
- 行–>对象
id | name | age | address |
---|---|---|---|
1 | 阿笛 | 10 | asd |
2 | 阿笛1 | 11 | asd |
3 | 阿笛2 | 20 | asd |
javabean的用法
<%
// People people = new People();
%>
<jsp:useBean id="people" class="com.ruasib.People" scope="page"></jsp:useBean>
<%
// people.setId(1);
// people.setName("阿笛");
// people.setAge(10);
// people.setAddress("asd");
%>
<jsp:setProperty name="people" property="id" value="1"></jsp:setProperty>
<jsp:setProperty name="people" property="name" value="阿笛"></jsp:setProperty>
<jsp:setProperty name="people" property="age" value="10"></jsp:setProperty>
<jsp:setProperty name="people" property="address" value="asd"></jsp:setProperty>
<%
// out.print("id:"+people.getId());
// out.print("name:"+people.getName());
// out.print("age:"+people.getAge());
// out.print("address:"+people.getAddress());
%>
id:<jsp:getProperty name="people" property="id"/>
name:<jsp:getProperty name="people" property="name"/>
age:<jsp:getProperty name="people" property="age"/>
address:<jsp:getProperty name="people" property="address"/>
10、MVC三层架构
什么是MVC: Model、View、Controller 模型、视图、控制器
10.1、双层架构
用户直接访问控制层,控制层就可以直接操作数据库
servlet --- curd--->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理jdbc、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的,否则就加多层
10.2、MVC三层架构
Model:
- 业务处理:业务逻辑(Service)
- 数据持久层:CRUD (Dao)
View:
- 展示数据
- 提供链接发起的Servlet请求(a,form,img…)
Controller (Servlet)
- 接收用户的请求:(req:请求参数、Session信息…)
- 交给业务层对应的代码
- 控制视图的跳转
登录-->接收用户的登录请求-->处理用户的请求(获取用户登录的参数,username,password)-->交给业务层处理登录业务(判断用户名密码是否正确:数据库事务)-->Dao层查询数据库中的用户名和密码是否正确-->数据库
11、Filter
Filter:过滤器,用来过滤网站的数据;或者是通过不同的vip等级进入不同的页面
- 处理中文乱码
- 登录验证
Filter开发步骤:
- 导包
- 编写过滤器,实现过滤器接口
class 类名 implements javax.servlet.Filter
并重写方法
servlet:
public class ShowServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("你好");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
字符编码过滤器
将字符编码转化成utf-8
public class CharacterEncodingFilter implements Filter {
// 初始化:在服务器启动时调用此方法
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter 初始化");
}
// Chain:链,可以有很多个过滤器
/*
* 1,过滤器中的所以代码,在过滤特定请求的时候都会执行
* 2,必须要让过滤器继续通行: filterChain.doFilter(servletRequest,servletResponse);
* */
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
System.out.println("过滤前");
// 让我们的请求继续通行,如果不写,程序就在这里就被拦截了
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("过滤后");
}
// 销毁:在服务器停止的时候调用此方法
public void destroy() {
System.out.println("CharacterEncodingFilter 销毁");
}
}
3.在web.xml配置Filter
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>com.nguyen.servlet.ShowServlet</servlet-class>
</servlet>
<!-- 有过滤器-->
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<!-- 没有过滤器-->
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
<!-- 配置过滤器,-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.nguyen.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
</web-app>
12、监听器
实现一个监听器的接口,统计当前在线人数
OnlineCountListener.java
// 统计网站在线人数,统计session
public class OnlineCountListener implements HttpSessionListener {
// 创建session监听:
// 一旦创建一个Session就会触发一次该方法
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer)servletContext.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(1);
}else {
// 获取当前在线人数,一旦有新的用户上线就对在线人数+1
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
// 销毁session监听
// 一旦销毁Session就会触发一次此方法
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer)servletContext.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>当前有 <span style="color: blue"><%= request.getServletContext().getAttribute("OnlineCount")%></span> 人在线</h1>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 注册监听器-->
<listener>
<listener-class>com.nguyen.listener.OnlineCountListener</listener-class>
</listener>
</web-app>
13、过滤器、监听器常见应用
监听器在GUI编程中经常使用
拦截登录实现
此功能使用到第11节的字符编码过滤器
无过滤器情况
Constant.java
定义session常量,存放用户信息
package com.nguyen.util;
public class Constant {
public final static String USER_SESSION = "USER_SESSION";
}
error.jsp
错误页面:输入地址错误,或者登录失败都会进入此页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>错误</h1>
<h3>没有权限或者密码错误</h3>
</body>
</html>
login.jsp
登录界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/servlet/login" method="post">
<h1>登录</h1>
<label>
<input type="text" name="username">
<input type="submit" value="登录">
</label>
</form>
</body>
</html>
success.jsp
登录成功后才能进入该页面
<%@ page import="com.nguyen.util.Constant" %><%--
Created by IntelliJ IDEA.
User: nguyen
Date: 2021/7/18
Time: 12:44
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
// 检查是否存在user_session,如果没有登录,则不允许进入该页面,并且自动跳转到登录界面
Object o = request.getSession().getAttribute(Constant.USER_SESSION);
if (o==null){
response.sendRedirect("/login.jsp");
}
%>
<h1>主页</h1>
<p><a href="${pageContext.request.contextPath}/servlet/logout">注销</a></p>
</body>
</html>
LoginServlet.java
服务器响应登录请求
package com.nguyen.servlet;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
System.out.println(username);
if ("admin".equals(username)){//登录成功
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
// 重定向
resp.sendRedirect("/sys/success.jsp");
}else {// 登录失败
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
LogoutServlet.java
服务器响应注销请求
package com.nguyen.servlet;
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object o = req.getSession().getAttribute(Constant.USER_SESSION);
//客户端发起注销请求时,从session中删除User_session
if(o!=null){
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect("/login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
当且仅当用户通过登录界面,并且输入正确的账号信息时才能正常登录到主页面,否则会自动跳转到登录界面
注销后,无法进入主页
使用过滤器
由于jsp在理论上只需要实现展示页面的功能,所以不应该在jsp文件中添加主页访问权限(即只有登录了才能进入主页的权限),所以应该新增一层过滤器,以解决这一方面的问题
在无过滤器代码文件的基础上,仅更改success.jsp
文件,并新增一个过滤器
success.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>主页</h1>
<p><a href="${pageContext.request.contextPath}/servlet/logout">注销</a></p>
</body>
</html>
SysFilter.java
过滤器:用于处理主页访问权限问题
package com.nguyen.filter;
import com.nguyen.util.Constant;
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 获取session
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 获取user_session,如果登录了,则可以访问主页,否则跳转到错误页面
Object o = request.getSession().getAttribute(Constant.USER_SESSION);
if(o==null){
response.sendRedirect("/error.jsp");
}
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.nguyen.servlet.LoginServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.nguyen.servlet.LogoutServlet</servlet-class>
</servlet>
<!-- 有过滤器-->
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>
<!-- 配置过滤器,-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.nguyen.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.nguyen.filter.SysFilter</filter-class>
</filter>
<!-- 任何要访问sys下的请求都要经过该过滤器-->
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
</web-app>
正常登录时,可以进入主页,当直接通过地址进入主页时,会对该请求进行过滤,自动跳转到错误页面,以下图片为未登录的请求的请求。
14、JDBC
需要jar包的支持:
- java.sql
- javax.sql
- mysql-conneter , java 连接mysql数据库的驱动器(需要导入)
test.java
查询users表中的数据
package com.nguyen.text;
import java.sql.*;
public class test {
public static void main(String[] args) {
// 解决字符编码问题
String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=true&useUnicode=true&" +
"characterEncoding=utf-8";
String user = "root";
String password = "root";
try {
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.连接数据库
Connection conn = DriverManager.getConnection(url,user,password);
// 3.向数据库发生SQL的对象,PrepareStatement :CURD
String sql = "select * from users";
PreparedStatement statement = conn.prepareStatement(sql);
// 5.执行查询语句
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String password1 = resultSet.getString("password");
String email = resultSet.getString("email");
Date birthday = resultSet.getDate("birthday");
System.out.println("id="+id);
System.out.println("name="+name);
System.out.println("password="+password1);
System.out.println("email="+email);
System.out.println("birthday="+birthday);
}
resultSet.close();
statement.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
事务
-
基本概念:事务是恢复和并发控制的基本单位。
-
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
简单来说,就是事务提交的时候要么成功,要么失败。
ACID原则就是保证数据安全
开始事务
事务提交 commit()
事务回滚 rollback()
关闭事务
Junit单元测试
依赖
pom.xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
TestJDBC.java
package com.nguyen.text;
import org.junit.jupiter.api.Test;
public class TestJDBC {
@Test
public void hello(){
System.out.println("hello");
}
}
直接运行hello()
方法得到如下结果:
事务实例
转账操作,无异常则可以更新数据库状态,有异常会自动回滚事务
TestJDBC.java
package com.nguyen.text;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
@Test
public void hello(){
String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=true&useUnicode=true&" +
"characterEncoding=utf-8";
String user = "root";
String password = "root";
String Driver = "com.mysql.jdbc.Driver";
Connection conn = null;
try {
Class.forName(Driver);
conn = DriverManager.getConnection(url, user, password);
// 关闭自动提交事务
conn.setAutoCommit(false);
String sql = "UPDATE account set money = money - 100 WHERE name = 'A'";
conn.prepareStatement(sql).executeUpdate();
String sql1 = "UPDATE account set money = money + 100 WHERE name = 'B'";
conn.prepareStatement(sql1).executeUpdate();
// 制造异常
int i =1/0;
// 提交事务
conn.commit();
System.out.println("提交成功");
} catch (Exception e) {
// 如果出现异常则回滚事务
try {
assert conn != null;
conn.rollback();
System.out.println("提交失败");
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
conn.close();
} catch (SQLException e2) {
e2.printStackTrace();
}
e.printStackTrace();
}
}
}
由于该代码中存在异常(0不能是分母),所以该更新操作会自动回滚,数据库的状态不会发生变化。
conn = DriverManager.getConnection(url,user,password);
// 3.向数据库发生SQL的对象,PrepareStatement :CURD
String sql = “select * from users”;
PreparedStatement statement = conn.prepareStatement(sql);
// 5.执行查询语句
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()){
int id = resultSet.getInt(“id”);
String name = resultSet.getString(“name”);
String password1 = resultSet.getString(“password”);
String email = resultSet.getString(“email”);
Date birthday = resultSet.getDate(“birthday”);
System.out.println(“id=”+id);
System.out.println(“name=”+name);
System.out.println(“password=”+password1);
System.out.println(“email=”+email);
System.out.println(“birthday=”+birthday);
}
resultSet.close();
statement.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
#### 事务
- 基本概念:事务是恢复和[并发控制](https://baike.baidu.com/item/并发控制)的基本单位。
- 事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为**ACID特性**。
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
简单来说,就是事务提交的时候要么成功,要么失败。
ACID原则就是保证数据安全
```java
开始事务
事务提交 commit()
事务回滚 rollback()
关闭事务
Junit单元测试
依赖
pom.xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
TestJDBC.java
package com.nguyen.text;
import org.junit.jupiter.api.Test;
public class TestJDBC {
@Test
public void hello(){
System.out.println("hello");
}
}
事务实例
转账操作,无异常则可以更新数据库状态,有异常会自动回滚事务
TestJDBC.java
package com.nguyen.text;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
@Test
public void hello(){
String url = "jdbc:mysql://localhost:3306/jdbc?useSSL=true&useUnicode=true&" +
"characterEncoding=utf-8";
String user = "root";
String password = "root";
String Driver = "com.mysql.jdbc.Driver";
Connection conn = null;
try {
Class.forName(Driver);
conn = DriverManager.getConnection(url, user, password);
// 关闭自动提交事务
conn.setAutoCommit(false);
String sql = "UPDATE account set money = money - 100 WHERE name = 'A'";
conn.prepareStatement(sql).executeUpdate();
String sql1 = "UPDATE account set money = money + 100 WHERE name = 'B'";
conn.prepareStatement(sql1).executeUpdate();
// 制造异常
int i =1/0;
// 提交事务
conn.commit();
System.out.println("提交成功");
} catch (Exception e) {
// 如果出现异常则回滚事务
try {
assert conn != null;
conn.rollback();
System.out.println("提交失败");
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
conn.close();
} catch (SQLException e2) {
e2.printStackTrace();
}
e.printStackTrace();
}
}
}
由于该代码中存在异常(0不能是分母),所以该更新操作会自动回滚,数据库的状态不会发生变化。