当前位置: 首页 > news >正文

JavaWeb(一) | 基本概念(web服务器、Tomcat、HTTP、Maven)、Servlet 简介

1. 基本概念

1.1、前言

web开发:

  • web,网页的意思,www.baidu.com·
  • 静态 web
    • html,css
    • 提供给所有人看的数据始终不会发生变化!
  • 动态 web
    • 淘宝,几乎是所有的网站;
    • 提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同!
    • 技术栈:Servlet/JSP,ASP,PHP

1.2、web应用程序

可以提供浏览器访问的程序;

  • a.html、b.html.…. 多个 web 资源,这些 web 资源可以被外界访问,对外界提供服务;
  • 你们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上。
  • URL:通过这个 URL 可以访问到某个电脑上的资源
  • 这个统一的web资源会被放在同一个文件夹下,web应用程序 需要依赖 Tomcat:服务器 来展示
  • 一个web应用由多部分组成(静态web,动态web)
    • html,css,js
    • jsp,servlet
    • Java程序
    • jar包
    • 配置文件(Properties)

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

1.3、静态web

  • *.htm, *.html 这些都是网页的后缀、如果服务器上一直存在这些东西,我们就可以直接进行读取(需要网络);

下面是静态 web 的流程
在这里插入图片描述

  • 静态web存在的缺点
    • Web页面无法动态更新,所有用户看到都是同一个页面
      • 轮播图,点击特效:伪动态,下面是让静态页面可以动起来的两种技术
      • JavaScript [实际开发中,它用的最多]
      • VBScript
    • 它无法和数据库交互(数据无法持久化,用户无法交互)

1.4、动态web

页面会动态展示,“web 页面的展示效果因人而异”

WebServer Plugin 一个处理静态资源,一个处理动态资源,静态资源就是上面那条路,先走 WebServer,去 File System 获取静态资源。动态资源会去请求动态资源 JSP/Servlet,请求完了交给 WebServer
在这里插入图片描述

缺点:

  • 加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;
  • 重新发布就需要停机维护

优点:

  • Web页面可以动态更新,所有用户看到都不是同一个页面
  • 它可以与数据库交互(数据持久化:注册,商品信息,用户信息………)
    在这里插入图片描述

2、web服务器

2.1、技术讲解

ASP:

  • 微软:国内最早流行的就是 ASP;
  • 在HTML中嵌入了VB的脚本,ASP+COM;
  • 在ASP开发中,基本一个页面都有几千行的业务代码,页面极其混乱 维护成本高!
  • C# 语言开发
  • 使用的是 IIS 服务器

php:

  • PHP开发速度很快,功能很强大,跨平台,代码很简单(中国 70% 的网站都是 PHP 做的,WP)
  • 无法承载大访问量的情况(局限性)

JSP/Servlet: (JSP 本质是 Servlet)
B/S 架构:浏览器和服务器; C/S:客户端和服务器

  • sun 公司主推的 B/S 架构
  • 基于 Java 语言的(所有的大公司,或者一些开源的组件,都是用 Java 写的)
  • 可以承载三高问题带来的影响;(高并发、高可用、高性能)
  • 语法很像 ASP,很容易从 ASP → \to JSP,加强市场强度;

2.2、web服务器

服务器是一种被动的操作,用来处理用户的一些请求和给用户一些响应信息;(比如 lIS)

IIS 是微软的,用于运行 ASP,Windows 中自带的一些程序

Tomcat

在这里插入图片描述
工作中面向百度编程:

Tomcat 是 Apache 软件基金会(Apache Software Foundation) 的 jakarta 项目中的一个核心项目,最新的 Servlet 和 JSP 规范总是能在 Tomcat 中得到体现,因为 Tomcat 技术先进、性能稳定,而且免费,因而深受 java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的 Web 应用服务器。

Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选。对于一个Java初学web的人来说,它是最佳的选择

Tomcat 实际上运行JSP页面和Servlet。Tornct最新版为9.0

工作3-5年之后,可以尝试手写 Tomcat 服务器;

下载 Tomcat:

  1. 安装 or 解压
  2. 了解配置文件及目录结构
  3. 这个东西的作用

3、Tomcat

3.1、安装tomcat tomcat

官网: http://tomcat.apache.org/

我这里下载的 linux 版本
在这里插入图片描述
在这里插入图片描述

3.2、Tomcat启动和配置

1、右击“我的电脑” >> 选择“属性” >> 单击左侧栏 “高级系统设置” >>“高级”>>“环境变量”

2、在系统变量这一栏里,配置Tomcat的环境变量:
变量名:CATALINA_HOME
变量值:D:\Program Files\tomcat\apache-tomcat-9.0.93
在这里插入图片描述

找到Path变量,点击编辑:%CATALINA_HOME%\bin
在这里插入图片描述


注意还需要 JAVA 环境,%JAVA_HOME%\bin

1、闪退,说明我们环境没有配好,或者没配Java的环境(检查自己配置的变量)

2、乱码,如果界面是下面这样(乱码),这是因为我们的dos窗口和Tomcat编码类型不一致导致的

文件夹作用:
在这里插入图片描述

bin 目录下启动,关闭 Tomcat
在这里插入图片描述

访问测试: http://localhost:8080/

可能遇到的问题:

  1. Java环境变量没有配置
  2. 闪退问题:需要配置兼容性
  3. 乱码问题:配置文件中设置

可以修改 conf/logging.properties 中的 java.util.logging.ConsoleHandler.encoding = GBK 解决乱码问题

3.3、配置

在这里插入图片描述
打开这个 server.xml 文件,可以配置启动的端口号等

网页显示:
在这里插入图片描述

端口设置:
在这里插入图片描述

一个文件夹就是一个 web 应用,默认给出了 5 个 web 应用
在这里插入图片描述

现在对 ROOT 中的文件夹下的 index.jsp 进行修改。(jsp 实际上就是 js 中加入了 java 程序)
在这里插入图片描述

在这里插入图片描述

然后通过 bin 文件下的 startup.bat 启动,http://localhost:8080/ ,可以看到改动了
在这里插入图片描述

现在我们改动端口,将 conf 文件夹下的 server.xml 中的端口改为 8090,重新启动,8080 端口无法访问需要 http://localhost:8090/

在这里插入图片描述

注意 localhost 在这里改了之后是无法访问的
在这里插入图片描述
在这里插入图片描述

平时看到可以 www.baidu.com 访问。为什么呢?

在 C:\Windows\System32 下有一个 System32 文件夹,里面有我们核心配置,drivers 文件夹,里面有很多核心驱动,下面有一个 etc,是配置文件,里面有个 hosts 主机,打开 添加 127.0.0.1 www.future.com (注意改动需要在管理员权限下,先管理员权限运行记事本,然后打开)
在这里插入图片描述

在这里插入图片描述

www.future.com:8090,成功访问
在这里插入图片描述

  • tomcat 的默认端口号为:8080
  • mysql:3306
  • http:80
  • https:443

右键网页,检查,网络里面点击地址,可看到默认端口号,但是并不是所有网站都可以查看的
在这里插入图片描述

可以配置端口号

<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />

可以配置本地地址

  • 默认的主机名为:localhost->127.0.0.1
  • 默认网站应用存放的位置为:webapps
  <Host name="www.qinjiang.com"  appBase="webapps"unpackWARs="true" autoDeploy="true">

高难度面试题:

请你谈谈网站是如何进行访问的!

  1. 输入一个域名,如 www.baidu.com 或者 localhost:8080 等,回车
  2. 检查本机的 C:\Windows\System32\drivers\etc\hosts 配置文件下有没有这个域名映射;
    • 有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问,比如我们上述配置的 127.0.0.1 www.future.com

    • 没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;

在这里插入图片描述

4.可以配置一下环境变量(可选性)

3.4、发布一个web网站

不会就先模仿!!!

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

Tomcat 原始网页是寻找 ROOT 下的内容,现在 copy 一份,命名为 future
在这里插入图片描述
除了 WEB-INF 的其他文件都可以删除,WEB-INF 目录代表一个网站,WEB-INF 下面有一个 web.xml,这个是一定不能删除的。
在这里插入图片描述
打开 web.xml
在这里插入图片描述

