JavaWeb
1、JavaWeb简介
1.1、基本概念
JavaWeb:网页编程 B/S
- B/S即浏览器/服务器(browser/server),不需要安装客户端,采用浏览器浏览就可以了,指的是软件系统的结构.
网络编程:TCP/IP C/S
- C/S 指的就是 客户端/服务器 Client/server。
web开发:
- web,网页的意思。例如 www.baidu.com
- 静态web
- html, css
- 提供给所有人看的, 这个数据始终不会发生变化
- 动态Web
- 几乎是所有的网站。比如淘宝
- 提供给所有人看到数据始终会发生变化。 每个人在不同的事件,不同的地点看到的信息各不相同。从服务端获取数据,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应用程序编写完毕后, 如果想要提供给外界访问:就需要一个服务器来统一管理;
简单来说:web应用程序分为静态和动态的web,还需要URL即网络地址,存放东西的地方;配置文件和jar包用来实现连接的,这些和外部的连接 进行访问,就需要一个服务器:Tomcat。 我们需要把自己开发出来的Web程序放在我们服务器的webapps目录下。
1.3、静态web和动态web
静态web:
- x.html,*.htm 这种都是网页的后缀, 如果服务器上一直存在着这些东西, 我们就可以直接进行获取。 通信联络过程如下:
- 静态web存在的缺点:
- web页面没有办法进行动态更新,所有用户看到的都是同一个页面
- javaScript.在实际开发中用到最多
- VBScript
- 无法和数据库交互。因为它无法做到数据持久化,所以用户无法交互
动态web:
动态web的页面因人而异。 通信联络过程: 和静态web的请求响应几乎一样。不同的是,在服务端那里,动态web程序会进行动态资源和静态资源 web的调用,然后返回给客户端。 在静态web中,服务器只负责调用静态资源。
- 缺点:
- 在服务器中的动态web资源出现了错误, 就需要重新编写后台程序,重新发布;
- 会进行停机维护。 关闭服务,重新发布web资源。
- 优点:
- Web页面可以动态更新,可以实现真正用户交互。每个用户看到的是不同的页面,增强了用户体验性
- 它还能够与数据库进行交互。即JSP/Servlet部分和数据库之间的交互:数据持久化。
实现动态Web的手段:
- ASP :
- ASP是Active Server Page的缩写,意为“活动服务器网页”。ASP是微软公司开发的代替CGI脚本程序的一种应用,它可以与数据库和其它程序进行交互,是一种简单、方便的编程工具。
- 微软 IIS、采用C#、IIS。
- 维护成本高
- PHP:
- PHP的开发速度很快,功能强大,跨平台,代码简单。
- 局限性:无法承载大访问量的情况
- JSP / Servlet : B/S:浏览和服务器; C/S:客户端和服务端。
- SUN 公司 主要解决 B/S 架构
- 跨平台 (class文件)
- 语法像ASP (HTML嵌套Java代码)
- 可以承载三高问题带来的影响。 三高:高并发、高可扩、高性能。扩展数据库,提高用户体验性能。
Javaweb: 网页编程 B/s。B/S即浏览器/服务器(browser/server),不需要安装客户端,采用浏览器浏览就可以了,指的是软件系统的结构.
网络编程:TCP/IP C/S。C/S 指的就是 客户端/服务器 consumer/server, Client/server。
2、Web服务器
服务器是一种被动的操作,去处理一些用户的请求 和 给用户响应信息。
web服务器哪些:
- IIS:
微软的:ASP… windows中自带的。 - Tomcat (性能优良,非常的小,他是符合Web服务器最小的服务器,Apache)
- WebLogic
- WebShare
3、Tomcat
Tomcat 是Apache、Sun和其它一些公司及个人共同开发的。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。
3.1、Tomcat安装
Tomcat **官网:**https://tomcat.apache.org/
在官网下载Tomcat压缩包 *.zip。
将下载好的 Tomcat压缩包直接解压就可以。具体的文件信息:
启动和关闭Tomcat:打开bin文件进行操作。
- 启动:点击bin文件下的 startup.bat。
- 关闭:点击bin文件下的 startup.sh, 也可以直接关闭窗口。
出现的问题:
发现在点击启动后,进入网站搜索 localhost8080,无法出现界面,具体如下:
这种情况一般都是端口被占用了,或者端口号不对。 Tmocat默认的端口号为 8080.
解决办法:在这里我们运行 cmd ,dos命令查看 netstat -ano, 会发现我们的端口号被占用了。如下所示:
我们可以直接在任务管理器中关闭这个服务PID=6496的进程,也可以去修改端口号然后重新访问。
在这里,我们采取**修改端口号的方法:将conf文件即配置文件**中的打开,修改其中的端口连接位置,将8080改为8081:
<Connector URIEncoding="utf-8" port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
此时访问就得到了结果:
3.2、配置
修改配置的方法:
另外类似的去修改这个页面的方法如下: 然后搜索www.qinjiang.com,发现不能直接搜索到,但是可以百度一下就能搜索到此结果:
如果想直接搜索到:需要在c盘系统盘的 system32/64中的Drivers中的hosts去修改下localhost的名字,改为www.qinjiang.com。就能直接访问了。
改变端口号和主机名称:在下面的服务器核心文件中进行修改:
我们在前面进行了修改端口号。
可以配置启动的端口号:下面这是一些默认的:
- tomcat默认的端口号:8080
- MySQL:3306
- http:80
- https:443
修改配置的端口号命令:
<Connector URIEncoding="utf-8" port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
可以去进行配置的主机的名称:
- 默认的主机名为: localhost -> 127.0.01
- 默认的网站应用存放位置为: webapps
- 修改主机名配置代码如下:
<Host name="www.qiqi.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
请你谈谈网站是如何进行访问的?
- 输入一个域名:即www.qiqi.com等 回车
- 检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;
- 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
127.0.0.1 www.qiqi.com - 没有:去DNS服务器找找到的话就返回,找不到就返回找不到
先在本地的系统盘中的 hosts配置文件下去进行查找这个域名映射; 没有的话就去寻找 DNS服务器,在这里去寻找域名。 没有的话就代表不存在 找不到。
3.3、发表一个简单的web网站
将自己写的网站,放到服务器Tomcat中指定的web应用文件夹webapps下,就可以访问了。系统默认的是在webapps文件下的 ROOT文件中。
网站应该有的结构:
- webapps: Tomcat服务器的web目录
- ROOT
- study:网站的目录名
- Web-INF
- classes:java程序
- lib:web应用所依赖的jar包
- web.xml:网站配置文件
- index.html 默认的首页
例子:在这里只是简单增加了一个 默认的首页:
内容为:
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
此时运行 tomcat,访问 localhost:8080 的结果为:
4、HTTP详解
HTTP
超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它**指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应**。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。
4.1、什么是HTTP
HTTP(超文本传输协议)是一个简单的**请求-响应协议,它通常运行在TCP之上**。
- 文本: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:182.61.200.7:443
HTTP请求中的内容:
1.请求行
- 请求行中的 请求方式:GET
- 请求方式:Get,Post ,HEAD,DELETE,PUT,TRACT…
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。
2.消息头
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 告诉浏览器,它所支持的编码格式 GBK、 UTF-8 、GB2312
Accept-Language:告诉浏览器,它的语言环境
cache-Control:缓存控制
connection:告诉浏览器,请求完成是断开还是保持连接
Host:主机…/.
4.4、HTTP响应
服务器—响应----客户端
百度:
Cache-Control:private 缓存控制
Connection:keep-alive 连接
Content-Encoding:gzip 编码
Content-Type:text/html;charset=utf-8 类型
1.响应体
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: 告诉浏览器,它所支持的编码格式 GBK UTF-8 GB2312
Accept-Language:告诉浏览器,它的语言环境
cache-Control:缓存控制
connection:告诉浏览器,请求完成是断开还是保持连接
Host:主机…/.
Refrush:告诉客户端,多久刷新一次
Location:让网页重新定位;
2.响应状态码 (务必掌握)
200:请求响应成功 200
3xx:请求重定向
- 重定向:你重新到我给你新位置去;
4xx:找不到资源;404
5xx:服务器代码错误 500 502 网关错误
5、Maven详解
Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。网址为:https://maven.apache.org/
Maven
我为什么要学习这个技术?
- 在JavaWeb中,需要使用大量的jar包,我们手动去导入;
- 如何个够让一个东西自动帮我导入和配置这个jar包。
- 由此,Maven诞生了!
5.1、 Maven 项目架构管理工具
我们目前来就是方便导入jar包的!
Maven的核心思想:约定大于配置
- 有约束,不要去违反。
- Maven会规定好你该如何去编写我们java代码,必须按照这个规范
5.2 、下载安装Maven
下载完成后,解压即可;
5.2.1、配置环境变量
在我们的系统环境变量中
配置如下配置:
- M2_HOME :maven 目录下的bin目录
- MAVEN_HOME :maven的目录
- 在系统的path中配置 %MAVEN_HOME%\bin
在path目录下创建的:
测试结果:mvn -version
5.2.2、阿里云镜像
在配置文件 conf中进行修改:
- 镜像: mirrors。
- 使用阿里云镜像,在maven中进行下载包的速度比较快。 或者使用 nexus-aliyun 也可以。
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
<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.2.3、本地仓库
在 maven-repo中建立本地仓库。 注意:这个maven-repo是自己新建的一个文件夹。
建立一个本地仓库:localRepository
注意:这里是你安装的 maven 地址。 进行配置文件 **conf中的 setting.xml**中进行修改后,我的为:
- 建立本地仓库
<localRepository>/path/to/local/repo</localRepository>
<localRepository>D:\Java\apache-maven-3.6.3\maven-repo</localRepository>
可以用下面的进行maven的本地仓库创建;也可以用下一节讲的 IDEA使用Maven的时候进行本地仓库的建立。
方法一:
- 最后检查一下配置是否正确。 输入命令:mvn help:system
- 最后如果没有报错就说明配置好了。然后你会发现你自己建的maven仓库的文件夹下会有很多的文件包自动出来。这些就是maven从中央仓库下载下来的文件了。结果如下:
方法二:
- 见第6.1节
6、IDEA中的Maven操作
6.1、在IDEA中使用Maven
1.启动IDEA
2.创建一个 maven项目。 在这里选取了maven的模板 - webapp; java版本选择JDK8。
在这里选择 Maven的地址,即你安装好的路径; 选择设置文件 conf中的 setting.xml文件; 本地仓库的选择:
注意:如果上面没有选择自己安装的 Maven设置, IDEA会使用自带的。一定要选取自己安装的:
进入界面后,点击 Enable Auto-import,自动导入包:
maven环境创建成功的标志:
可能会出现错误 即代码中出现红色部分,然后在点击configure 进行配置。
3.观察此时的Maven-repo 即本地仓库中多出的文件:有我们原先用过的 io 包等。
4.在IDEA设置即setting选项版中找到maven:在创建。选择这里进行文件路径修改后,就不用在每次创建maven项目时 设置路径 本地仓库、配置文件这些路径选择了。
5.创建一个普通的Maven项目:
此时不勾选Maven模板,直接进行下一步 next:
普通的Maven项目中,没有jar包依赖的环境,没有这些jar包。
普通的maven项目中包含的文件信息有:
- main文件
- java。放置的是 java源代码。
- resource。 放置一些配置文件
- test文件:用于进行测试使用。
- pom.xml:编写配置文件,maven依赖等。
上面的第2步骤中:Maven项目是一个 javaweb中 maven-archetype-webapp的一个模板,所以里面会有相关的jar包,然后再配置Tomcat 后就能直接使用。 这个普通的,需要自己去建立这些包和 servlet 进行和服务器连接响应,即在java文件中编写java源代码,在resource中放置一些配置文件,在test文件中的java文件中进行测试。
这个pom.xml文件是用来编写配置文件的,让其与tomcat进行连接响应,存放jar包依赖环境。
这个有webapp模板的项目文件信息:这个只有在web应用下才会有:
6.标记文件夹目录:
对于上述的普通 maven项目文件, 如何标记java、resource文件,设置属性 存放的信息:
在原来的创建Maven项目中,即上面这个web的配置这种的,在src下新建两个文件Directory,分别为java和resource,然后将java文件设置为源码, resource设置为资源。
或者像下面这样进行配置:
Maven中的注意事项:配置资源导出
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
6.2、配置Tomcat
在我的IDEA2019中的选择地方为:点击**Add Configuration**选择,然后进行添加。
应该点击加号 + , 而不是直接点击Templates:
可以选择配置,来选择tomcat版本:
解决上述图中的警告问题:
必须要的配置:为什么会有这个问题:我们访问一个网站,需要制定一个文件夹名字
上述标记的位置就是 文件位置 访问时的URL路径,虚拟路径映射。当不写的时候,默认的路径就是 localhost:8080。
设置完成后,然后进行运行测试:
在浏览器端访问 localhost:8080的结果,是我们在这里修改后的 index.jsp文件, 这个是默认访问路径。
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
6.3、pom.xml文件
pom.xml是Maven的核心配置文件。
- 右边的 lifecycle是maven中的命令行操作;
- Plugins是插件。
- Dependencies是你导入的maven依赖,一个 jar包。 需要在这里显示了,才表示你导入maven依赖成功了。
点击右边的 lifecycle 中的clean就能把 target中的导入包逐渐删除。
pom.xml配置文件解析:
<?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>org.example</groupId>
<artifactId>javaweb-01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- Package: 项目的打包方式
jar:java应用
war: JavaWeb应用-->
<packaging>war</packaging>
<!-- 名字 这个name文件可以删除掉-->
<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>
<!--具体的jar包的地址-->
<dependency>
<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>
那么,对于我们创建的一个干净的Maven项目。又是如何导入 jar 包的呢?
- 我们原来是创建一个 lib文件夹,将自己下载好的 jar包导入后, 选择 add as library… 作为库来使用。
或者这样的;
- 在这里,对于一个干净的,我们不用手动下载导入 jar包,而是导入依赖后,让maven帮我们进行下载。且会自动帮你下载这个包有关的依赖。
- Maven自动导入jar包。 可以选择 Apache的maven官网地址:https://mvnrepository.com/ . 然后在里面搜索自己想要的 jar 包。
- 在这里,我们导入一个spring包:Spring Web MVC 网址为:https://mvnrepository.com/artifact/org.springframework/spring-webmvc
- 在 pom.xml中导入这个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>
<groupId>org.example</groupId>
<artifactId>javaweb-01-maven02</artifactId>
<version>1.0-SNAPSHOT</version>
<!--项目依赖-->
<dependencies>
<!--具体的jar包的地址-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--Maven会将这个包和它所依赖的其它jar包都下载下来-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.4</version>
</dependency>
</dependencies>
<!--在build中配置resource,为了防止资源导出时的失败-->
<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>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
6.4、全局默认配置Maven
不打开项目,在初始界面的 配置中进行Maven修改。
重新打开初始化界面的方法:intellij idea怎么设置软件启动时选择项目进入的网址: https://jingyan.baidu.com/article/9c69d48fe8a8c813c9024ea0.html
我想让我的IDEA每次打开默认界面:不勾选下面这两个
然后在初始化的界面中进行配置 Setting:
进行配置修改:
6.5、Maven默认web项目中的web.xml版本
将maven中的 web-app版本修改为和 Tomcat一个版本:
<!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>
</web-app>
修改如下:
<?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">
</web-app>
永久修改 web,xml版本的方法:
找到创建webapp 这个maven模板所在的位置:D:\Java\apache-maven-3.6.3\maven-repo\org\apache\maven\archetypes\maven-archetype-webapp\1.4
用解压软件打开,找到其中的web.xml文件,路径为:
maven-archetype-webapp-1.4.jar\archetype-resources\src\main\webapp\WEB-INF
进行以下代码需改:就可以永久改变 webapp的版本。
<?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">
</web-app>
7、HelloServlet
Servlet简介
- Servlet就是sun公司开发动态web的一门技术
- sun公司在这些API中提供一个接口叫作:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器中。
把**实现了Servlet接口的java程序叫做Servlet**.
API(Application Programming Interface,应用程序接口)是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。
7.1、创建HelloServlet项目
1、我们构建一个普通的Maven项目, 删除掉里面的 src目录。这样,这个Maven项目就是一个 Maven主工程。
pom.xml配置文件导入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>
<groupId>com.AL</groupId>
<artifactId>javaweb-02.servlet</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>servlet-01</module>
<module>servlet-02</module>
<module>response</module>
<module>request</module>
</modules>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jsp-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
</project>
在导入的jar包不能使用的时候,自己手动下载jar包 导入:自己去导入maven文件中的maven-repo文件中对应的javax.servlet目录下。
2、创建一个maven子项目:即此时再新建一个Maven,采用了一个webapp的模块的 maven项目。
7.2、servlet-01 Maven子项目
创建一个maven子项目:即此时再新建一个Maven,采用了一个webapp的模块的 maven项目。
- 修改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_3_1.xsd"
version="3.1">
</web-app>
- 将Maven的结构搭建完整。 新建文件夹 java和resource。并设置其属性为 源代码和 资源配置文件。
- 编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口
7.2.1、编写Servlet程序
我们编写了一个类, 这个类实现了Servlet接口, 再进行web发布,就能称为一个 Servlet程序。
- 实现Servlet接口。我们这里选择直接继承 HttpServlet接口。
我们查看 HttpServlet接口实现类的代码, 可以发现它继承了GenericServlet接口; 而GenericServlet接口又继承了 Servlet接口。 所以,在这里我们直接继承 HttpServlet接口就能去实现 Servlet接口。
在此项目中,我们使用 doget、dopost 方法。 继承了接口,对其中的方法我们进行重写 @Override。
package com.AL.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;
// 这是我们自己编写的实现类, 重写方法,继承HttpServlet,完成servlet的工作
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同的方式,可以互相调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入doGet方法");
PrintWriter writer = resp.getWriter();//响应流
writer.print("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
- 将编写好的Servlet 去部署到web服务器中。 对我们写的Servlet程序进行发布。 即在 web.xml文件中**进行注册和映射Servlet的请求路径**。
<?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_3_1.xsd"
version="3.1">
<!-- 注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.AL.servlet.HelloServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
配置Tomcat进行测试:路径选择为空。
在浏览器端输入 http://localhost:8080/hello,结果如下
自我总结:
完成一个Servlet。Servlet是用来创建动态web的技术。开发一个Servlet程序,需要两个步骤:
- 编写一个类,实现Servlet接口。 sun公司默认有两个类:HttpServlet,GenericServlet。HttpServlet继承了Servlet接口的功能, 所以我们直接继承HttpServlet,编写一个类 就能去实现servlet接口。
- 把开发好的java类添加到web服务器中。即在web.xml配置文件中,完成servlet注册和servlet请求的路径映射。
在这里,我们就将实现了Servlet接口的java程序叫做Servlet。
具体步骤:
1.创建一个具有webapp模板的Maven项目,即maven-archetype-webapp这个模板,然后删掉里面的src目录。以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven的主工程;
2.在这个Maven主工程,即父工程下去创建 空的,没有模板的maven项目,称为子工程。关于Maven父子工程的理解:
父项目中,会包含你创建的所有的子项目:
<groupId>com.AL</groupId>
<artifactId>javaweb-02.servlet</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>servlet-01</module>
<module>servlet-02</module>
<module>response</module>
</modules>
子项目中会标注自己的父工程是谁,继承了谁的功能,:
<parent>
<artifactId>javaweb-02.servlet</artifactId>
<groupId>com.AL</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的java子项目可以直接使用,类似于java中类的:son extends parents。
3.Maven环境优化和完善:1.修改web.xml为最新的版本;2.将maven的结构搭建完整。
4.编写一个Servlet程序:需要两个步骤:1.编写一个普通类; 2.实现Servlet接口,这里我们直接继承HTTPServlet。
5.将编写好的Servlet 去部署到web服务器中。需要两个步骤:1.注册servlet2.编写Servlet的映射
6.配置Tomcat。 注意:配置项目发布的路径就可以了
7.启动测试
7.3、Servlet原理
Servlet是由Web服务器调用, web服务器在收到了浏览器的请求之后,就会去寻找 请求和响应,即Request和Response,在这里调用的就是 Servlet中的方法(我们做的就是就这个 servlet程序, 它是发布在了 web容器中)。然后去进行响应给客户端东西 数据信息。
7.4、Mapping问题
Mapping问题,即映射路径的问题。
- 一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定多个映射路径: 即多个映射路径 URL 查询,可以去调用同一个Servlet程序。就好比去 ->B有多个路径,但是最终的目的地B 或者数据 页面只有一个, 对应着就是一个Servlet。
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello4</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello5</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定通用的映射路径:
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 默认请求路径。 即不管你查询什么,你随便输入 url路径,查询的结果都是一样的
<!--默认请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
- 指定一些后缀或者前缀等等
<!--可以自定义后缀实现请求映射
注意点,*前面不能加项目映射的路径
hello/sajdlkajda.do
-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
- 优先级问题. 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<!--404-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
响应顺序:自己的理解:
按照下方这样,当localhost:8080/s1/hello,即进入了路径/hello,然后选择hello这个名字的servlet,对应的hello,再找到com.AL.servlet.HelloServlet这个类,方法进行运行,得到了Hello servlet!这个界面的结果。具体顺序如标记所示:
7.5、ServletContext对象
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用:
ServletContext:在一个web程序中,有多个servlet,他们之间如何共享数据?在每个Servlet中,可以将数据放在ServletContext,然后读取ServletContext就行了。
一个web程序是指,这一个子项目 在同一个Maven子项目中。如下图所示:在servlet-02项目,对应url为/s2/*的路径下,有两个servlet,两种地址:s2/getc s2/hello.
- 共享数据:
- 在这个Servlet保存的数据,可以在另一个Servlet拿到, 通过ServletContext拿到,中间商:
创建一个servlet,Servletcontext:向servletcontext中存放了一个字符串 name=“ALZN”
package com.AL.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 {
System.out.println("Hello");
//this.getInitParameter(); //初始化参数
//this.getServletConfig(); // Servlet配置
//this.getServletContext(); // Servlet上下文。
// ServletContext相当于将servlet-01、servlet-02中的数据存储到这个里面,可以在这个里面读取这几个 URL中的数据
ServletContext context = this.getServletContext();
String name = "AL ZN"; // 数据
context.setAttribute("username", name); //将一个数据保存在了ServletContext中,名字为:username,值username
}
}
- 创建一个读取servletcontext文件中的servlet程序:
package com.AL.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();
//为了能够获取信息,不会乱码
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
String username = (String) context.getAttribute("username");
resp.getWriter().println("名字:"+ username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
- Web.xml 配置文件:注册servlet,servlet路径映射.
<?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>hello</servlet-name>
<servlet-class>com.AL.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.AL.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
</web-app>
启动tomcat,进行测试:http://localhost:8080/getc
理解上述代码:
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//为了能够获取信息,不会乱码。
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
String username = (String) context.getAttribute("username");
resp.getWriter().println("名字"+ username);
}
- 其中的req,resp。当浏览器请求服务器(WEB站点),服务器就给这个请求创建几个对象,request,response session等。
- 其中,request携带请求地址、参数,用于寻找需要执行的Servlet和其参数。
- response就是要返回给浏览器的结果对象。你可以通过getOutputStream()来得到这个流,往里面写数据内容。
- session则是标志一个会话(在同一浏览器一定时间内访问统一服务器则认为是同一个会话)。
7.5.2、ServletContext应用:获取初始化参数
1.在web.xml文件中配置web初始化参数, 注册servlet和路径映射:
配置一些web应用初始化参数-:
自己定义了一个参数为 url 的信息, 去获取这个 url 参数。
<?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">
<!-- 配置一些web应用初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.AL.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.AL.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.AL.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
</web-app>
2.创建一个servle程序,去获取url参数信息:this.getInitParameter(); //初始化参数
package com.AL.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;
// 设置一个servlet 去读取 servletcontext的参数
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url"); // 获取context的url参数
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.启动tomcat,测试:http://localhost:8080/gp。结果为:
7.5.3、ServletContext应用:请求转发
请求转发的时候,不会发生网址变化,只是在内部由B去访问C了。关系如下:
1.创建一个servletDemo04,用于进行请求和转发: Servlet程序完成请求和转发。
使用 ==requestDispatcher.forward(req,resp);方法去实现请求转发==调用forward实现请求转发。
在ServletDemo04这个servlet程序中,这是一个请求转发的servlet,它会去调用 请求路径下的servlet程序,此时是去调用 /gp 下的程序。 但是在访问的时候,地址不会发生改变。 这是和重定向不同的地方。
package com.AL.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 ServletDemo04 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"); //转发的请求路径
//requestDispatcher.forward(req,resp); //调用forward实现请求转发
context.getRequestDispatcher("/gp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.在web.xml配置文件中进行 注册servlet和servlet请求的路径映射:
<servlet>
<servlet-name>sd4</servlet-name>
<servlet-class>com.AL.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd4</servlet-name>
<url-pattern>/sd4</url-pattern>
</servlet-mapping>
3.启动tomcat进行测试:http://localhost:8080/sd4。 结果是 /gp 下的 url参数信息。 还可以发现此时的地址没有发生变化,还是http://localhost:8080/sd4。
7.5.4、读取资源文件
资源文件,即 properties 文件。
Properties:
• 在java目录下新建properties
• 在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为类路径,即#classpath.
思路:需要一个文件流。因为我们读取的 资源信息不仅仅是一个数据, 是 文件流。
1.创建一个db.properties: 在resource资源文件夹下。
username=root
password=123456
2.创建一个资源获取的 servlet程序:
采取 InputStream 这个文件流,用来写入获取的资源流 文件流。
package com.AL.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 ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入了ServletDemo05");
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
System.out.println("##################");
Properties properties = new Properties();
properties.load(in);
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.配置web.xml文件:注册servlet和servlet请求的路径映射
<servlet>
<servlet-name>sd5</servlet-name>
<servlet-class>com.AL.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd5</servlet-name>
<url-pattern>/sd5</url-pattern>
</servlet-mapping>
4.启动tomcat运行测试:http://localhost:8080/sd5。结果为:
7.6、HttpServletResponse
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 setContentLengthLong(long var1);
- void setContentType(String 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_INRMATION = 203;
- int SC_NO_CONTENT = 204;
- int SC_RESET_CONTENT = 205;
- int SC_PARTIAL_CONTENT = 206;
2.常见应用
- 向浏览器输出消息
- 下载文件
创建一个reponse的maven项目进行练习:
此时创建的时候出现错误:
Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:3.2.0:generate (default-cli) on project standalone-pom: The defined artifact is not an archetype
解决方法: 将maven - webapp这个文件夹完全删除,重新加载,即可。如下所示:
7.6.1、Response下载文件
下载文件:具体步骤:
1. 要获取下载文件的路径
- 下载的文件名是啥?
- 设置想办法让浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端!
1.创建下载文件的Servlet程序:
注意:对于文件流,要记得关闭。 最后打开的先关闭,从下往上。
package com.AL.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.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
// 下载文件
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
//String realPath = this.getServletContext().getRealPath("/1.png");
String realPath = "E:\Java_work\Learning_code\JavaWeb\javaweb-02.servlet\response\src\main\resources\\1.jpg";
System.out.println("下载文件的路径为:"+realPath);
//2. 下载的文件名是啥?
String fileName=realPath.substring(realPath.lastIndexOf("\")+1);
System.out.println("##########");
// 3. 设置想办法让浏览器能够支持下载我们需要的东西
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缓冲区,使用OutputStream将缓冲区中的数据输出到客户端!
while ((len=in.read(buffer))>0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.web.xml配置文件:注册Servlet和Servlet的路径映射。
<?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>filedown</servlet-name>
<servlet-class>com.AL.Servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>filedown</servlet-name>
<url-pattern>/down</url-pattern>
</servlet-mapping>
</web-app>
3.启动tomcat,进行测试。 输入 localhost:8080/down。
7.6.2、Response验证码实现
验证码功能:
- 后端实现:我们需要一个java的图片类,用于实时刷新的一组数字,去生产一个图片。 就是在后端里面自己生成的一个图片。 在这里没有用到前端实现。
我们自己在Java程序中生成一个图片, 然后在得到用户请求的时候, 跳转到 映射的 url路径对应的 java程序, 然后去输出一个拼接成的图片, 数字随机生成,刷新。
验证码功能的实现:
1.创建图片和数字验证码照片的 Servlet程序:
在这段代码中生成随机数: 之所以加这个for循环,是为了将num一定为7位数。
package com.AL.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 g = (Graphics2D) image.getGraphics();//笔
//设置图片的北京颜色
g.setColor(Color.white);
g.fillRect(0, 0, 80, 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","no1-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
//生成随机数
private String makeNum () {
Random random = new Random();
String num = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7 - num.length(); i++) {
sb.append("0");
}
num = sb.toString() + num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.web.xml配置文件:注册Servlet和Servlet的路径映射。
<servlet>
<servlet-name>image</servlet-name>
<servlet-class>com.AL.Servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>image</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
3.启动tomcat,进行测试。 输入http://localhost:8080/img。 结果为:
7.6.3、Response重定向
一个web资源 B 收到客户端 A的请求后, B会去通知 A客户端去访问另一个web资源 C,这个过程叫做重定向。
常用场景:
- 用户登录
- void sendRedirect(String var1) throws IOException;
我们先进行测试,查看能否访问图片下载或者验证码的那个 网址 /img。
在这里,我们重定向 /img,代码如下:
- 重定向: resp.sendRedirect()方法。
- 请求转发://requestDispatcher.forward(req,resp); //调用forward实现请求转发; context.getRequestDispatcher("/gp").forward(req,resp);
1.Servlet程序:
package com.AL.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", "r1/img")
* resp.setStatus(302)
*/
resp.sendRedirect("/r1/img");
//resp.sendRedirect("/r1/down"); //重定向
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2.web.xml配置文件:
<servlet>
<servlet-name>RedirectServlet</servlet-name>
<servlet-class>com.AL.Servlet.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/red</url-pattern>
</servlet-mapping>
3.启动测试:在输入 localhost:8080/r1/red 的时候, 结果会地址发生改变:http://localhost:8080/r1/img
面试题:请你聊聊重定向和转发的区别?
相同点:
- 页面都会实现跳转
不同点:
- 请求转发的时候,url不会产生变化
- 重定向的时候,url地址栏会产生变化
- 重定向: resp.sendRedirect()方法。
- 请求转发://requestDispatcher.forward(req,resp); //调用forward实现请求转发; context.getRequestDispatcher("/gp").forward(req,resp);
用户登录的例子:
用户登录思路:那么我们需要创建一个登录的默认界面。 页面的按钮或者是按键信息 submit 会去响应到指定的 url 路径,在这里我们写死了路径地址。 而这个url地址是我们已经在 web.xml文件中注册过的,对这个 url的映射路径, 去执行请求的 Servlet程序, Servlet程序再来给具体响应,输出具体对应信息, 该输出输出 该请求转发或者重定向 去跳转页面。
1.创建**localhost:8080/r1**响应时的默认界面,路径是这个maven项目中设置默认的。在index.jsp中的代码: 采用 get()方式去获取信息。 也可以用post等方法。
在这个页面,点击提交,即submit时,会响应到 /login路径下,即去完成servlet中路径映射为/login的servlet程序。
<html>
<body>
<h2>Hello World!</h2>
<%-- 这里提交的路径,需要去寻找到项目的路径--%>
<%-- ${pageContext.request.contextPath} 表示当前项目的路径--%>
<form action="${pageContext.request.contextPath}/login" method="get">
username: <input type="text" name="username"> <br>
password: <input type="password" name="password"> <br>
<input type="submit">
</form>
</body>
</html>
2.路径映射为/login的servlet程序:
- 响应请求,进入请求后,去获取请求信息:req.getParameter。
- 重定向。 响应请求完成后去重定向,反馈给前端客户端 访问是否成功的信息。
package com.AL.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 {
System.out.println("进入这个请求了:");
// 处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
//重定向一定要注意路径问题,否则就会404错误
resp.sendRedirect("/r1/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.web.xml配置文件: 完成Servlet的注册和 路径映射。
<?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>image</servlet-name>
<servlet-class>com.AL.Servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>image</servlet-name>
<url-pattern>/img</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RedirectServlet</servlet-name>
<servlet-class>com.AL.Servlet.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RedirectServlet</servlet-name>
<url-pattern>/red</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RequestTest</servlet-name>
<servlet-class>com.AL.Servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestTest</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
3.上述servlet程序成功后 重定向的项目程序:resp.sendRedirect("/r1/success.jsp"); 重定向的界面的url路径为/r1/success.jsp。
创建这个success.jsp 这个界面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title> <%--即网页的名称,题目 --%>
</head>
<body>
<h1>Success<h1> <%--即网页显示的内容 --%>
</body>
</html>
4.启动 Tomcat,进行测试: 首先进入 localhost:8080/r1 这个maven项目的默认路径下的界面:
进行输入信息后,点击提交回车:
在java控制台也成功捕捉到了信息:req.getParameter(“username”); 获取信息。
进入这个请求了:
ALZN:QWERTYUIOP
7.7、HttpServletRequest
HttpServletRequest 代表客户端的请求, 用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest, 通过这个HttpServletRequest的方法获得客户端的所有信息;
关于req中的一些获取信息的方法: 即HttpServletRequest 中的获取方法 get()。
获取参数和请求转发的 HttpServletRequest 例子:
1.设置初始化页面:在index.jsp中, 这个webapp下的这个 index.jsp就是默认的界面,我们在这里改就可以了。
<%–br表示换行–%>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h1>登录</h1>
<div style="text-align: -webkit-center"> <%--这个表示文本在界面中的位置--%>
<%-- ${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="checkbox" name="hobbys" value="唱">唱
<input type="checkbox" name="hobbys" value="跳">跳
<input type="checkbox" name="hobbys" value="rap">rap
<input type="checkbox" name="hobbys" value="篮球">篮球
<br> <%--br表示换行--%>
<input type="submit">
</form>
</div>
</body>
</html>
2.设置请求转发的servlet程序:获取的初始化参数,请求转发的路径:
package com.AL.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[] hobbys = req.getParameterValues("hobbys");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
// 通过请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.转发路径的success.jsp页面设置: 在这里使用的是 请求转发的方式进行页面跳转。 成功后,跳转的页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>
4.配置文件web.xml:注册servlet,servlet路径映射
<?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.AL.Servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
5.启动tomcat,进行测试。 注意:我们每次对于新的Servlet程序,或者因该说是新的 Servlet程序进行web发布的时候, 需要设置对应的Maven项目的路径。
启动后的默认界面:
此时在控制台的结果为:
kunkun
123456
[唱, 跳, rap, 篮球]
关于HttpServletResponse和HttpServletRequest的区别:
HttpServletResponse:
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HTTPServletRequest对象,代表响应的一个HTTPServletResponse;
- 如果要获取客户端请求过来的参数:找 HttpServletRequest
- 如果要给客户端响应一些信息:找 HTTPServletResponse
HttpServletRequest 代表客户端的请求, 用户通过Http协议访问服务器, HTTP请求中的所有信息会被封装到HttpServletRequest, 通过这个HttpServletRequest的方法获得客户端的所有信息;
例如:我们想要获取客户端发过来的信息、参数什么的,就要去找 HttpServletRequest ,
- req:
req.getParameter("username"); //获取参数信息
req.setCharacterEncoding("UTF-8"); // 获取客户端的请求参数进行编码后的请求, 防止乱码
通过请求转发: req
//requestDispatcher.forward(req,resp); //调用forward实现请求转发;
context.getRequestDispatcher("/gp").forward(req,resp);
// 通过请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
我们想要给客户端去响应一些东西,去设置一些参数信息, 就去找HttpServletResponse:
- resp:
resp.getWriter();//响应流, 响应给客户端文件流,向其响应进行输入
resp.setCharacterEncoding("UTF-8"); //给客户端响应编码信息
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));//给客户端,浏览器响应给 header 信息。
重定向:resp
resp.sendRedirect("/r1/down"); //重定向
一个简单的动态web:
- Servlet程序。发布我们编写好的 servlet程序到 web 容器中。客户端通过这个进行请求,请求信息封装到 HttpServletRequest ;再响应给客户端一些东西 HttpServletResponse。
- jsp。页面渲染
那么我们这就相当于完成了一个简单的动态 web, JSP+Servlet, 再加入数据库的话,就能做一些数据持久的工作,调用数据库的内容显示给客户端, 响应 客户端的请求。 客户端进行CRUD的操作请求后,服务端再去完成响应这些动作,并通过 JSP 页面去直观渲染地显示给客户端。 这就能构建完成了。