文章目录
1、Javaweb
-
静态web
html,css
-
动态web
技术栈:Servlet/jsp,asp,php
1.1 web应用程序
可以提供浏览器访问的程序: a.html , b.html…
tomcat服务器
一个web应用由多部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- java程序
- jar包
- 配置文件(properties)
web应用程序编写完毕后,若想要提供给外界访问,需要一个服务器来统一管理
1.2 静态web
*.html *.htm,这些都是网页的后缀,如果服务器上一直存在这些东西,就可以直接进行读取,
静态web存在的缺点:
- web页面无法动态更新,所有用户看到的都是同一个页面
- 为了实现轮播图,点击特效:伪动态
- JavaScript [实际开发中,它用的最多]
- VBScript
- 他无法和数据库交互(数据无法持久化,用户无法交互)
1.3 动态web
页面会动态展示:“web的页面展示的效果因人而异”
缺点:
- 假如服务器的动态web资源出现了错误,我们需要重写编写我们的后台程序,重新发布。
- 停机维护
优点:
- web页面可以动态更新,所有用户看到都不是同一页面
- 它可以与数据库交互(数据持久化)
2、web服务器
2.1 技术讲解
ASP:
- 微软:国内最早流行的
- 在html中嵌入VB脚本,ASP+COM
- 在ASP开发中,基本一个页面都有几千航的业务代码,页面极其混乱
php:
- 开发速度快,功能强大,跨平台,代码简单(70%,WP)
- 无法承载大访问亮的情况(局限性)
Jsp/servlet:
-
本质上是servlet
-
sun公司主推的B/S架构
(B/S:浏览器和服务器 C/S:客户端和服务器)
-
基于java语言的(所有的大公司,或者一些开源的组件,都是用java写的)
-
可以承载三高问题带来的影响,高并发,高性能,高可用
-
语法像ASP,ASP–>JSP,加强市场强度
2.2 web服务器
Tomcat
面向百度编程;
apache 软件基金会
工作3-5年,尝试手写Tomcat;
下载Tomcat:
- 安装 or 解压
- 了解配置文件及目录结构
- 这个东西的作用
Tomcat官网
tomcat server.xml 文件可以修改启动的端口号,可以修改主机名称,
默认端口号:
tomcat:8080
mysql:3306
http:80
https:443
默认主机名称:
localhost—>127.0.0.1
默认网站应用存放的位置:
webapps
-
高难度面试题:
请你谈一下网站如何进行访问的?
-
输入域名,回车 www.baidu.com
-
检查本机的 C:\Windows\System32\drivers\etc\hosts配置问下有没有这个域名映射;
-
有,就直接返回对应ip的地址
127.0.0.1 www.baidu.com
这个地址中有我们需要访问的web程序,可以直接访问
-
没有,去DNS服务器,(DNS全世界的域名都在这里管理 14.215.117.39:443)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PwMM33nX-1658156711620)(https://s2.loli.net/2022/07/06/tAkM2RQg3PNewsh.png)]
-
-
IIS
微软的; ASP … Windows中自带
…
服务器是一种被动的操作,用来处理用户的请求和给用户一些响应信息;
发布一个web网站
将自己写的网站 *.html文件,放到服务器tomcat中指定的web应用的文件夹webapps下,就可以访问了
网站应该有的结构
-- webapps: tomcat 服务器的web目录
-- ROOT
-- kuangstudy : 网站的目录名
-- WEB-INF
-- Classes : java程序
-- lib : web 应用所有需要的jar包
-- web.xml : 网站配置文件
--index.html 默认的首页
-- static
--css
--style.css
--js
--img
-- ....
3、HTTP
3.1 HTTP是什么
HTTP 超文本传输协议,简单的请求、响应协议
- 文本:html ,字符串,…
- 超文本:图片,音乐,视频,定位,地图…
- 80
HTTPS:
- 443
- 安全的
3.2 两个时代
-
http1.0
http/1.0:客户端可以和web服务器连接后,只能获得一个web资源,断开连接。
-
http2.0
http/1.1:客户端可以与web服务器连接后,可以获得多个web资源。
3.3 http请求
-
客户端—发请求(request)—服务器
-
以百度为例:
General 通用的:请求和响应都有
Request URL: https://www.baidu.com/ 请求地址 Request Method: GET get/post方法 Status Code: 200 OK 状态码:200 Remote Address: 180.101.49.11:443 远程地址 Referrer Policy: strict-origin-when-cross-origin 引荐来源网址策略 “strict-origin-when-cross-origin”,用于修剪用户敏感信息,例如路径和查询字符串,以保护隐私。 referrer 头经常包含用户的隐私数据,比如用户在引用网站上阅读哪些文章、甚至是用户在网站上的账户信息。因此,W3C 官方提出了一些候选策略 Referrer Policy,以规范 referrer 内容。 即当从 HTTPS 网站跳转到 HTTP 网站或者请求其资源时(安全降级 HTTPS→HTTP),不显示 referrer 的信息,其他情况(安全同级 HTTPS→HTTPS,或者 HTTP→HTTP)则在 referrer 中显示完整的源网站的 URL 信息。
Request header:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,... 请求类型信息 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 语言 Connection: keep-alive 连接:一直连接 中间一堆cookie信息 Cookie: BIDUPSID=27CCFA0EF0EC7BE270189BCE89C465F1; PSTM=1597130134; BAIDUID=5B74033ED4696DC25CC97B295A443D76:FG=1; BD_UPN=12314753; MCITY=-352%3A; BAIDUID_BFESS=5B74033ED4696DC25CC97B295A443D76:FG=1; ZFY=N9RnKbDDv1VWhF3plEYx2jnBibjkBClK4C5W7h3a5A0:C; COOKIE_SESSION=4581192_2_9_9_8_9_1_0_8_5_1_0_4581192_0_37_0_1657009934_1652341087_1657009897%7C9%232235112_315_1652341085%7C9; baikeVisitId=fa2ebb37-2746-49fd-a81f-da7ca55cf1f9; BA_HECTOR=04a58la00g25818g201hccfrq14; BDRCVFR[-HoWM-pHJEc]=mk3SLVN4HKm; BD_HOME=1; H_PS_PSSID=31254_26350 Host: www.baidu.com 主机 sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103" sec-ch-ua-mobile: ?0 移动 sec-ch-ua-platform: "Windows" 平台 windows Sec-Fetch-Dest: document 文档 Sec-Fetch-Mode: navigate 导航 Sec-Fetch-Site: none 网站 Sec-Fetch-User: ?1 用户 Upgrade-Insecure-Requests: 1 升级-不安全-请求 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 用户代理
-
请求行
- 请求行中的请求方式 get
- 请求方式 :GET POST HEAD DELETE PUT TRACT…
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的url地址栏显示数据内容,不安全,但是高效
- post:请求能携带参数没有限制,带下没有限制,不会在浏览器的url地址显示数据内容,安全,不高效
-
消息头
Accept: 告诉浏览器,它所支持的数据类型 Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1 Accept-Language: 告诉浏览器,他的语言环境 cache-Control: 缓存控制 Connection: keep-alive 告诉浏览器请求完成是断开还是连接 Host...主机
-
3.4 http响应
-
服务器—响应(respose)—客户端
-
以百度为例,respose header
Cache-Control: private 缓存控制 Connection: keep-alive 保持连接 Content-Encoding: gzip 内容编码 压缩程序 Content-Type: text/html;charset=utf-8 内容类型:文本/超文本标记语言 text/html, 字符集=utf-8 utf:Unicode Transformation Format Unicode转换格式 Date: Thu, 07 Jul 2022 02:13:05 GMT 当前时间 GMT:格林尼治时间 Expires: Thu, 07 Jul 2022 02:12:14 GMT 有效期 Server: BWS/1.1 浏览器服务信息 Strict-Transport-Security: max-age=172800 严格传输安全 Traceid: 1657159985069125325811992526401082961452 跟踪id Transfer-Encoding: chunked 转移编码:分块 X-Frame-Options: sameorigin 框架选项:同源 X-Ua-Compatible: IE=Edge,chrome=1 兼容
-
响应体
Accept: 告诉浏览器,它所支持的数据类型 Accept-Encoding: 支持哪种编码格式 GBK UTF-8 GB2312 ISO8859-1 Accept-Language: 告诉浏览器,他的语言环境 cache-Control: 缓存控制 Connection: keep-alive 告诉浏览器请求完成是断开还是连接 Host...主机 Refrush:告诉客户端,多久刷新一次; Location: 让网页重新定位;
-
响应状态码
200 请求响应成功
3** 请求重定向 303
- 重定向:你重新到我给你的位置去
4** 找不到资源 404
- 资源不存在 后端服务器没有找到
5** 服务器代码错误 500 502 网关错误1
常见面试题
当你的浏览器中地址栏输入地址并回车到页面能够展示回来,经历了什么?
-
4、Maven
帮助管理jar包,java开发中大量jar包,需要手动导入很麻烦
maven帮助自动导入和配置jar包
maven是一个项目架构管理工具
目前用它来导入jar包
核心思想:约定大于配置
- 有约束,不要违反
maven会规定如何编写java代码,必须按规范来
下载安装maven
-
apache maven progect 官网下载 bin.zip & src.zip
https://maven.apache.org/
解压 bin.zip
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KcI60xi3-1658156711621)(https://s2.loli.net/2022/07/07/6cMiyOqJwLPSYQG.png)]
conf – 配置
4.1 配置环境变量
在系统环境变量中,配置如下配置:
- M2_HOME maven安装目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置%MAEN_HOME%\bin
4.2阿里云镜像
-
镜像 mirrors
- 作用:加速下载
-
国内建议使用阿里云的镜像
<mirror> <id>alimaven</id> <mirrorof>central</mirrorof> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/comtent/groups/public</url> </mirror>
或者
<mirror> <id>nexus-aliyun</id> <mirrorof>*,!jeecg,!jeecg-snapshots</mirrorof> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/comtent/groups/public</url> </mirror>
4.3本地仓库
在本地的仓库,远程仓库;
建立一个本地仓库: 不需要每次去网上下载 localRepository
setting.xml中
<localRepository>
这里放的是本地自己新建的maven仓库地址
</localRepostory>
4.4 Idea中使用maven
- 启动idea
创建一个maven web项目
选中maven web项目模板,进行创建
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fBZ8odAK-1658156711627)(https://s2.loli.net/2022/07/07/GDkg4VK5uTNvf17.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RO34m2Bx-1658156711633)(https://s2.loli.net/2022/07/07/FEU8VgQwxmy1S2Z.png)]
点击finish
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEOBjf3C-1658156711635)(https://s2.loli.net/2022/07/07/HXDvqAWdYKGybra.png)]
构建maven项目成功
观察maven仓库中多了什么东西?
IDEA中的maven设置:
idea项目创建成功后,看一下maven配置
maven在idea中的配置和使用就ok了
创建一个普通的maven项目
不选中创建模板,直接next
mavenWeb项目和普通maven项目结构区别
maven web项目结构:
WEB-INF----web.xml index.jsp 这个只有在web应用下才会有!
普通maven项目结构:
完整构建maven web项目
在 maven web项目下加入一个 java文件 和 resources文件;
java文件中放代码 ,标记为源码目录 Sources Root
resources文件中放资源,标记为资源目录 Resource Root
标记文件夹功能:
项目结构配置:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yYIPRklw-1658156711641)(https://s2.loli.net/2022/07/07/aA6B5lE3nXFYqQ9.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JIalTbHb-1658156711642)(https://s2.loli.net/2022/07/07/OfMJo8Lyj6zPpNq.png)]
4.5 在IDEA中配置tomcat
创建了一个 maven web项目后,配置Tomcat;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAlxCtIu-1658156711647)(https://s2.loli.net/2022/07/07/g4KObFYvNVfUjMo.png)]
解决了警告问题。
为什么会有警告问题?
我们访问一个网站,需要指定一个文件夹的名字;idea没有主动去找项目名字,需要手动配置。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GSetS5Rh-1658156711648)(https://s2.loli.net/2022/07/07/sWMRih7ST8NdxO2.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LxOwlLpP-1658156711651)(https://s2.loli.net/2022/07/07/pNCzPoGbJMWk6Ht.png)]
4.6 pom.xml文件
pom.xml是maven的核心配置文件
maven命令使用:
clean:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kbf5AV9J-1658156711652)(https://s2.loli.net/2022/07/07/d8h7IbCpU9vmZMH.png)]
Maven导入jar包:
4.7 Maven存在的问题-资源导出问题
Maven由于他的约定大于配置,所以默认的maven项目在构建编译时不会把我们其他目录下的配置文件导出到target目录中,从而导致配置文件无法导出或者生效的问题。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UwamquG2-1658156711654)(https://s2.loli.net/2022/07/18/IfHKinyBx2RqPWt.png)]
解决方案:在项目的pom.xml文件中手动配置资源过滤,让它把src/main/java目录下的.properties和.xml文件也能够被导出。
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4HttIY9A-1658156711655)(https://s2.loli.net/2022/07/18/UgIaw9Db4hOsM5J.png)]
4.8 IDEA中生成jar包目录树
4.9 解决遇到的问题
-
Maven 3.6.2 版本有问题,建立依赖的时候依赖无法导入,导入的时候会报错
解决方法:降级为3.6.1
-
Tomcat闪退
因为tomcat需要java的环境,但是tomcat中没有配置java环境,所以就会闪退。
解决办法:tomcat安装文件\bin\catlina.bat用记事本打开,找到Java环境配置的地方,配置下java的环境。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c3T7okhr-1658156711656)(https://s2.loli.net/2022/07/07/Tl9cWprqdtvPYQo.png)]
-
IDEA中每次都要重复配置Maven
解决办法:在IDEA中的全局默认配置中去配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GhIw4GV4-1658156711657)(C:\Users\16431\AppData\Roaming\Typora\typora-user-images\image-20220707174107079.png)]
-
Maven项目中Tomcat无法配置
-
Maven默认web项目中的web.xml版本问题
默认生成web-app_2_3,这个版本太老了,
替换为webapp4.0版本,和tomcat保持一致
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yWloyZME-1658156711658)(https://s2.loli.net/2022/07/08/2S7IazXFbjR5QlY.png)]
所以需要更换使用 D:\Program Files\apache-tomcat-9.0.43\webapps\ROOT\WEB-INF\web.xml 中的xml模板:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lqzGrWjg-1658156711659)(https://s2.loli.net/2022/07/08/Es7OqhtynUCacjx.png)]
<?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" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> </web-app>
5、tomcat和web.xml中配置理解
创建maven web项目结构:
创建servlet类:
这个类模板在tomcat\webapps\examples\servlet中;
操作:启动tomcat,访问localhost:8080/examples/servlets即可得到Servlets examples
项目启动后,浏览器输入url,进行访问,得到页面,后端是怎么进行的?
配置Tomcat Deployment中的Application Context理解
/hello,就是给tomcat下加了一层包,包名字叫hello,访问的时候地址变为:localhost:8080/hello
-
如果没有加,访问 localhost:8080 默认进入后端index.jsp页面
-
如果给tomcat这里加了新的包层,则访问路径为localhost:8080/hello/,访问页面默认进入后端index.jsp页面
配置servlet理解
-
访问 localhost:8080/hello/kuangsheng 访问时先从WEB-INF中的web.xml文件找 servlet-mapping 中 url-pattern 请求路径为 /kuang 的 servlet-name , 由于一个servlet 对应一个 servlet-mapping ,所以再通过找到的servlet-name 去找servlet中的 servlet-class ,servlet-class中是这个类的 路径 ,从而找到类响应的页面;
前端页面显示中文问题
6、Servlet
6.1 Servlet简介
- Servlet就是Sun公司开发动态web的一门技术
- Sun公司在这些API中提供一个接口叫:Servlet,如果你想开发一个Servlet程序,只需要完成两个步骤;
- 编写一个类,实现Servlet接口。
- 把开发好的java类部署到web服务器中。
- 把实现了Servlet接口的程序叫做,Servlet
6.2 HelloServlet
1、构建一个普通Maven项目;
不需要勾选 create Maven-webapps模板;
删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven主工程;
2、关于Maven父子工程的理解:
父项目中pom.xml中多了一个
<modules>
<module>servlet-01</module>
</modules>
子项目中pom.xml中多了一个
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.kuang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的jar包,子项目可以直接使用;
子项目中的jar包,父项目不能直接使用;
son extends father
3、Maven环境优化
- 修改web.xml为最新的
- 将Maven的结构搭建完整
更换子项目中web.xml内容为tomcat安装包\webapps\ROOT\WEB-INF\web.xml中的内容;因为模板中的webapp版本太老了,和下载的Tomcat版本不匹配;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZT1X3sv0-1658156711667)(https://s2.loli.net/2022/07/08/YmU97cgPNBFrqw6.png)]
main包下添加java包和resource包
4、编写一个Servlet
-
编写一个普通类
-
实现Servlet接口 ,这里我们直接继承HttpServlet
Servlet接口在Sun公司有两个默认的实现类:HttpServlet和GenericServlet 即httpServlet和通用servlet.
package com.kuang.servlet; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; 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 HollerServlet extends HttpServlet { //由于get或post只是请求实现的不同方式,可以互相调用,业务逻辑一样 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); //输入流 //ServletInputStream writer = req.getInputStream(); //响应流 //ServletOutputStream outputStream = resp.getOutputStream(); PrintWriter writer = resp.getWriter(); writer.print("hello,servlet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
5、编写Servlet的映射
为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径。
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
6、配置Tomcat
注意:配置项目发布的路径就行了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PKdVB5qB-1658156711671)(https://s2.loli.net/2022/07/08/UuOKbcZf6nIQWqF.png)]
7、访问成功
访问:localhost:8080/s1/hello/ 就访问到了写的java代码的响应流的内容。
6.3 Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器的请求后,会:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CEMvuQgo-1658156711672)(https://s2.loli.net/2022/07/08/bm5dlrws3qNU7PI.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CVL2inOi-1658156711672)(https://s2.loli.net/2022/07/08/MmWdtxgrOklNIXS.png)]
6.4 Mapping问题
1、一个Servlet可以指定一个映射路径;
访问:http://localhost:8080/s1/hello
就会访问到HelloServlet类中的响应的内容。
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
2、一个Servlet可以指定多个映射路径
访问:
http://localhost:8080/s1/hello1
http://localhost:8080/s1/hello2
http://localhost:8080/s1/hello3
访问到的都是HelloServlet类中响应的内容。
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<!--localhost:8080/s1/hello/* *:通配符 不论*是什么,都可以访问到HelloServlet类-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</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>
3、一个Servlet可以指定通用映射路径;
访问 http://localhost/s1/hello/任意符号
都可以访问到HelloServlet类响应的内容。
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<!--localhost:8080/s1/hello/* *:通配符 不论*是什么,都可以访问到HelloServlet类-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
4、默认的映射路径
访问 http://localhost:8080/s1/jskfljadf 后面任意符号
都可以访问到HelloServlet类响应的内容。
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5、指定一些前缀或者后缀
-
例1:*.do
<!--注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.kuang.servlet.HelloServlet</servlet-class> </servlet> <!--Servlet的请求路径--> <!--localhost:8080/s1/hello/* *:通配符 不论*是什么,都可以访问到HelloServlet类--> <servlet-mapping> <servlet-name>hello</servlet-name> <!--可以自定义后缀实现请求映射--> <url-pattern>*.do</url-pattern> </servlet-mapping>
注意: * 前面不能加项目映射的路径
如果路径格式有误,服务器会报错:
6、优先级问题
指定了固有的映射路径,优先级最高; 如果找不到,就会走默认的路径。
<!--hello,servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<!--localhost:8080/s1/hello/* *:通配符 不论*是什么,都可以访问到HelloServlet类-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<!--可以自定义后缀实现请求映射-->
<url-pattern>/hello</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>
<!--默认直接进入ErrorServlet类中-->
<url-pattern>/*</url-pattern>
</servlet-mapping>
6.5 ServletContext对象
小知识:note.md临时模板的使用
对于web.xml文件中的头每次都要复制粘贴,很麻烦,这时候就可以建一个note.md文件,作为临时文件,将web.xml的内容复制进来,每次使用的时候从这里粘贴就行。
ServletContext作用
web容器在启动的时候,它会为每个web程序都创建一个对应的ServetContext对象,它代表了当前的web应用。
① 共享数据
我在这个Servlet中保存的数据,可以在另一个Servlet拿到;
HelloServlet类:保存数据到ServletContext中;
package com.kuang.servlet;
import javax.servlet.ServletContext;
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
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//给前端响应进入了HelloServlet
// 1 设置响应的类型
resp.setContentType("text/html");
// 2 设置响应格式
resp.setCharacterEncoding("utf-8");
// 3 获取打印输出流,并打印出来内容
PrintWriter writer = resp.getWriter();
writer.print("<h1>HelloServlet!</h1>");
/*
this是怎么来的? 来自父类或者Object类
this.getServletContext() 获取servlet上下文
this.getServletConfig() 获取Servlet配置
this.getInitParameter() 获取初始化参数
这些可以在配置servlet中的web.xml文件中的<servlet></servlet>中进行配置,例如:
<init-param>
<param-name></param-name>
<param-value></param-value>
</init-param>
*/
/*
ServletContext:获取servlet上下文
servlet-01访问路径 URL/s1 servlet-02访问路径:URL/s2 servlet-03访问路径:URL/s3
但是三个servlet之间没有办法通信怎么办,这时候就需要ServletContext
ServletContext是在web应用中的,凌驾在在所有子Servlet之上的,来帮助子Servlet之间进行通信的
*/
// 1:获取这个web项目的ServletContext,命名为context
ServletContext context = this.getServletContext();
// 2:给servlet-02中存个数据,数据为String类型的常量
String username = "宋丹敏"; //作为Servlet-02中的数据
// 3: 将数据存到名字为context的 ServletContext中去,存储格式设置为键值对形式,键:username 值:username
context.setAttribute("username", username); //将一个数据保存到ServletContext中,名字:username,值:username中的值“宋丹敏”
// 4:另一个GetServlet去拿到存在这个HelloServlet的数据,就是从名字为context的ServletContext中取
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp){
}
}
GetServlet类:获取ServletContext中数据;
package com.kuang.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 {
// 5:先获取ServeltContext
ServletContext context = this.getServletContext();
// 6:从ServeltContext中获取键为username的属性值,对属性值进行强制类型转换为String类型
String username =(String)context.getAttribute("username");
// 7:响应给前端并打印出来username的值
resp.getWriter().print(username);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
测试访问结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ykqFxJ9c-1658156711677)(https://s2.loli.net/2022/07/18/JA75P6pb2suUO9w.png)]
② 获取初始化参数
web.xml中配置servlet和web应用初始化参数:
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
<!--配置一些web应用初始化参数-->
<context-param>
<!--配置jdbc连接-->
<param-name>url</param-name>
<!--接口:数据库类型://主机名:端口号/数据库-->
<param-value>jdbc:mysql://localhost:3306//mybatis</param-value>
</context-param>
package com.kuang.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 ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//配置一些web应用初始化参数,在web.xml中通过<context-parm>标签配置
String url = context.getInitParameter("url");
resp.getWriter().print(url); //打印输出url
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
③ 请求转发
把对ServletDemo04的请求转发到ServletDemo03的请求中去;
ServletDemo03:
package com.kuang.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 ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//配置一些web应用初始化参数,在web.xml中通过<context-parm>标签配置
String url = context.getInitParameter("url");
resp.getWriter().print(url); //打印输出url
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
ServletDemo04:
package com.kuang.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;
/*
ServletContext请求转发功能演示
*/
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//测试是否进入ServletDemo04中的get方法
System.out.println("进入了ServletDemo04中的get方法!");
// 1 获取ServletContext
ServletContext context = this.getServletContext();
// 2 获得请求转发,转发给路径为/gp的请求中去
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
// 3 将请求转换格式,传req,resp两个参数,实现请求
requestDispatcher.forward(req,resp);
// 2 3 合并
//context.getRequestDispatcher("/gp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
web.xml:
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>dp</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dp</servlet-name>
<url-pattern>/dp</url-pattern>
</servlet-mapping>
测试访问结果:
访问的/dp,显示的页面是/gp路径下页面的内容:
④ 重定向
请求转发和重定向的区别:
请求转发:a需要的数据在c那:a请求b,b请求c,c响应给b,b响应给a;
请求转发a和c之间是没有直接的联系;
重定向:a需要的数据在c那:a请求b,b告诉a数据在c那,a再去请求c;
重定向a和c之间有直接联系;
⑤ 读取资源文件
思路:需要一个文件流;
Piroperties类
发现:.properties文件都被打包到了同一个路径下:classes文件中,我们俗称这个路径为classpath;类路径
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1CsraV89-1658156711680)(https://s2.loli.net/2022/07/18/kby3sxSfHTE64ZI.png)]
-
在java目录下新建properties,读取aa.properties文件
aa.properties
username=root password=123456
只需修改类中获取文件流的路径即可,如下面ServletDemo5类中注释所示。
-
在resources目录下新建properties,读取resources目录下的db.properties文件
ServletDemo5.java
package com.kuang.servlet; import jdk.internal.util.xml.impl.Input; import javax.servlet.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.beans.PropertyEditor; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /* ServletContext读取文件资源功能演示: 通过ServletContext对象获取文件db.properties文件中的文件流 1 先从ServletContext中获取到db.properties文件流 2 把获取的文件流加载到Properties类中去 3 测试,得到文件流中的属性值 */ public class ServletDemo05 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从ServletContext中获取到文件流,并返回出一个流 InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); // /-代表当前web项目,指向target/servlet-02文件夹 //InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties"); // /-代表当前web项目,指向target/servlet-02文件夹 //把流加载到Properties中去,new的Properties类就是为了存储获取到的文件流中的属性值 Properties prop = new Properties(); prop.load(is); //获取流的属性 String user = prop.getProperty("username"); String pwd = prop.getProperty("password"); //测试 是否获取到文件流中的属性值 resp.getWriter().print(user+":"+pwd); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
web.xml
<servlet> <servlet-name>sd5</servlet-name> <servlet-class>com.kuang.servlet.ServletDemo05</servlet-class> </servlet> <servlet-mapping> <servlet-name>sd5</servlet-name> <url-pattern>/sd5</url-pattern> </servlet-mapping>
resources/db.properties
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zYp0Gd4g-1658156711681)(https://s2.loli.net/2022/07/18/7iTUv3ekJOAcXol.png)]
username=root password=123456
测试:访问到了db.properties文件中的数据
6.6 HttpServletRequest
6.7 HttpServletResponse
Response 响应
web服务器接收到客户端http请求,会针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse对象;
- 如果要获取客户端请求过来的参数,找HttpServletRequest;
- 如果要给客户端响应一些信息,找HttpServletResponse;
1、 简单分类
负责向浏览器发送数据的方法:
ServletResponse.java
// 一般写平常流用getOutputStream(),写中文用getWriter()
public ServletOutputStream getOutputStream() throws IOException;
public PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法:
ServletResponse.java
public void setCharacterEncoding(String charset);
public void setContentLength(int len);
public void setContentLengthLong(long len);
public void setContentType(String type);
public void setBufferSize(int size);
HttpServletResponse.java
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);
响应的状态码:
ServletResponse.java
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2、常见应用
1、向浏览器输出消息
2、下载文件
- 要获取下载文件的路径
- 下载的文件名?
- 设置想办法让浏览器可以支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓存区
- 获得OutputStream对象
- 将FileOutputStream流写入到buffer缓存区
- 使用OutputStream将缓冲区中的数据输出到客户端!
package com.kuang.servlet;
import sun.net.www.content.image.png;
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;
/*
下载文件功能:
1. 要获取下载文件的路径
2. 下载的文件名?
3. 设置想办法让浏览器可以支持下载我们需要的东西
4. 获取下载文件的输入流
5. 创建缓存区
6. 获得OutputStream对象
7. 将FileOutputStream流写入到buffer缓存区
8. 使用OutputStream将缓冲区中的数据输出到客户端!
*/
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//1. 要获取下载文件的路径
//String realPath = this.getServletContext().getRealPath("/1.png");
String realPath = "D:\\IdeaProjects\\javaweb-02-servlet\\response\\target\\classes\\1.png"; //target\classes\1.png右键copy path
System.out.println("下载文件的路径"+realPath);
//2. 下载的文件名? 从realPath中截取
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);// \转义字符
//3. 设置想办法让浏览器可以支持下载我们需要的东西,这里就是要设置浏览器行为,通过Response对象来进行设置
//Content-Disposition 通知客户端以下载的方式接受数据
resp.setHeader("Content-Disposition", "attachmen;filename="+fileName);
//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 {
}
}
测试下载:
图片名命名为中文名时:
修改
package com.kuang.servlet;
import sun.net.www.content.image.png;
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;
/*
下载文件功能:
1. 要获取下载文件的路径
2. 下载的文件名?
3. 设置想办法让浏览器可以支持下载我们需要的东西
4. 获取下载文件的输入流
5. 创建缓存区
6. 获得OutputStream对象
7. 将FileOutputStream流写入到buffer缓存区
8. 使用OutputStream将缓冲区中的数据输出到客户端!
*/
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//1. 要获取下载文件的路径
//String realPath = this.getServletContext().getRealPath("/1.png");
String realPath = "D:\\IdeaProjects\\javaweb-02-servlet\\response\\target\\classes\\秦疆.png"; //target\classes\1.png右键copy path
System.out.println("下载文件的路径"+realPath);
//2. 下载的文件名? 从realPath中截取
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);// \转义字符
//3. 设置想办法让浏览器可以支持下载我们需要的东西,这里就是要设置浏览器行为,通过Response对象来进行设置
//Content-Disposition 通知客户端以下载的方式接受数据 中文文件名URLEncoder.encode编码,否则可能会有乱码
resp.setHeader("Content-Disposition", "attachmen;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 {
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dhbd9jfz-1658156711684)(https://s2.loli.net/2022/07/18/GHIrKnh1XPuQUMp.png)]
3、验证码功能
验证怎么老的?
-
前端实现
-
后端实现,需要用到java的图片类,生成一个图片,图片中的数字3秒刷新一次
ImageServlet.java
package com.kuang.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; /* HttpServletResponse 验证码实现示例 */ public class ImageServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //想要响应一个图片到前端去 //如何让浏览器 3s 刷新一次 resp.setHeader("refresh","3"); //在内存中创建一个图片 BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_BGR); //得到图片 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/jpeg"); //网站存在缓存,我们需要不要让浏览器缓存 resp.setDateHeader("expires", -1); resp.setHeader("Cache-Control", "no-cache"); resp.setHeader("Pragma", "no-cache"); //把图片写给浏览器 ImageIO.write(image, "jpg",resp.getOutputStream()); } //生成随机数 7位, 拼接一个“”空字符串,返回String类型num 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"); //保证随机数是7位,不是7位用0附加 } String s = sb.toString()+num; return s; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
web.xml
<servlet> <servlet-name>ImageServlet</servlet-name> <servlet-class>com.kuang.servlet.ImageServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ImageServlet</servlet-name> <url-pattern>/img</url-pattern> </servlet-mapping>
测试:访问localhost:8080/r/img
持续更新中