现在开始写程序,分为静态 Web 和动态的 Web,先写一个静态的,在 future 文件夹下创建一个 index.html,并在网络上任意找了一段 html 代码如下,放入到 index.html 中,直接双击 index.html 就可以看到里面的内容

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>flex弹性布局-今日头条首页热门视频栏</title><style type="text/css">body {margin: 0;padding: 0;}a{text-decoration: none;}.show-monitor {width: 320px;height: 600px;/* border: 2px solid red; */margin: 50px 0px 0px 50px;}.panel-head {display: flex;/* height: 100px; *//* 解除图标变形 */align-items: center;}.panel-head span.panel-head-title {/* 占满全部空间 */flex-grow: 1;font-size: 20px;margin-left: 10px;}.panel-head .panel-head-sx {font-size: 16px;color: red;margin-left: 5px;}.panel-con {height: 94px;/* background-color: antiquewhite; */margin-top: 20px;display: flex;}.panel-con .panel-con-img {width: 126px;/* 高度自动继承 *//* height: 94px; *//* background-color: aqua; */margin-right: 10px;flex-shrink: 0;}.panel-con .panel-con-img img {width: 100%;height: 100%;/* 裁剪图片 防止变形 */object-fit: cover;}.panel-con .panel-con-txt {/* background-color: aquamarine; *//* 占满剩余空间 */flex-grow: 1;display: flex;flex-direction: column;text-overflow: ellipsis;}.panel-con .panel-con-txt a{font-size: 16px;color: #222;/* 超过44px文字不再显示 */max-height: 44px;overflow: hidden;line-height: 22px;/* 弹性伸缩盒子模型显示 */display: -webkit-box;/* 设置或检索伸缩盒子对象的子元素的排列方式 */-webkit-box-orient: vertical;/* 限制在一个块级元素显示的文本的行数 */-webkit-line-clamp: 2;/* 文本溢出显示省略号 */text-overflow: ellipsis;}.panel-con .panel-con-txt span.like{font-size: 12px;background-color: #fff2f2;color: #f04142;/* 消除占满整行现象 变为内容实际所占宽度*/align-self: flex-start;padding: 3px 6px;border-radius: 5px;margin-top: 5px;}.panel-con .panel-con-txt .desc{font-size: 14px;color: #999;display: flex;justify-content: space-between;margin-top: 5px;}</style></head><body><div class="show-monitor"><div class="panel-head"><img src="images/icon-play.png" alt="" width="22"><span class="panel-head-title">热门视频</span><img src="images/icon-sx2.png" alt="" width="16"><span class="panel-head-sx">换一换</span></div><div class="panel-con"><div class="panel-con-img"><a href=""><img src="images/toutiao-01.jpeg" alt=""></a></div><div class="panel-con-txt"><a href="">司马南:中国与俄罗斯的战线</a><span class="like">1万评论</span><div class="desc"><span>148万次观看</span><span>司马南频道</span></div></div></div><div class="panel-con"><div class="panel-con-img"><a href=""><img src="images/toutiao-02.jpeg" alt=""></a></div><div class="panel-con-txt"><a href="">无论做什么鱼:最忌放盐和料酒研制,大厨教你绝招.</a><span class="like">1万评论</span><div class="desc"><span>148万次观看</span><span>司马南频道</span></div></div></div><div class="panel-con"><div class="panel-con-img"><a href=""><img src="images/toutiao-03.jpeg" alt=""></a></div><div class="panel-con-txt"><a href="">司马南:中国与俄罗斯的战线</a><span class="like">1万评论</span><div class="desc"><span>148万次观看</span><span>司马南频道</span></div></div></div><div class="panel-con"><div class="panel-con-img"><a href=""><img src="images/toutiao-04.jpeg" alt=""></a></div><div class="panel-con-txt"><a href="">司马南:中国与俄罗斯的战线</a><span class="like">1万评论</span><div class="desc"><span>148万次观看</span><span>司马南频道</span></div></div></div></div></body>
</html>

重新启动 Tomcat,它会自动访问 ROOT 下面的内容,进一步输入 localhost:8090/future/,就会访问 future 文件夹下的资源,实际会自动添加 localhost:8090/future/index.html,静态 web,不会动的
在这里插入图片描述

同理,还可以通过 localhost:8090/docs/ 访问 docs 文件夹下的内容,其他文件下的内容同理
在这里插入图片描述

重点是 examples 文件夹下有很多例子,访问 localhost:8090/examples/
在这里插入图片描述

比如进入 Servlet Examples,很多例子可以执行,可以通过 Source 查看源码,自学就可以通过这些例子来查看源码
在这里插入图片描述

网站应该有的结构

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

HTTP 协议: 面试

4.HTTP

4.2 什么是 HTTP?

HTTP(hypertext transport protocol) 超文本传输协议。

  • 文本 :HTML,字符串…
  • 超文本:图片,音乐,视频,定位,地图…
  • 80 端口

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

  • 443 端口

4.2 两个时代

HTTP 1.0:

  • HTTP/1.0:客户端与 Web 服务器连接后,只能获得一个 Web 资源,然后就断开连接,加入某个页面有多个图片资源需要加载,那么需要连接多次,影响服务器和客户端的性能。

HTTP 2.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.39:443
Accept:text/html  
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9    语言
Cache-Control:max-age=0
Connection:keep-alive

1、请求行

请求行中的请求方式:GET
请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…

  • get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
  • post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效。

2、消息头

Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.

4.4 HTTP 响应

  • 服务器 -> 响应(response) ->客户端

百度:

Cache-Control:private    缓存控制
Connection:Keep-Alive    连接
Content-Encoding:gzip    编码
Content-Type:text/html   类型

1、响应体

Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;

2、响应状态码

200:请求响应成功 200

3xx:请求重定向

  • 重定向:你重新到我给你新位置去;

4xx:找不到资源 404
5xx:服务器代码错误 500 502:网关错误

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

5. Maven

  • 在 JavaWeb 开发中,需要使用大量的 jar 包,我们手动去导入;
  • 如何能够让一个东西自动帮我导入和配置这个jar包。

由此,Maven诞生了!

5.5 标记文件夹功能

通过选中文件夹,将其标记为 maven 对应的文件夹
在这里插入图片描述

在这里插入图片描述


还有一种标记方式如下:
在这里插入图片描述

可以通过这里点击文件夹,然后点击 Mark as 的一个标记来标记此文件夹
在这里插入图片描述

5.6 在 IDEA 中配置 Tomcat

先创建一个maven项目,选择 webapp
在这里插入图片描述

结构如下:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

解决警告问题

必须要的配置:为什么会有这个问题:因为我们访问一个网站,需要指定一个文件夹名字(之前是默认 webapps 这个文件),IDEA 配置 tomcat 时没有这个默认文件,所以我们要手动配置

在这里插入图片描述
选择 war,就配置好啦
在这里插入图片描述

在这里点击启动
在这里插入图片描述

成功访问
在这里插入图片描述

可能存在 Maven 默认 Web 项目中的 web.xml 版本问题
在这里插入图片描述

在这里插入图片描述

替换为 webapp4.0 版本和 Tomcat 一致

<?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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

5.7 部分其他问题

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

在 pom.xml 中配置,比如默认情况我们在资源文件 resources 下写的 properties 文件才会被打包,在 java 源代码文件下撰写的 properties 文件最终是无法被导出的,为了解决这个问题添加配置信息如下半部分

<!--在build中配置resources,来防止我们资源导出失败的问题-->
<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>

6. Servlet 简介

Servlet 就是 Sun 公司开发动态 Web 的一门技术

Sun 在这些 API (Application Programming Interface,应用程序接口)中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:

  • 编写一个类,实现Servlet接口。
  • 把开发好的Java类部署到web服务器中。

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

6.2 HelloServlet

Serlvet 接口 Sun 公司有两个默认的实现类:HttpServlet,GenericServlet

  1. 构建一个普通的 Maven 项目,删掉里面的 src 目录,以后我们的学习就在这个项目里面建立 Moudel;这个空的工程就是Maven主工程(建一个WebApp Maven项目,勾选模板),因为可以在项目内构建多个子工程,每个子工程都有自己的 pom.xml;
    在这里插入图片描述

尽可能的把所有依赖都导入到主工程的 pom.xml 中,在 maven 仓库 中,获取 servlet 的依赖,加入到主工程中。

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
</dependency>

同时把 JSP 的依赖添加到主工程中

<!-- 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><scope>provided</scope>
</dependency>

通常只有版本信息会变 version 字段
在这里插入图片描述

构建一个 servlet 项目,新建 Module
在这里插入图片描述

由于 servlet 是一个 web 项目,选中模版中的 org.apache.maven.archetypes:maven-archetype-webapp
在这里插入图片描述
在这里插入图片描述

  1. 关于Maven父子工程的理解:

父项目的 pom.xml 中会有:

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

如果多个子项目,父项目的 pom.xml 中会有

<modules><module>servlet-01</module><module>subproject-01</module><module>subproject-02</module><module>subproject-03</module>....
</modules>

子项目中会有:

<parent><artifactId>Servlet</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version>
</parent>

父项目中的 jar 包子项目可以直接使用,但是子项目中的,父项目不可以使用

son extends father
  1. Maven 环境优化
  • 修改 web.xml 为最新的
  • 将 maven 的结构搭建完整

产生 servlet-01 子项目后,第一步,将 src/main/webapp/WEB-INF/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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

然后再 src/main 下,新建 java、resources ,并标记为 源代码文件和资源文件
在这里插入图片描述

  1. 编写一个Servlet程序
  • 编写一个普通类
  • 实现 Servlet 接口,这里我们直接继承 HttpServlet

在这里插入图片描述

建包
在这里插入图片描述

创建类 HelloServlet
在这里插入图片描述

然后让类继承 HttpServlet 接口,子工程会自动导包父工程
在这里插入图片描述

如果无法正常自动导包父工程中的 jar 包,检查父工程 pom.xml 如下:(外层不要使用
dependencyManagement,注释掉 scope)
在这里插入图片描述

重写 get,post 方法

在这里插入图片描述

S1:编写一个普通类
S2:实现 Servlet 接口,这里我们直接继承 HttpServlet

由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;

public class HelloServlet extends HttpServlet {//由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletOutputStream outputStream = resp.getOutputStream();PrintWriter writer = resp.getWriter(); //响应流writer.print("Hello,Serlvet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
  1. 编写 Servlet 的映射

为什么需要映射:我们写的是 Java 程序,但是要通过浏览器访问,而浏览器需要连接 Web 服务器,所以我们需要在 Web 服务中注册我们写的 Servlet,还需给他一个浏览器能够访问的路径;

<!--注册Servlet-->
<servlet><servlet-name>hello</servlet-name><servlet-class>com.uestc.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern>
</servlet-mapping>

在这里插入图片描述

  1. 配置 Tomcat
    注意: 配置项目发布的路径就可以了

在这里插入图片描述
在这里插入图片描述

配置好后,解决警告,点击 Fix
在这里插入图片描述

会进入到 Deployment,选择项目 servlet-01:war
在这里插入图片描述

或者点击 + 号,选择则 artifacts,再设置,其中 Application context 设置为 /s1,表示请求
在这里插入图片描述

  1. 启动测试,OK!

在这里插入图片描述

项目下面会产生一个 target 文件夹,里面就是我们项目的信息
在这里插入图片描述

成功访问,我们设置的 8090 端口,s1 下进行访问,成功!(通常是 8080 端口)
在这里插入图片描述

网页上查找 hello 的请求路径
在这里插入图片描述

会在 Servlet 的请求路径中查看 url-pattern,找到 hello,获取到 name 为 hello,在 servlet 中找到 hello,获取到对应的类,如下:
在这里插入图片描述

6.3、Servlet原理

Servlet是由Web服务器调用,浏览器会向 Web 容器发送 http 请求(request 请求),如果是首次访问,会将我们编写的 java 类编译成 class 类去运行,如果项目比较庞大,第一次会比较慢,后面就会很快。

在这里插入图片描述

web 容器会产生两个对象,请求(request)和响应(response),servlet 里面有个 service 方法,这个方法可以处理请求和响应,因此 请求(request)和响应(response)对象会去调用这个 service 方法。 Request 从 service 方法中拿到请求,并把请求之后的响应交给 Response
在这里插入图片描述

获取响应信息的过程如下:
在这里插入图片描述

获取到响应信息后就可以返回给客户端了,整个流程如下
在这里插入图片描述

6.4 Mapping 问题

  1. Mapping 是请求映射的一个路径,一个 Servlet 指定一个映射路径的情况:
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern>
</servlet-mapping>
  1. 一个 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>
  1. 一个Servlet指定通用映射路径,使用 /*,这个通配符
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  1. 默认请求路径(就是什么都不写,会走如下请求)
<!--默认请求路径-->
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/*</url-pattern>
</servlet-mapping>
  1. 指定一些后缀或者前缀等等….
<!--可以自定义后缀实现请求映射注意点,*前面不能加项目映射的路径hello/sajdlkajda.qinjiang-->
<servlet-mapping><servlet-name>hello</servlet-name><url-pattern>*.qinjiang</url-pattern> <!-- 不能写成 /*.qinjiang --> 
</servlet-mapping>

1. 使用 /* (通用路径匹配)

<servlet-mapping>  <servlet-name>hello</servlet-name>  <url-pattern>/hello/*</url-pattern>  
</servlet-mapping>  
  • 匹配路径:匹配所有以 /hello/ 开头的路径,例如 /hello/abc/hello/xyz/def
  • 用途:这种方式通常用于匹配某个特定前缀后的所有路径。可以让 servlet 处理以某个特定路径为前缀的所有请求。
  • 说明/* 会匹配 /hello/ 后面的所有路径和子路径。例如,/hello/test/hello/abc/xyz 都会被 hello servlet 处理。

2. 默认请求路径 /*

<!--默认请求路径-->  
<servlet-mapping>  <servlet-name>hello</servlet-name>  <url-pattern>/*</url-pattern>  
</servlet-mapping>  
  • 匹配路径:这种配置会匹配所有的请求路径,包括根路径和所有的子路径,例如 /abc/hello/xyz/abc 等。
  • 用途:适用于在没有明确指定路径的情况下,处理所有请求。非常常见于默认 servlet 或通用处理请求的场景。需要谨慎使用,因为它会拦截所有的请求,包括静态资源(如图片、CSS、JS 等)。
  • 说明/* 匹配所有请求,通常作为全局的默认映射。

3. 使用后缀(自定义后缀)

<!--可以自定义后缀实现请求映射-->  
<servlet-mapping>  <servlet-name>hello</servlet-name>  <url-pattern>*.qinjiang</url-pattern>  
</servlet-mapping>  
  • 匹配路径:只会匹配以 .qinjiang 为后缀的路径。例如,/hello/something.qinjiang 会被 hello servlet 处理。
  • 用途:用于将特定的 URL 后缀映射到指定的 servlet。例如,某些特殊类型的文件请求可以由某个 servlet 处理,而其他请求则交给其他 servlet 或静态资源处理。
  • 说明:这种方式比较特殊,通常用于基于文件后缀的请求路由。**注意:**不能在前面加上 /,因为 url-pattern 是通过匹配路径来识别请求的,* 只能匹配文件名的后缀。

总结

  • /*(例如 /hello/*)用于匹配以某个特定路径开头的所有请求(支持多层级路径)。
  • /* 用于匹配所有请求路径(全局匹配)。
  • *.qinjiang 用于匹配特定后缀的请求,通常用于指定文件类型的请求处理。

选择使用哪种方式,取决于你的需求:

  • 如果你需要针对特定路径做处理,使用 /hello/*
  • 如果你需要拦截所有请求,使用 /*
  • 如果你需要根据文件后缀进行处理,使用 *.qinjiang
  1. 优先级问题
    指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<!--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>

6.5 ServletContext对象

Web 应用程序的上下文(Web Application Context)是指 Web 应用程序在运行时的环境和状态信息的集合。它提供了一个在整个应用程序范围内共享的区域,包含了应用的配置、资源、参数和一些状态信息。在 Servlet 容器中,ServletContext 就是表示 Web 应用程序上下文的对象。它提供了跨 Servlet 共享数据、访问应用参数、获取资源、日志记录等功能。

主要功能:

  1. 共享资源:通过 setAttribute()getAttribute() 方法,多个 Servlet 可以共享数据。
  2. 访问应用参数:通过 getInitParameter() 获取 web.xml 中的初始化参数。
  3. 资源访问:通过 getResource()getResourceAsStream() 获取应用中的静态资源。
  4. 日志记录:使用 log() 方法记录应用日志。
  5. 获取服务器信息:使用 getServerInfo() 获取容器的基本信息。

举例:

在 Servlet 容器中,当应用启动时,容器为每个 Web 应用程序创建一个 ServletContext 对象,该对象管理该应用程序的配置、资源、生命周期等信息。

总结:

Web 应用程序的上下文是一个虚拟环境,包含了 Web 应用的配置、资源、共享数据和生命周期信息。它使得不同的组件(如 Servlet、Filter 等)能够在同一个 Web 应用内共享信息和资源。ServletContext 用于跨 Servlet 共享资源、访问应用级参数、获取资源及日志记录,是 Web 应用的重要上下文对象。

先在父工程下新建一个 servlet-02 项目
在这里插入图片描述

父工程的 pom.xml 多了一个模块
在这里插入图片描述

更改 servlet-02 中的 src/main/webapp/WEB-INF/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/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>

添加 源码目录(java)和资源目录(resources),进行标记
在这里插入图片描述

如果:Maven pom.xml 文件变灰且中间有一条横线的处理办法:
是因为 pom.xml 文件被设置在maven忽略文件清单中
解决方法: file -->setting–>maven–>Ignored Files 将清单中对应项目的pom.xml文件取消选中即可;

创建 HelloServlet

public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("Hello"); // 向后台输入也能测试 servlet}
}

在这里插入图片描述

然后在 web.xml 中注册 Servlet

    <!--注册Servlet--><servlet><servlet-name>hello</servlet-name><servlet-class>com.uestc.servlet.HelloServlet</servlet-class></servlet><!--Servlet的请求路径--><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping>

Tomcat 配置
在这里插入图片描述

多了一个 servlet-02 war 包,添加进入,并去掉之前的 servlet-01:war,需要保持这里面只有一个 war 包,因为添加两个打包会很慢
在这里插入图片描述
在这里插入图片描述

然后在网页上走 hello 这个请求 http://localhost:8090/s2/hello,页面没有任何东西,后台输出了 hello(因为我们上面代码的 response 没有响应到页面,只是让后台输出了 hello)
在这里插入图片描述

查看 HttpServlet 类中的方法
在这里插入图片描述

下面我们重点来看 ServletContext:web 容器在启动的时候,他会为每个 web 程序都创建一个对应的ServletContext 对象,它代表了当前的 web 应用;

思考一个问题:不同的 Servlet 之间能否互相传送数据。(能,保存在 ServletContext 中,其他 Servlet 直接读取里面的东西即可)
在这里插入图片描述

更改 Servelt-02 的 HelloServlet 如下,将数据保存到 ServletContext

public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//this.getInitParameter()   初始化参数//this.getServletConfig()   Servlet配置//this.getServletContext()  Servlet上下文ServletContext context = this.getServletContext();String username = "青年有志"; // 数据,这里使用中文,可以导致乱码context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username}
}

在 Servelt-02 中创建一个 GetServlet
在这里插入图片描述

public class GetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = (String) context.getAttribute("username");resp.setContentType("text/html");resp.setCharacterEncoding("utf-8"); // 正常显示中文resp.getWriter().print("名字"+username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

在 Servelt-02 下的 web.xml 中进行配置
在这里插入图片描述
配置名字为 getc(自定义)

    <servlet><servlet-name>getc</servlet-name><servlet-class>com.uestc.servlet.GetServlet</servlet-class></servlet><servlet-mapping><servlet-name>getc</servlet-name><url-pattern>/getc</url-pattern></servlet-mapping>

重启 Tomcat,我们先请求 getc,为 null
在这里插入图片描述

那么我们先请求 hello,什么都没有,很正常,代码只实现了向 ServletContext 中写入数据
在这里插入图片描述

再执行请求 getc,成功获取!
在这里插入图片描述

6.5.1 共享数据

总结上述过程:在一个 servlet 中保存的数据,可以在另一个 servlet 中拿到;

需要一个放置数据的类

public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//this.getInitParameter()   初始化参数//this.getServletConfig()   Servlet配置//this.getServletContext()  Servlet上下文ServletContext context = this.getServletContext();String username = "秦疆"; //数据context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username 。值 username}
}

读取数据的类

public class GetServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();String username = (String) context.getAttribute("username");resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");resp.getWriter().print("名字"+username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

最后注册 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>/hello</url-pattern></servlet-mapping><servlet><servlet-name>getc</servlet-name><servlet-class>com.kuang.servlet.GetServlet</servlet-class></servlet><servlet-mapping><servlet-name>getc</servlet-name><url-pattern>/getc</url-pattern></servlet-mapping>

6.5.2 获取初始化参数 <context-param>

元素在 web.xml 中的作用是为 Web 应用程序提供全局的上下文参数。这些参数可以在整个应用程序中被访问,并且可以用于配置、初始化参数等。它们通常用于配置在整个 Web 应用中都需要访问的一些常量值,例如数据库连接、API 密钥、文件路径等。

使用 <context-param> 的基本语法

<context-param><param-name>参数名称</param-name><param-value>参数值</param-value>
</context-param>
  • <param-name>:这是参数的名称,定义了这个上下文参数的标识符。
  • <param-value>:这是参数的值,通常是一个字符串,可以是任意的配置信息。

典型的使用场景

  1. 数据库连接配置
    在 Web 应用程序中,你可能需要配置数据库连接的 URL、用户名、密码等信息,可以通过 <context-param> 来提供这些信息。

    <context-param><param-name>db.url</param-name><param-value>jdbc:mysql://localhost:3306/mydatabase</param-value>
    </context-param>
    <context-param><param-name>db.username</param-name><param-value>root</param-value>
    </context-param>
    <context-param><param-name>db.password</param-name><param-value>password123</param-value>
    </context-param>
    
  2. 文件路径或配置路径
    对于一些需要特定文件路径或者配置文件路径的情况,也可以通过 <context-param> 来传递这些路径信息。

    <context-param><param-name>config.file.path</param-name><param-value>/path/to/config.xml</param-value>
    </context-param>
    
  3. 外部服务或 API 配置
    如果应用需要访问外部 API 或服务,可以通过 <context-param> 存储 API 密钥、URL 等信息。

    <context-param><param-name>api.key</param-name><param-value>12345abcdef</param-value>
    </context-param>
    

访问 <context-param> 参数

一旦在 web.xml 中定义了 <context-param>,你就可以在应用程序的 Java 代码中访问这些参数。访问方式通常是通过 ServletContext 对象,下面是几种常见的访问方法:

1. 使用 ServletContext 访问参数
// 获取 ServletContext 对象
ServletContext context = getServletContext();// 获取参数值
String dbUrl = context.getInitParameter("db.url");
String dbUsername = context.getInitParameter("db.username");
String dbPassword = context.getInitParameter("db.password");
2. 在 ServletFilter 中使用

ServletFilter 中也可以轻松访问这些参数。比如:

@WebServlet("/example")
public class ExampleServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取 context-param 参数ServletContext context = getServletContext();String dbUrl = context.getInitParameter("db.url");// 使用 dbUrl 做其他操作response.getWriter().write("Database URL: " + dbUrl);}
}
3. 在 Listener 中使用

如果你需要在应用启动时进行初始化操作,也可以在 ServletContextListener 中访问这些参数:

public class AppContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {ServletContext context = sce.getServletContext();String dbUrl = context.getInitParameter("db.url");// 在此处使用 dbUrl 进行初始化数据库连接等操作}@Overridepublic void contextDestroyed(ServletContextEvent sce) {// 处理清理操作}
}

相关注意事项

  • 参数名称唯一性<param-name> 应该具有唯一性,以避免多个参数具有相同的名称,导致混淆。

  • 参数值类型<param-value> 中存储的通常是字符串类型的数据,但也可以通过解析或转换来处理更复杂的配置。例如,你可以将 JSON 配置字符串存储在 <param-value> 中,启动时再将其解析为对象。

  • 访问范围:这些参数是全局的,因此可以在整个 Web 应用程序中使用,但需要注意,如果多个模块需要不同的值,最好分开使用不同的参数名称来避免冲突。

  • 配置加载顺序:Web 应用程序启动时,web.xml 中的所有 <context-param> 会被读取,并可供应用中的所有组件使用。所以这些参数的加载顺序是先于 Servlet、Filter 等组件的初始化。

示例:web.xml 配置

<web-app 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/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><context-param><param-name>db.url</param-name><param-value>jdbc:mysql://localhost:3306/mydatabase</param-value></context-param><context-param><param-name>db.username</param-name><param-value>root</param-value></context-param><context-param><param-name>db.password</param-name><param-value>password123</param-value></context-param><servlet><servlet-name>exampleServlet</servlet-name><servlet-class>com.example.ExampleServlet</servlet-class></servlet><servlet-mapping><servlet-name>exampleServlet</servlet-name><url-pattern>/example</url-pattern></servlet-mapping></web-app>

在上面的示例中,<context-param> 用于配置数据库的连接信息,这些信息可以在 Web 应用程序中的各个 Servlet 或其他组件中通过 ServletContext 来访问。

<!--配置一些 web 应用初始化参数,比如配置 jdbc 连接-->
<context-param><param-name>url</param-name><param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>

下面在 Servlet-02 中创建类 ServletDemo03,并打印配置的 url

ServletContext context = this.getServletContext();String url = context.getInitParameter("url");resp.getWriter().print(url);

在这里插入图片描述

进行 Servlet 注册

<servlet>
<servlet-name>gp</servlet-name><servlet-class>com.uestc.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping><servlet-name>gp</servlet-name><url-pattern>/gp</url-pattern>
</servlet-mapping>

在这里插入图片描述

然后重启 Tomcat,然后请求 gp,localhost:8090/s2/gp,就拿到了上述我们配置的 url
在这里插入图片描述

6.5.3、请求转发

在 servlet-02 下面新建一个 ServletDemo04

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext context = this.getServletContext();System.out.println("进入了ServletDemo04"); // 查看是否成功进入//RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径,当前页面下的 gp//requestDispatcher.forward(req,resp); //调用forward实现请求转发;context.getRequestDispatcher("/gp").forward(req,resp); // 上面两行合并为一行
}

注册 servlet

    <servlet><servlet-name>sd4</servlet-name><servlet-class>com.uestc.servlet.ServletDemo04</servlet-class></servlet><servlet-mapping><servlet-name>sd4</servlet-name><url-pattern>/sd4</url-pattern></servlet-mapping>

重启 Tomcat,然后请求 sd4,获取到的是请求 gp 时的内容,这就是请求转发的效果,但是路径是不会改变的,还是 localhost:8090/s2/sd4,后面讲的重定向才会发生改变
在这里插入图片描述

A 想要拿到 C 的资源,但是无法直接调用 C,只能找到 B,可以先 B 找 C 拿,C 再给 B,B 再给 A,这就是请求转发,这样 A 的路径是没有变化的,只有转发的概念,如下图上部分

什么是重定向?A 告诉 B ,要拿一个资源,但是资源只有 C 有,B 就告诉 A ,去 C 哪里拿,A 又去找 C,到时候会发生跳转,如下图下半部分

在这里插入图片描述

在 Java Web 开发中,请求转发(Request Forwarding)是一种由服务器端处理的请求流转机制,它允许将客户端的请求从一个 Servlet 转发到另一个 Servlet、JSP 页面或其他资源,而无需客户端知道这一过程。

context.getRequestDispatcher("/gp").forward(req, resp); 语句是实现请求转发的一种方式

1. 什么是请求转发?

请求转发是服务器端的一种处理方式,其中服务器将客户端的请求(HttpServletRequest)转发到另一个资源(如另一个 Servlet、JSP 页面、HTML 页面等)。转发后,客户端并不知道请求被转发到哪里,它只知道发出了请求,而最终的响应是由转发后的资源生成并返回的。

2. RequestDispatcher 接口

RequestDispatcher 是 Java Servlet API 中的一个接口,它提供了两种主要的方法来转发请求或包括资源的内容:

  • forward(ServletRequest request, ServletResponse response):将请求转发到另一个资源(Servlet、JSP 页面等),请求会继续在服务器端处理,而客户端并不会知道这个过程。转发后,控制权交给目标资源,原请求的 requestresponse 会被传递给目标资源。
  • include(ServletRequest request, ServletResponse response):将请求的响应内容包含在另一个资源的响应中。通常是将另一个 Servlet 或 JSP 页面的内容插入到当前页面中。

3. context.getRequestDispatcher("/gp").forward(req, resp) 解释

context.getRequestDispatcher("/gp").forward(req, resp);  
  • context: 这里的 contextServletContext 对象,它表示应用的上下文。可以通过 getServletContext() 方法获取它。
  • getRequestDispatcher("/gp"): getRequestDispatcher 方法返回一个 RequestDispatcher 对象,表示可以将请求转发到指定路径的资源。这里的 "/gp" 是转发的目标路径,它可以是:
    • 相对路径/gp 是从 Web 应用的根目录开始的相对路径,也可以是 /contextPath/gp。如果路径是 /gp,那么它会映射到 Web 应用根目录下的 gp 资源(例如 gp 对应的 Servlet 或 JSP)。
    • 绝对路径getRequestDispatcher("/somePath") 表示从 Web 应用根目录开始的路径。注意这里的路径是相对于 Web 应用的根路径的,而不是相对于当前请求的路径。
  • forward(req, resp):这将把当前请求转发到 /gp 路径指定的资源,并将原始的请求对象(req)和响应对象(resp)传递给目标资源。转发后,控制权交给 /gp 对应的资源进行处理。

4. 请求转发的特点

  • 服务器端操作:请求转发完全由服务器处理,客户端(浏览器)并不知道请求已经被转发。
  • 共享请求和响应对象:在转发过程中,原始的 requestresponse 对象会被传递给目标资源。因此,转发后的资源可以访问到原始请求中的所有参数、属性等。
  • URL 不变:请求转发后,客户端浏览器的 URL 不会发生变化,仍然是最初请求的 URL。这是请求转发与重定向的一个主要区别。

5. 请求转发的应用场景

请求转发通常用于以下几种情况:

  1. 请求链处理
  • 在 Web 应用中,一个请求可能需要经过多个 Servlet 或资源的处理。例如,一个请求在一个 Servlet 中进行验证或设置了数据,然后转发到另一个 Servlet 或 JSP 页面处理结果并展示给用户。
  • 示例:用户登录后,先由一个 Servlet 进行身份验证,然后将验证结果转发到一个显示用户信息的页面。
  1. JSP 页面之间的跳转
  • 一个 Servlet 或一个 JSP 页面可以通过请求转发将请求传递给另一个 JSP 页面,生成最终的响应。
  • 示例:一个 Servlet 处理了表单提交的逻辑后,将请求转发到一个 JSP 页面显示结果。
  1. 分布式 Web 应用中的请求处理
  • 在某些分布式 Web 应用中,一个 Servlet 可能会将请求转发到另一台服务器上的资源进行处理。

6. 转发与重定向的区别

请求转发和重定向都是 Web 开发中常用的请求处理方式,它们有以下不同之处:

特点请求转发 (forward)重定向 (sendRedirect)
控制权由服务器控制,客户端不知道转发过程由客户端控制,浏览器会重新发起请求
URL 变化不会变化,浏览器 URL 不变会变化,浏览器 URL 会更新为目标 URL
请求传递请求对象和响应对象会传递给目标资源新的请求会发往服务器,原请求信息丢失
请求次数只有一次请求会发起两次请求:一次到当前资源,另一次到目标资源
适用场景服务器端的资源跳转,内部请求处理链客户端跳转,或者跨应用的请求

7. 实际示例

假设我们有以下的 Web 应用结构:

/webapp  
├── /index.jsp  
├── /loginServlet  
└── /welcome.jsp  

loginServlet 负责处理登录逻辑,登录成功后将请求转发到 welcome.jsp 页面:

LoginServlet.java
@WebServlet("/loginServlet")  
public class LoginServlet extends HttpServlet {  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  String username = request.getParameter("username");  String password = request.getParameter("password");  // 假设验证成功  if ("user".equals(username) && "pass".equals(password)) {  // 登录成功,转发到欢迎页面  request.getRequestDispatcher("/welcome.jsp").forward(request, response);  } else {  // 登录失败,转发回登录页面  request.getRequestDispatcher("/index.jsp").forward(request, response);  }  }  
}  
welcome.jsp
<html>  
<body>  <h1>Welcome, you have logged in successfully!</h1>  
</body>  
</html>  

8. 总结

  • 请求转发是服务器端的操作,客户端无法察觉,适用于在服务器端处理多个资源之间的请求。
  • 通过 RequestDispatcherforward() 方法实现请求的转发。
  • 请求转发不会改变浏览器 URL,且请求和响应对象保持一致,适合用于多个资源的内部处理链。

6.5.4、读取资源文件 properties 文件内容

在 Web 应用中,通常资源文件(例如 db.properties)会被放置在类路径中,例如 WEB-INF/classes 目录下。在这种情况下,您不需要硬编码绝对路径,而是依赖于类路径来动态访问文件。下面我将详细说明如何在 Web 应用中通过 HTTP 请求加载 db.properties 文件。

1. 类路径概念

在 Java Web 应用中,所有的 Java 类文件和资源文件(例如 .properties 文件、.xml 文件等)最终都会打包到应用的类路径中。通常:

  • 编译后的 .class 文件放在 WEB-INF/classes 目录下。
  • 资源文件(如配置文件)也应放在 WEB-INF/classesWEB-INF 下的其他适当目录。

类路径是 Java 应用程序查找类文件和资源文件的地方。在 Web 应用中,类路径通常是 Web 应用的根目录下的 WEB-INF/classes 目录,所有的资源文件都会被部署到这个路径中。

2. Web 应用中的资源访问方式

在 Web 应用中,使用 ServletContext 来访问 WEB-INF 下的资源文件。通过 getResourceAsStream() 方法,可以从类路径中读取资源文件,而不需要关心文件的绝对路径。

3. 加载 db.properties 配置文件的步骤

假设 db.properties 文件存放在 WEB-INF/classes/com/yourapp/config/db.properties 中,您可以通过如下步骤从请求中加载该文件。

代码实现

import javax.servlet.ServletException;  
import javax.servlet.http.*;  
import java.io.IOException;  
import java.io.InputStream;  
import java.util.Properties;  public class ServletDemo extends HttpServlet {  @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  // 使用 getServletContext() 获取资源输入流,路径为 /WEB-INF/classes/com/yourapp/config/db.properties  InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/yourapp/config/db.properties");  // 如果文件没有找到,返回错误消息  if (is == null) {  resp.getWriter().print("db.properties not found!");  return;  }  // 创建 Properties 对象,用于读取配置文件内容  Properties prop = new Properties();  prop.load(is);  // 获取属性值(例如数据库连接信息)  String dbUrl = prop.getProperty("db.url");  String dbUser = prop.getProperty("db.username");  String dbPassword = prop.getProperty("db.password");  // 将读取到的配置信息输出到浏览器  resp.getWriter().print("Database URL: " + dbUrl + "<br>");  resp.getWriter().print("Username: " + dbUser + "<br>");  resp.getWriter().print("Password: " + dbPassword + "<br>");  }  @Override  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  // 处理 POST 请求,调用 doGet 进行处理  doGet(req, resp);  }  
}  

解释

  1. 加载配置文件

    • getServletContext().getResourceAsStream("/WEB-INF/classes/com/yourapp/config/db.properties")
      • 这行代码通过 ServletContext 来加载 db.properties 配置文件。路径 /WEB-INF/classes/com/yourapp/config/db.properties 表示相对于 Web 应用的根路径。
      • getResourceAsStream() 会返回一个输入流 InputStream,您可以用它来读取文件内容。
  2. 读取文件内容

    • 使用 Properties 类来读取 .properties 文件的键值对。prop.load(is) 会从 InputStream 加载配置项。
    • 通过 prop.getProperty("db.url")prop.getProperty("db.username")prop.getProperty("db.password") 获取数据库连接的相关配置。
  3. 返回响应

    • 将数据库的配置信息输出到网页上,使用 resp.getWriter().print() 将信息打印到浏览器。

4. 重要概念和注意事项

  • getResourceAsStream 方法
    getResourceAsStream()ServletContext 提供的一个方法,用于从 Web 应用的类路径中加载资源文件。这个方法会返回一个 InputStream,可以用来读取文件内容。在这里,它加载的是 WEB-INF/classes/com/kuang/servlet/aa.properties 文件。

  • 路径问题
    路径 /WEB-INF/classes/com/kuang/servlet/aa.properties 表示文件位于 Web 应用根目录下的 WEB-INF/classes/com/kuang/servlet 目录中。Web 应用启动时,WEB-INF/classes 目录下的所有资源会被加入到类路径中,从而能够通过 getServletContext().getResourceAsStream 来访问。

  • Properties
    Properties 类是 Java 提供的一种用于处理属性文件(如 .properties 文件)的类。属性文件是以键值对形式存储配置的文本文件,可以使用 getProperty(key) 方法根据键来获取值。

5. 路径配置

正确的路径设置

  • db.properties 文件放置在 WEB-INF/classes/com/yourapp/config/ 目录下。
  • 使用 getServletContext().getResourceAsStream("/WEB-INF/classes/com/yourapp/config/db.properties") 读取文件时,路径 /WEB-INF/classes/ 是从 Web 应用根目录开始的。

如果您的文件路径不在 WEB-INF/classes/ 目录下,而是放在 WEB-INF/ 或其他路径中,您需要调整路径以正确访问。

6. 补充说明

  • 路径中的前缀 /
    getResourceAsStream() 中,路径前面的 / 表示从 Web 应用的根目录开始查找。/WEB-INF 是 Web 应用的保密目录,通常对外部不可直接访问,但是可以通过 ServletContext 访问。

  • ServletContext 和路径问题
    getResourceAsStream() 方法会从 Web 应用的类路径中查找文件。因此,无论部署在哪里,只要文件位于正确的位置,ServletContext 都能加载到它。

7. 总结

  • 使用 ServletContextgetResourceAsStream() 方法可以加载放置在 WEB-INF/classes 中的资源文件。
  • 通过这种方式,可以避免硬编码绝对路径,确保在开发和生产环境中都能够正确加载资源。
  • 配置文件(如 db.properties)通常会存放在 WEB-INF/classes 中,而通过 Properties 类可以轻松读取和管理这些文件的内容。

会涉及到 properties 类

在 resources 文件夹下创建一个以 .properties 为后缀的文件,并存储以下数据

uername=root
password=123456

在这里插入图片描述

之前的思路如何读取到 db.properties 这个文件下的内容? 通过 properties 类通过绝对地址去 load 出来,但是现在是 web 应用,无法保证绝对地址,是在服务器上获取内容!需要观察它在服务器的什么位置。

下面先通过 maven 的 clean 清理干净(target 文件就会被删除掉),清理完成后,重新启动 tomcat,会产生一个 target 文件,target/servlet-02/WEB-INF/classes/db.properties 下

在这里插入图片描述

先提到一个 classpath,类路径的概念,我们源代码 java 和资源文件 resources 的内容最终都会以相同的路径打包到类路径也就是 classes 文件夹下的
在这里插入图片描述

如果我们在源代码 java 文件而不是资源文件 resources 下创建一个如 test.properties 文件,观察它是否会被打包到 target 目录下
在这里插入图片描述

重启 tomcat,发现并没有生成 test.properties
在这里插入图片描述

实际上在 maven 中已经讲过,需要在 pom.xml 中进行配置,如下,从而打包 java 源码下的 properties 文件

<!--在build中配置resources,来防止我们资源导出失败的问题-->
<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>
  • 在 java 目录中新建 properties
  • 在 resource 目录下新建 properties

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

下面我们新建一个 ServletDemo05 类来从服务器上读取我们想要的文件内容

public class ServletDemo05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties"); // 获取文件路径Properties prop = new Properties();prop.load(is);String user = prop.getProperty("username");String pwd = prop.getProperty("password");resp.getWriter().print(user+":"+pwd); // 输入到网页上}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

并注册 servlet ,命名为 sd5

    <servlet><servlet-name>sd5</servlet-name><servlet-class>com.uestc.servlet.ServletDemo04</servlet-class></servlet><servlet-mapping><servlet-name>sd5</servlet-name><url-pattern>/sd5</url-pattern></servlet-mapping>

重启 tomcat,请求 sd5:localhost:8090/s2/sd5,如果发生 500 错误,检查文件路径是否正确,正确尝试将 target 文件删除再使用
在这里插入图片描述

成功获取
在这里插入图片描述

6.6 HttpServletResponse

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

  • 如果想要获取客户端请求过来的参数:找 HttpServletRequest
  • 如果要给客户端响应一些信息:找 HttpServletResponse

6.6.1 简单分类

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

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

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

    void setCharacterEncoding(String var1);void setContentLength(int var1);void setContentLengthLong(long var1);void setContentType(String var1);void setDateHeader(String var1, long var2);void addDateHeader(String var1, long var2);void setHeader(String var1, String var2);void addHeader(String var1, String var2);void setIntHeader(String var1, int var2);void addIntHeader(String var1, int var2);

响应的状态码

int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

HttpServletResponse 是 Java Servlet API 中的一个接口,代表了服务器端对客户端的响应。它负责向客户端发送响应数据和设置响应头信息。你提到的几种方法可以分为两大类:一类是处理响应数据的发送,另一类是处理响应头的设置。

1. 向浏览器发送数据的方法

这类方法主要用于向客户端发送响应体内容。

ServletOutputStream getOutputStream() throws IOException;
  • 这个方法返回一个 ServletOutputStream 对象,允许你以二进制流的形式写入响应数据。

  • 常用于发送图片、视频、文件等二进制数据。

  • 例如:

    ServletOutputStream out = response.getOutputStream();
    out.write(byteArray); // 直接写入字节数组
    out.flush(); // 确保所有数据都写入
    
PrintWriter getWriter() throws IOException;
  • 这个方法返回一个 PrintWriter 对象,用于以字符流的方式写入响应数据。

  • 通常用于发送文本数据,例如 HTML、JSON 或 XML 格式的响应。

  • 你可以使用 PrintWriterprintln()write() 方法向客户端发送字符数据。

  • 例如:

    PrintWriter writer = response.getWriter();
    writer.println("<html><body><h1>Hello World</h1></body></html>");
    writer.flush(); // 确保数据被发送到客户端
    

2. 向浏览器发送响应头的方法

这些方法用于设置响应的头信息,告知浏览器如何处理响应体的数据。

void setCharacterEncoding(String var1);
  • 设置响应的字符编码。常用的字符编码包括 UTF-8ISO-8859-1 等。

  • 该方法需要在响应数据之前调用,否则可能会导致乱码。

  • 例如:

    response.setCharacterEncoding("UTF-8");
    
void setContentLength(int var1);
  • 设置响应体的长度,以字节为单位。

  • 对于文本响应,可以通过 response.getWriter() 写入数据并自动计算长度,或者手动设置长度。

  • 例如:

    response.setContentLength(1024); // 设置响应体的字节长度为 1024 字节
    
void setContentLengthLong(long var1);
  • 这是 setContentLength 的长整型版本,适用于内容长度大于 2GB 的情况。

  • 例如:

    response.setContentLengthLong(5000000000L); // 设置一个非常大的响应体长度
    
void setContentType(String var1);
  • 设置响应内容的类型,例如 text/htmlapplication/jsonimage/png 等。

  • 通过设置此头信息,客户端会根据类型来解析响应数据。

  • 例如:

    response.setContentType("text/html; charset=UTF-8");
    
void setDateHeader(String var1, long var2);
  • 设置响应头中的日期信息,例如 ExpiresLast-Modified 等。

  • var1 是日期头的名称,var2 是日期的毫秒表示。

  • 例如:

    long currentTime = System.currentTimeMillis();
    response.setDateHeader("Last-Modified", currentTime);
    
void addDateHeader(String var1, long var2);
  • setDateHeader 类似,但此方法会在已有的同名响应头后追加新的日期值,而不是替换。

  • 例如:

    response.addDateHeader("Expires", System.currentTimeMillis() + 3600 * 1000); // 设置一个过期时间
    
void setHeader(String var1, String var2);
  • 设置一个自定义的响应头,var1 为头的名称,var2 为对应的值。

  • 例如:

    response.setHeader("Cache-Control", "no-cache");
    
void addHeader(String var1, String var2);
  • setHeader 类似,但此方法允许向同名响应头追加多个值。

  • 例如:

    response.addHeader("Set-Cookie", "username=JohnDoe");
    response.addHeader("Set-Cookie", "sessionId=abc123");
    
void setIntHeader(String var1, int var2);
  • 设置一个整数类型的响应头。

  • 例如:

    response.setIntHeader("Retry-After", 3600); // 设置重试的时间间隔为 3600 秒
    
void addIntHeader(String var1, int var2);
  • setIntHeader 类似,但此方法允许向同名响应头追加多个整数值。

  • 例如:

    response.addIntHeader("Warning", 298); // 添加一个警告头
    

总结

  • 向浏览器发送数据的方法(如 getOutputStream()getWriter())用于传输响应体的内容。
  • 设置响应头的方法(如 setCharacterEncoding()setContentType() 等)用于配置响应的元数据,例如字符集、内容类型和缓存策略等。

6.6.2 下载文件

给浏览器输出消息

下载文件

  1. 要获取下载文件的路径
  2. 下载的文件名是什么?
  3. 设置浏览器使其支持下载的内容
  4. 获取下载文件的输入流
  5. 创建缓冲区
  6. 获取 OutputStream 对象
  7. 将 FileOutputStream 写入到 buffer 缓冲区
  8. 使用 OutputStream 将缓冲区中的数据输出到客户端

新建一个子工程为 response
在这里插入图片描述

添加 java、resources 文件,以及修改 web.xml
在这里插入图片描述

在 resources 文件下,随意加入一个图片,命名为 1.png
在这里插入图片描述

创建类 FileServlet

public class FileServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 要获取下载文件的路径String realPath = "/1.png";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[] 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();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册Servlet

<servlet><servlet-name>filedown</servlet-name><servlet-class>com.uestc.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>filedown</servlet-name><url-pattern>/down</url-pattern>
</servlet-mapping>

修改 tomcat 配置,选择 response:war
在这里插入图片描述

重启 tomcat,请求 down,发生了如下错误:
在这里插入图片描述

查看后台输出的路径结果,发现路径是 D 盘下的,肯定不对
在这里插入图片描述

获取 1.png 的绝对路径,我的为:D:\08Code\Servlet\response\target\classes\1.png
在这里插入图片描述

因此更新代码,更改地址
在这里插入图片描述

然后 clean maven 项目后重启 tomcat,再请求 down ,成功!
在这里插入图片描述

有几点可以优化和注意的地方:

1. 文件路径问题

realPath 目前是硬编码的路径("/1.png"),这意味着文件是从根目录中获取的。如果文件存在于项目的某个特定目录中,建议使用 ServletContext.getRealPath() 获取文件的绝对路径。例如:

String realPath = getServletContext().getRealPath("/WEB-INF/files/1.png");  

这会返回实际存储文件的路径,"/WEB-INF/files/1.png" 是相对路径。

2. 文件路径分隔符

你的代码使用了 realPath.substring(realPath.lastIndexOf("\\") + 1) 来提取文件名,这在 Windows 环境下是有效的。但为了跨平台,建议使用 File.separator 来保证路径分隔符正确:

String fileName = realPath.substring(realPath.lastIndexOf(File.separator) + 1);  

3. 下载文件时的 Content-Type

在返回文件之前,最好设置文件的 Content-Type 头,告知浏览器如何处理文件。对于图片文件,可以使用如下设置:

resp.setContentType("image/png");  

如果文件类型是动态的,可以根据文件后缀设置不同的 MIME 类型。可以用一个工具类来根据文件扩展名返回合适的 MIME 类型。

4. 错误处理

当前代码中没有异常处理逻辑,建议添加文件不存在或读取错误时的处理逻辑。例如:

File file = new File(realPath);  
if (!file.exists()) {  resp.setStatus(HttpServletResponse.SC_NOT_FOUND); // 404错误  return;  
}  

5. 优化流的关闭

虽然 Java 7 引入了 try-with-resources 语法来自动关闭流,你可以使用它来避免手动关闭流。这样可以确保即使出现异常也能正确关闭流:

try (FileInputStream in = new FileInputStream(realPath);  ServletOutputStream out = resp.getOutputStream()) {  int len = 0;  byte[] buffer = new byte[1024];  while ((len = in.read(buffer)) > 0) {  out.write(buffer, 0, len);  }  
} catch (IOException e) {  e.printStackTrace();  resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500错误  
}  

6. 文件大小

如果文件非常大,你可能希望设置 Content-Length 头,这样浏览器可以知道文件的大小。例如:

File file = new File(realPath);  
resp.setContentLengthLong(file.length());  

7. doPost 方法

你重写了 doPost 方法,但是没有做任何事情。通常如果不需要处理 POST 请求,可以不实现该方法,或者抛出一个异常来阻止 POST 请求。

@Override  
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "POST method is not supported.");  
}  

综合优化后的代码示例:

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.*;  
import java.net.URLEncoder;  
import java.nio.file.Files;  public class FileServlet extends HttpServlet {  @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  // 获取文件的实际路径  String realPath = getServletContext().getRealPath("/WEB-INF/files/1.png");  File file = new File(realPath);  if (!file.exists()) {  resp.setStatus(HttpServletResponse.SC_NOT_FOUND);  return;  }  // 设置文件名  String fileName = realPath.substring(realPath.lastIndexOf(File.separator) + 1);  // 设置 Content-Disposition 让浏览器进行下载  resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));  // 设置Content-Type(根据文件类型进行设置)  String mimeType = getServletContext().getMimeType(realPath);  resp.setContentType(mimeType != null ? mimeType : "application/octet-stream");  // 设置Content-Length  resp.setContentLengthLong(file.length());  try (FileInputStream in = new FileInputStream(realPath);  ServletOutputStream out = resp.getOutputStream()) {  // 创建缓冲区  byte[] buffer = new byte[1024];  int len;  while ((len = in.read(buffer)) > 0) {  out.write(buffer, 0, len);  }  } catch (IOException e) {  e.printStackTrace();  resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500错误  }  }  @Override  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "POST method is not supported.");  }  
}  

6.6.3 验证码功能实现

验证怎么来的?

  • 前端实现
  • 后端实现,需要用到 java 的图片类,生成一个图片,没有图片就没有验证码,我们要把这个图片响应到前端

在上述 response 文件的 java 源码下,创建一个 ImageServlet 类

public class ImageServlet extends HttpServlet {@Overrideprotected 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/jpeg");//网站存在缓存,不让浏览器缓存resp.setDateHeader("expires",-1);resp.setHeader("Cache-Control","no-cache");resp.setHeader("Pragma","no-cache");//把图片写给浏览器ImageIO.write(image,"jpg", resp.getOutputStream());}//生成随机数private String makeNum(){Random random = new Random();String num = random.nextInt(9999999) + "";StringBuffer sb = new StringBuffer();for (int i = 0; i < 7-num.length() ; i++) {sb.append("0");}num = sb.toString() + num;return num;}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

注册 Servelt

    <servlet><servlet-name>ImageServlet</servlet-name><servlet-class>com.uestc.servlet.ImageServlet</servlet-class></servlet><servlet-mapping><servlet-name>ImageServlet</servlet-name><url-pattern>/ImageServlet</url-pattern></servlet-mapping>

然后走 ImageServlet 这个请求,成功产生,并且每 3s 产生一次
在这里插入图片描述

6.6.4 实现重定向

在这里插入图片描述

Web 资源 B 收到客户端 A 请求后,通知 A 访问另一个 Web 资源 C ,这个过程叫做重定向

常见场景:

  • 用户登录,登录成功就会访问另一个页面

重定向是方法 sendRedirect 来实现

void sendRedirect(String var1) throws IOException;

创建类 RedirectServlet,使其重定位到上面我们注册的 ImageServlet 里

public class RedirectServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/*resp.setHeader("Location","/response/ImageServlet");resp.setStatus(302);*/resp.sendRedirect("/reseponse/ImageServlet");//重定向}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册 Servlet

<servlet>
<servlet-name>RedirectServlet</servlet-name><servlet-class>com.uestc.servlet.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>RedirectServlet</servlet-name><url-pattern>/red</url-pattern>
</servlet-mapping>

启动tomcat,请求 red,成功重定向到之前的验证码 ImageServlet 中,注意请求时加上我们设置的入口 reseponse,不然进入的是 localhost:8090/ImageServlet,少了 reseponse
在这里插入图片描述

面试题:重定向与转发的区别?

相同点:

  • 页面都会实现跳转

不同点:

  • 请求转发的时候,URL 不会发生变化
  • 重定向时候,URL 地址栏会发生变化;

6.6.4 简单实现登录重定向

index.jsp (注意 maven 下导入 JSP 的包)

<html><body><h2>Hel1o World!</h2><%--这里提交的路径,需要寻找到项目的路径--%><%--${pageContext. request, contextPath}代表当前的项目--%><form action="${pageContext. request.contextPath}/login" method="get">用户名: <input type="text" name="username"> <br>密码: <input type="password" name="password"> <br><input type="submit"></form></body>
</html>

关键部分解释:

${pageContext.request.contextPath}

这是 JSP 表达式语言(Expression Language, EL)中的一个表达式,用于动态获取当前项目的上下文路径。具体含义如下:

  • pageContext

    • 是一个隐式对象,提供对页面范围内相关信息的访问。
    • 它封装了许多有用的属性,比如 requestresponse 等。
  • request

    • 是另一个隐式对象,表示当前的 HTTP 请求。
  • contextPath

    • request 对象的一个属性,返回当前 Web 应用程序的上下文路径。
    • 通常对应 Web 应用部署时的根路径,比如 /myApp

创建一个类 RequestTest.java

public class RequestTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//处理请求System.out.println("进入了这个请求");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册 Servlet

<servlet><servlet-name>requset</servlet-name><servlet-class>com.uestc.servlet.RequestTest</servlet-class>
</servlet>
<servlet-mapping><servlet-name>requset</servlet-name><url-pattern>/login</url-pattern>
</servlet-mapping>

重启 Tomcat,请求 login,乱码是浏览器的问题,不是我们代码的问题,成功
在这里插入图片描述
但是输入账号,密码后,点击提交,反应到了浏览器的地址中
在这里插入图片描述

下面我们来处理上述的请求,即提交后跳转页面。

新建一个 success.jsp,内容只有一个 success 输出

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1> success </h1></body>
</html>

然后获取 RequestTest 获取账号密码,打印到后台,并跳转到 success.jsp

public class RequestTest extends HttpServlet {@Overrideprotected 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("/response/success.jsp");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

现在重启 Tomcat,后台获得了这个账号密码,并打印输出,并且跳转到了 success.jsp
在这里插入图片描述
在这里插入图片描述

6.7、HttpServletRequest

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

在这里插入图片描述

获取前端传递的参数,请求转发,下面是四个获取参数的方法,重点掌握两个
在这里插入图片描述

下面新建一个子工程,request
在这里插入图片描述

添加 java 文件夹,resources 文件夹,进行标记,并更新 web.xml
在这里插入图片描述

并删除 index.jsp,再新建一个 index.jsp,会多一个头
在这里插入图片描述

创建类 LoginServlet,前面使用的都是 get 方法,下面使用 post 方法
在这里插入图片描述

在 index.jsp 中写入一个简单的前端,注意下面的 <form action="<%=request.getContextPath()%>/login" method="get"> 中的 method=“get” 在提交登录后会去调用 get 方法

<%--Created by IntelliJ IDEA.User: 15592Date: 2024/7/25Time: 17:46To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title>
</head>
<body><h1> 登录成功 </h1>
<div style="text-align: center"><form action="<%=request.getContextPath()%>/login" method="get">用户名: <input type="text" name="username"> </input> <br>密码: <input type="password" name="password"> </input> <br>爱好:<input type="checkbox" name="hobbys" value="女孩"> 女孩<input type="checkbox" name="hobbys" value="代码"> 代码<input type="checkbox" name="hobbys" value="唱歌"> 唱歌<input type="checkbox" name="hobbys" value="电影"> 电影<br><input type="submit" value="登录"></form></div></body>
</html>

把前面的 success.jsp 拿过来

<%--Created by IntelliJ IDEA.User: 15592Date: 2024/7/25Time: 17:33To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<h1> success </h1></body>
</html>

在这里插入图片描述

LoginServlet 类中获取 index.jsp 的内容(注意与前面的 method=“get”匹配,执行下面 doGet 方法)

public class LoginServlet extends HttpServlet {@Overrideprotected 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("=============================");//后台接收中文乱码问题System.out.println(username);System.out.println(password);System.out.println(Arrays.toString(hobbys));System.out.println("=============================");System.out.println(req.getContextPath());//通过请求转发//这里的 / 代表当前的web应用req.getRequestDispatcher("/success.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}

注册 Servlet

<servlet><servlet-name>requset</servlet-name><servlet-class>com.uestc.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping><servlet-name>requset</servlet-name><url-pattern>/login</url-pattern>
</servlet-mapping>

由于新建了 request 子工程,需要重新配置 tomcat
在这里插入图片描述

启动 tomcat
在这里插入图片描述

点击登录后成功跳转
在这里插入图片描述
在这里插入图片描述

References

B站—【狂神说Java】JavaWeb入门到实战—笔记

相关文章:

JavaWeb(一) | 基本概念(web服务器、Tomcat、HTTP、Maven)、Servlet 简介

1. 基本概念 1.1、前言 web开发&#xff1a; web&#xff0c;网页的意思&#xff0c;www.baidu.com静态 web html,css提供给所有人看的数据始终不会发生变化&#xff01; 动态 web 淘宝&#xff0c;几乎是所有的网站&#xff1b;提供给所有人看的数据始终会发生变化&#xf…...

五十一:HPACK如何减少HTTP头部的大小?

在现代的Web通信中&#xff0c;HTTP是最常用的协议。然而&#xff0c;随着网络应用程序的复杂化&#xff0c;HTTP头部的大小迅速增加&#xff0c;尤其是在HTTP/2中&#xff0c;由于其多路复用特性&#xff0c;多个请求和响应共享同一个连接&#xff0c;头部大小对性能的影响变得…...

windows11家庭版安装docker无法识别基于wsl2的Ubuntu

软件环境&#xff1a;windows11家庭版安装WSL2,Ubuntu22.04&#xff0c;docker4.34.2 问题描述&#xff1a;安装docker时&#xff0c;设置阶段无法识别Ubuntu22.04. 原因&#xff1a;windows11家庭版本默认没有Hyper-V 解决方案&#xff1a;将下述代码保存在新建记事本中&am…...

利用Spring Cloud Gateway Predicate优化微服务路由策略

利用Spring Cloud Gateway Predicate优化微服务路由策略 一、Predicate简介 Spring Cloud Gateway 是 Spring 生态系统中用于构建 API 网关的框架&#xff0c;它基于 Project Reactor 和 Netty 构建&#xff0c;旨在提供一种高效且灵活的方式来处理 HTTP 请求和响应。 Spring …...

谷歌浏览器的网络安全检测工具介绍

作为全球最受欢迎的浏览器之一&#xff0c;谷歌浏览器不仅提供了快速、便捷的浏览体验&#xff0c;还内置了一系列强大的网络安全检测工具&#xff0c;帮助用户识别潜在的网络威胁&#xff0c;保护个人隐私和数据安全。本文将详细介绍谷歌浏览器中的几项关键网络安全检测功能&a…...

Debian系统宝塔面板安装LiteSpeed Memcached(LSMCD)

参考链接 1. 官网指引&#xff1a; https://www.litespeedtech.com/support/wiki/doku.php/litespeed_wiki:lsmcd:installation 2. 安装OpenLiteSpeed官方LSMCD对象缓存替换Memcached详细图文教程 - 搬主题 实操记录&#xff1a; 首先LSMCD 默认的端口是11211&#xff0c;…...

termux下ubuntu换arm清华源

原官方源 deb http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiversedeb http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiversedeb http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted un…...

计算机网络——练习题

一. 单选题&#xff08;共27题&#xff0c;67.5分&#xff09; 1. (单选题)计算机网络的最突出的优点是____。 A. 运算速度快 B. 运算精度高 C. 存储容量大 D. 资源共享 我的答案: D:资源共享;正确答案: D:资源共享; 2.5分 答案解析&#xff1a; 2. (单选题)TCP/IP协…...

单机游戏《野狗子》游戏运行时提示dbghelp.dll缺失是什么原因?dbghelp.dll缺失要怎么解决?

《野狗子》游戏运行时提示dbghelp.dll缺失&#xff1a;原因与解决方案 在畅游《野狗子》这款引人入胜的游戏世界时&#xff0c;突然遭遇“dbghelp.dll缺失”的错误提示&#xff0c;无疑会给玩家的探险之旅蒙上一层阴影。作为一名深耕软件开发领域的从业者&#xff0c;我深知此…...

飞搭系列 | 条件动态控制,打造个性化数字体验

前言 汉得飞搭aPaaS低代码平台&#xff08;FEIDA&#xff0c;以下简称“飞搭”&#xff09;是基于低代码理念打造的融合 aPaaS 平台&#xff0c;助力企业快速搭建业务应用。作为 HZERO 生态的重要组成部分&#xff0c;致力于充分融合 HZERO 的各平台能力&#xff0c;提供企业用…...

ssr实现方案

目录 序言 一、流程 二、前端要做的事情 三、节点介绍 四、总结 序言 本文不是详细的实现过程&#xff0c;是让你最快最直接的理解ssr的真正实现方法&#xff0c;有前端经验的同学&#xff0c;能够很好的理解过程&#xff0c;细节根据具体项目实现 一、前端要做的事情 1.…...

STM32高级物联网通信之以太网通讯

目录 以太网通讯基础知识 什么是以太网 互联网和以太网的区别 1)概念与范围 (1)互联网 (2)以太网 2)技术特点 (1)互联网 (2)以太网 3)应用场景 (1)互联网 (2)以太网 以太网的层次 1)物理层 2)数据链路层 OSI 7层模型 TCPIP 4层模型 一些常见…...

以太网帧、IP数据报图解

注&#xff1a;本文为 “以太网帧、IP数据报”图解相关文章合辑。 未整理去重。 以太网帧、IP数据报的图解格式&#xff08;包含相关例题讲解&#xff09; jueyuanfengsheng2023-08-07 11:49 一、基础知识 UDP 段、IP 数据包&#xff0c;以太网帧图示 通信过程中&#xff…...

外包干了两年,技术退步明显...

先说一下自己的情况&#xff0c;普通本科&#xff0c;曾在外包干了2年多的功能测试&#xff0c;再加上大环境不好&#xff0c;那时我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;所以当时我感觉自己不能够在这样蹉跎下去了&#xff0c;长时间呆在一个舒适的环境…...

AI可信论坛亮点:合合信息分享视觉内容安全技术前沿

前言 在当今科技迅猛发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;技术正以前所未有的速度改变着我们的生活与工作方式。作为AI领域的重要盛会&#xff0c;CSIG青年科学家会议AI可信论坛汇聚了众多青年科学家与业界精英&#xff0c;共同探讨AI技术的最新进展、挑…...

vue中proxy代理配置(测试一)

接口地址&#xff1a;http://jsonplaceholder.typicode.com/posts 1、配置一&#xff08;代理没起作用&#xff09; &#xff08;1&#xff09;设置baseURL为http://jsonplaceholder.typicode.com &#xff08;2&#xff09;proxy为 ‘/api’&#xff1a;’ ’ &#xff08;3&a…...

通用人工智能的关键:统一语言描述万物

当今世界&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度推进着人类社会的进步。从最初的简单计算到如今能够执行复杂任务的智能系统&#xff0c;AI 的每一次飞跃都伴随着理解世界能力的显著提升。然而&#xff0c;要实现真正的通用人工智能——即能够像人类…...

使用QML实现播放器进度条效果

使用QML实现播放进度效果 QML Slider介绍 直接上DEMO如下&#xff1a; Slider {width: 300;height: 20;orientation: Qt.Vertical; //决定slider是横还是竖 默认是HorizontalstepSize: 0.1;value: 0.2;tickmarksEnabled: true; //显示刻度}效果图如下 那么我先改变滑块跟滚轮…...

TowardsDataScience 博客中文翻译 2018~2024(一百二十三)

TowardsDataScience 博客中文翻译 2018~2024&#xff08;一百二十三&#xff09; 引言 从 2018 年到 2024 年&#xff0c;数据科学的进展超越了许多技术领域的速度。Towards Data Science 博客依然是这个领域的关键平台&#xff0c;记录了从基础工具到前沿技术的多方面发展。…...

14: curl#6 - “Could not resolve host: mirrorlist.centos.org; 未知的错误“

出现这个错误是因为使用的 CentOS 7 仓库已经被归档&#xff0c;当前的镜像地址无法找到所需的文件。CentOS 7 的官方支持已经结束&#xff0c;部分仓库已被移至归档库。这导致了你的 yum 命令无法找到所需的元数据文件。CentOS 7 的官方仓库在 2024 年 6 月 30 日之后已经停止…...

将 ASP.NET Core 应用程序的日志保存到 D 盘的文件中 (如 Serilog)

将 ASP.NET Core 应用程序的日志保存到 D 盘的文件中&#xff0c;可以使用第三方日志库&#xff08;如 Serilog&#xff09;来实现。Serilog 是一个流行的日志库&#xff0c;支持将日志输出到文件、控制台、数据库等多种目标。 以下是实现步骤&#xff1a; 1. 安装 Serilog 相…...

深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223

深入探讨 Go 中的高级表单验证与翻译&#xff1a;Gin 与 Validator 的实践之道 在现代后端开发中&#xff0c;表单验证是保证数据完整性和服务稳定性的核心环节。如何优雅、高效地实现表单验证&#xff0c;同时提供人性化的错误提示&#xff0c;是每位开发者的必修课。在本文中…...

相机主要调试参数

解析度测试 - 解释如何衡量摄像头捕捉细节的能力&#xff0c;确保图像清晰。锐度评估 - 教你如何判断图像边缘的清晰程度&#xff0c;以优化视觉效果。色散与色彩还原 - 分析色彩准确性&#xff0c;确保所见即所得的色彩一致性。白平衡校正 - 确保在各种光源下拍摄的照片颜色自…...

JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码

JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码&#xff1a;引领智慧养老新时代 在当今老龄化社会日益严重的背景下&#xff0c;智慧养老已成为解决养老问题的重要途径。我们推出的JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码&#xff0c;正是基于这一需求而研发…...

一个简单封装的的nodejs缓存对象

我们在日常编码中&#xff0c;经常会用到缓存&#xff0c;而一个有效的缓存管理&#xff0c;也是大家必不可少的工具。而nodejs没有内置专用的缓存对象&#xff0c;并且由于js的作用域链的原因&#xff0c;很多变量使用起来容易出错&#xff0c;如果用一个通用的缓存管理起来&a…...

【ELK】filebeat采集数据输出到kafka指定topic

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 背景filebeat主体配置filebeat.inputs部分filebeat.output部分 filebeat完整配置 背景 今天收到需求&#xff0c;生产环境中通需要优化filebeat的输出&#xff0c;…...

Qt 6 QML Settings location 不创建指定路径文件

在 Qt QML 项目中可以使用Qt QSettings QML 版 Settings 方便数据持久化&#xff0c;具体使用可以参考Qt 文档&#xff0c;这里主要简单记录一下从Qt 5 升级到 Qt 6 后&#xff0c;没有创建指定的文件。在Qt 5中是使用 fileName 属性来指定文件路径&#xff0c;如下&#xff0…...

LabVIEW如何学习FPGA开发

FPGA&#xff08;现场可编程门阵列&#xff09;开发因其高性能、低延迟的特点&#xff0c;在实时控制和高速数据处理领域具有重要地位。LabVIEW FPGA模块为开发者提供了一个图形化编程平台&#xff0c;降低了FPGA开发的门槛。本篇文章将详细介绍LabVIEW FPGA开发的学习路径&…...

idea设置控制台日志输出自动换行

文章目录 1. 原因2. 方法一&#xff1a;3. 方法二&#xff1a; 1. 原因 你是否碰到ideal控制台输入日志是一行的效果&#xff0c;那是因为带了soft wrap。 2. 方法一&#xff1a; 最新版的IDEA设置控制台自动换行位置如下&#xff1a; Setting->Editor->General->C…...

帧缓存的分配

帧缓存实际上就是一块内存。在 Android 系统中分配与回收帧缓存&#xff0c;使用的是一个叫 ION 的内核模块&#xff0c;App 使用 ioctl 系统调用后&#xff0c;会在内核内存中分配一块符合要求的内存&#xff0c;用户态会拿到一个 fd&#xff08;有的地方也称之为 handle&…...

Spitfire浏览器:为CodiggerDesktop打造的轻量级浏览新选择

近期&#xff0c;一款名为Spitfire的专业级轻量级浏览器凭借其卓越的性能和便捷的使用体验&#xff0c;吸引了科技界的广泛关注。这款浏览器是专为CodiggerDesktop用户量身打造的&#xff0c;旨在提供高速、流畅的浏览服务&#xff0c;满足开发者和设计者的多元化需求。 Spitfi…...

etcd+京东hotkey探测使用

qhotKey链接 京东hotkey把热点数据默认缓存在了本地缓存caffeine中&#xff0c;也可以存到redis中&#xff0c;但是京东hotkey的SDK没有redis的实现方法&#xff0c;因此需要自己实现。 官方目录结构下&#xff1a;分别是client客户端&#xff08;要打包引入到自己的项目&…...

从源码分析swift GCD_DispatchGroup

前言&#xff1a; 最近在写需求的时候用到了DispatchGroup&#xff0c;一直没有深入去学习&#xff0c;既然遇到了那么就总结下吧。。。。 基本介绍&#xff1a; 任务组&#xff08;DispatchGroup&#xff09; DispatchGroup 可以将多个任务组合在一起并且监听它们的完成状态。…...

【最后203篇系列】002 - 两个小坑(容器时间错误和kafka模块报错

这里两个小坑填了&#xff0c;希望有用。 1 Multiple conflicting time zone configurations found:\n/etc/timezone: Asia/Shanghai\n/etc/localtime is a symlink to: Etc/UTC\nFix the configuration, or set the time zone in a TZ environment variable. 我碰到这个错误…...

StarRocks 生产部署一套集群,存储空间如何规划?

背景&#xff1a;StarRocks 3.2&#xff0c;存储一体 使用场景&#xff1a;多分析、小查询多单但不高、数据量几百T FE 存储 由于 FE 节点仅在其存储中维护 StarRocks 的元数据&#xff0c;因此在大多数场景下&#xff0c;每个 FE 节点只需要 100 GB 的 HDD 存储&#xff0c…...

WebGL 项目外包开发流程

WebGL 项目外包开发流程与一般的软件项目外包流程类似&#xff0c;但由于 WebGL 的特殊性&#xff0c;在某些环节需要特别注意。以下是一个详细的 WebGL 项目外包开发流程。 1. 需求分析与定义 (明确目标是关键)&#xff1a; 客户沟通与需求收集&#xff1a; 与客户进行深入沟…...

SQLMAP

Taeget 实践内容&#xff1a;练习使用 SQLMap 进行自动化 SQL 注入。 涉及知识点&#xff1a;理解 SQL 注入、SQLMap 工具使用、自动化攻击、Web 应用安全。 Trial 说明&#xff1a;Sqlmap是一个开源的渗透测试工具&#xff0c;可以自动检测和利用SQL注入漏洞&#xff0c;并…...

windwos defender实现白名单效果(除了指定应用或端口其它一律禁止)禁止服务器上网

一、应用场景说明 当我们的一台windows服务器中毒&#xff0c;变成别人肉鸡&#xff0c;不断向外请示非法网站或攻击其它服务器。 要彻底清除相关木马或病毒往往需要的时间比较长&#xff0c;比较有效的方法是禁止服务器主动向外发包除了网站端口和远程程序除外。 其实这就是一…...

模型库网站

目录 1 网站 1 网站 https://hf-mirror.com/ https://swanhub.co/models https://modelscope.cn/models https://www.suanjiayun.com/mirror?sourcebaidutg&bd_vid11787806978655223592...

5、栈应用-表达式求值

本章内容使用上述栈结构函数&#xff0c;来完成表达式求值操作。 表达式例如&#xff1a;3*(7-2) 或者 (0-12)*((5-3)*32)/(22) 。 1、实现思路 a、建立OPTR&#xff08;运算符&#xff09;和OPND&#xff08;数字&#xff09;两个栈&#xff0c;后输入字符串以结束 b、自左向…...

传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统&#xff0c;其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术&#xff0c;自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述&#xff1a; 1. 导入必要的库 系统首先导入…...

重温设计模式--原型模式

文章目录 原型模式定义原型模式UML图优点缺点使用场景C 代码示例深拷贝、浅拷贝 原型模式定义 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象&#xff1b; 核心中的核心就是 克隆clone ,后面讲 原型模式是一种创建型设计模式&#xff0c;它的主要…...

STM32在bootloader跳转到application时设置MSP

1. 简介 在做bootloader 跳转到application时&#xff0c;经常会看到设置MSP的操作__set_MSP(*(__IO uint32_t*) APPLICATION_ENTRY);。 1.1 MSP的作用 在STM32微控制器中&#xff0c;MSP&#xff08;Main Stack Pointer&#xff0c;主堆栈指针&#xff09;是一个非常重要的…...

SDMTSP:黑翅鸢算法(Black-winged kite algorithm,BKA)求解单仓库多旅行商问题,可以更改数据集和起点(MATLAB代码)

一、黑翅鸢算法BKA 黑翅鸢算法&#xff08;Black-winged kite algorithm&#xff0c;BKA&#xff09;由Wang Jun等人于2024年提出&#xff0c;该算法受黑翅鸢的迁徙和掠食行为启发而得。BKA集成了柯西突变策略和领导者策略&#xff0c;增强了算法的全局搜索能力&#xff0c;提…...

我们来学mysql -- 区分大写

区分大写 题记大小写不敏感文件文件系统大小写敏感文件文件系统mysql认不认大小写lower_case_table_names 题记 混沌初开&#xff0c;万物共享盛世&#xff0c;自由自在好不快活然&#xff0c;人性难掩&#xff0c;初露獠牙&#xff0c;喊杀一片&#xff0c;好不热闹族群&…...

显示器“刷新率”的通俗理解

显示器刷新率的定义 显示器的刷新率&#xff08;Refresh Rate&#xff09;是指屏幕每秒刷新图像的次数&#xff0c;以赫兹&#xff08;Hz&#xff09;为单位。比如&#xff0c;刷新率为 60Hz 表示屏幕每秒能够刷新 60 次图像。 刷新率是显示器硬件特性的一部分&#xff0c;定…...

25计软新增考研院校!或可捡漏上岸!

C哥专业提供——计软考研院校选择分析专业课备考指南规划 新增的计算机与软件工程考研院校为考研同学带来了多方面的机遇&#xff0c;这些机遇不仅体现在过国家线后可能面临的更低竞争压力&#xff0c;还包括更多元化的教育选择和更广阔的就业前景&#xff1a; 一、降低竞争压…...

[入门JAVA数据结构 JAVADS] 哈希表的初步介绍和代码实现

目录 前言 哈希表的概念和诞生的原因 哈希冲突 简单实现哈希表 基本属性 插入 获取key的val 计算负载因子 扩容(难点) 完整代码(方便大家复制自己去调试) 数据是int的 使用泛型实现的 结尾 前言 笔者鸽了接近两个月后决定"勤政"了.尽力把学过的知识写下…...

谷歌外链好不好,关键看“搭配”!

做SEO的人都知道外链很重要&#xff0c;但有一个误区是只追求“高质量外链”&#xff0c;却忽略了外链结构的合理性。其实&#xff0c;外链就像饮食&#xff0c;光吃好东西不够&#xff0c;营养搭配得当才能健康发展。 谷歌对外链的要求&#xff0c;不仅是看它是不是dofollow、…...

【AI驱动的数据结构:包装类的艺术与科学】

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 包装类装箱和拆箱阿里巴巴面试题 包装类 在Java中基本数据类型不是继承来自Object&#xff0c;为了…...