JavaWeb
课程安排
1.HTTP、Tomcat、Servlet
2.Request(请求)、Response(响应)
3.会话技术(Cookie、Session)
4.Filter(过滤器)、Listener(监听器)
B/S 架构:Browser/Server,浏览器/服务器 架构模式,它的特点是,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器,获取Web资源,服务器把Web资源发送给浏览器即可
好处:易于维护升级:服务器端升级后,客户端无需任何部署就可以使用到新的版本
静态资源:HTML、CSS、JavaScript、图片等。负责页面展现
动态资源:Servlet、JSP 等。负责逻辑处理
数据库:负责存储数据
HTTP协议:定义通信规则
Web服务器:负责解析 HTTP 协议,解析请求数据,并发送响应数据
一、maven
0.在csdn中 网址:
超级详细的 Maven 教程(基础+高级)_maven教程_汪了个王的博客-CSDN博客
1.什么是maven
Maven是apache旗下的一个开源项目,是一款用于管理和构建java项目的工具。
2.maven的作用
1.依赖管理
方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题
2.统一项目结构
提供标准、统一的项目结构
3.项目构建
标准跨平台(Linux、Windows、MacOS)的自动化项目构建方式
3.maven的安装
首页:
Maven – Welcome to Apache Maven
下载页面:
或者你也可以选择之前的版本:
然后里面选择自己对应的版本下载即可:
下载之后解压到非中文、没有空格的目录,如下:
4.指定本地仓库
本地仓库默认值:用户家目录/.m2/repository。由于本地仓库的默认位置是在用户的家目录下,而家目录往往是在 C 盘,也就是系统盘。将来 Maven 仓库中 jar 包越来越多,仓库体积越来越大,可能会拖慢 C 盘运行速度,影响系统性能。所以建议将 Maven 的本地仓库放在其他盘符下。配置方式如下:
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>D:\software\maven-repository</localRepository>
本地仓库这个目录,我们手动创建一个空的目录即可。
记住:一定要把 localRepository 标签从注释中拿出来。
注意:本地仓库本身也需要使用一个非中文、没有空格的目录。
5.配置阿里云提供的镜像仓库
1.将原有的例子配置注释掉
<!-- <mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror> -->
2.加入自己的配置
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
6.配置环境变量
Maven 是一个用 Java 语言开发的程序,它必须基于 JDK 来运行,需要通过 JAVA_HOME 来找到 JDK 的安装位置。
可以使用下面的命令验证:
C:\Users\Administrator>echo %JAVA_HOME%
D:\software\Java
C:\Users\Administrator>java -version
java version "1.8.0_141"
Java(TM) SE Runtime Environment (build 1.8.0_141-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.141-b15, mixed mode)
然后新建环境变量:
配置环境变量的规律:
XXX_HOME 通常指向的是 bin 目录的上一级
PATH 指向的是 bin 目录
在配置 PATH:
通过 mvn -v
验证:
C:\Users\Administrator>mvn -v
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00)
Maven home: D:\software\apache-maven-3.3.9\bin\..
Java version: 1.8.0_333, vendor: Oracle Corporation
Java home: D:\software\jdk1.8\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 11", version: "10.0", arch: "amd64", family: "dos"
7.IDEA集成Maven
7.1配置Maven环境(当前工程)
7.2配置Maven环境(全局)
7.3创建Maven项目
7.4IDEA 导入 Maven 项目
方式一
方式二
二、HTTP
CSDN中的网址:
【计算机网络】HTTP 协议详解_http协议解析_吞吞吐吐大魔王的博客-CSDN博客
0.概念
概念:HyperText Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。
1.Http常见请求方式
1. get:从数据库查询数据,select
2. post:向服务器发送数据并保存数据,insert
3. put:修改数据,update
4. delete:删除数据
2.HTTP 协议特点
基于TCP协议:面向连接,安全
基于请求-响应模型的:一次请求对应一次响应
HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。
缺点:多次请求间不能共享数据。
优点:速度快
3.HTTP-请求数据格式
4.HTTP-响应数据格式
HTTP状态码汇总(常见)
在csdn中:HTTP状态码汇总(常见)_IT萌萌熊的博客-CSDN博客
状态码200:表示服务器响应成功
状态码301 :
状态码301和状态码302相似,不同的是状态码301往往代表的是永久性的重定向,值得注意的是,这种重定向跳转,从严格意义来讲不是服务器跳转,而是客户端跳转的。这个“跳”的动作是服务器是通过回传状态码301来下达给客户端的,让客户端完成跳转。
状态码302:
代表临时跳转
状态码304 :
服务器通过返回,可以告诉客户端请求资源成功,
状态码403:
状态码403代表请求的服务器资源权限不够,也就是说,没有权限去访问服务器的资源,或者请求的IP地址被封掉了。
状态码404:
状态码404代表服务器上没有该资源,或者说服务器找不到客户端请求的资源,是最常见的请求错误码。
状态码500:
状态码500代表程序错误,也就是说请求的网页程序本身报错了。在服务器端的网页程序出错。由于现在的浏览器都会对状态码500做一定的处理,所以在一般情况下会返回一个定制的错误页面。
三、Tomcat
0.在scdn中的网址 官网
学习Tomcat这一篇就够了_轻松的小希的博客-CSDN博客
官网:
1.简介
1.1概念:
Tomcat是Apache 软件基金会一个核心项目,是一个开源免费的轻量级Web服务器,支持Servlet/JSP少量JavaEE规范。
JavaEE:Java Enterprise Edition,Java企业版。指Java企业级开发的技术规范总和。包含13项技术规范:JDBC、JNDI、EJB、RMI、JSP、Servlet、XML、JMS、Java IDL、JTS、JTA、JavaMail、JAF
Tomcat 也被称为 Web容器、Servlet容器。Servlet 需要依赖于 Tomcat才能运行
2.作用
封装HTTP协议操作,简化开发
可以将web项目部署到服务器中,对外提供网上浏览服务
3.基本使用 配置端口 部署项目
4.IDEA中创建 Maven Web项目
4.1使用骨架
4.2不使用骨架
4.3 使用骨架和不使用骨架的好处
使用骨架的主要好处是:
- 快速启动:骨架提供了一个项目的基本结构和配置,可以节省创建项目的时间。
- 预定义的依赖项:骨架通常包含一些常用的依赖项,如JUnit、Log4j等,以便快速开始编写代码。
- 预定义的插件:骨架还可以包含一些常用的插件配置,如编译插件、打包插件等,以帮助构建和部署项目。
不使用骨架的主要好处是:
- 自定义配置:可以根据项目的需求自定义配置,而不受骨架的限制。
- 精简项目结构:不使用骨架可以避免一些不必要的配置和依赖项,使项目结构更加简洁。
5.在IDEA中使用 Tomcat – 集成本地 Tomcat
1.
2.
四、Servlet
0.Tomcat工作机制动画演示(点击动图可全屏观看)
https://img-blog.csdnimg.cn/2018120522281643.gif
1.快速入门
Servlet 快速入门
1. 创建 web项目,导入 Servlet依赖坐标
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
2. 创建:定义一个类,实现 Servlet接口,并重写接口中所有方法,并在 service方法中输入一句话
public class ServletDemo1 implements Servlet {
public void service(){}
}
3. 配置:在类上使用@WebServlet 注解,配置该 Servlet的访问路径
@WebServlet("/demo1")
public class ServletDemo1 implements Servlet {
}
4. 访问:启动 Tomcat,浏览器输入URL 访问该Servlet
http://localhost:8080/web-demo/demo1
2.执行流程
3.生命周期
对象的生命周期指一个对象从被创建到被销毁的整个过程
Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段:
加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理。
服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收
@WebServlet(urlPatterns = "/demo",loadOnStartup = 1)
负整数:第一次被访问时创建Servlet对象
0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高
方法介绍
4.体系结构
5.为什么要使用Servlet? ---处理动态资源的能力
因为web服务器(tomcat、Weblogic、iis、apache)没有处理动态资源请求的能力(即该请求需要计算),只能处理静态资源的请求(如果浏览器请求某个html页面,web服务器查看请求的html页面是否存在,存在则返回。)如果要让web服务器处理动态资源的请求,则需要使用CGI1程序、组件加容器的方式。
HttpServlet 原理
urlPattern配置
Servlet 要想被访问,必须配置其访问路径(urlPattern)
五、respon request
今日目标
掌握Request对象的概念与使用
掌握Response对象的概念与使用
能够完成用户登录注册案例的实现
能够完成SqlSessionFactory工具类的抽取
1、Request和Response的概述
==Request是请求对象,Response是响应对象。==这两个对象在我们使用Servlet的时候有看到:
此时,我们就需要思考一个问题request和response这两个参数的作用是什么?
-
request:==获取==请求数据
-
浏览器会发送HTTP请求到后台服务器[Tomcat]
-
HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]
-
后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中
-
所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数
-
获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务
-
-
response:==设置==响应数据
-
业务处理完后,后台就需要给前端返回业务处理的结果即响应数据
-
把响应数据封装到response对象中
-
后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果
-
浏览器最终解析结果,把内容展示在浏览器给用户浏览
-
对于上述所讲的内容,我们通过一个案例来初步体验下request和response对象的使用。
@WebServlet("/demo3") public class ServletDemo3 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用request对象 获取请求数据 String name = request.getParameter("name");//url?name=zhangsan //使用response对象 设置响应数据 response.setHeader("content-type","text/html;charset=utf-8"); response.getWriter().write("<h1>"+name+",欢迎您!</h1>"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("Post..."); } }
启动成功后就可以通过浏览器来访问,并且根据传入参数的不同就可以在页面上展示不同的内容:
小结
在这节中,我们主要认识了下request对象和reponse对象:
-
request对象是用来封装请求数据的对象
-
response对象是用来封装响应数据的对象
目前我们只知道这两个对象是用来干什么的,那么它们具体是如何实现的,就需要我们继续深入的学习。接下来,就先从Request对象来学习,主要学习下面这些内容:
-
request继承体系
-
request获取请求参数
-
request请求转发
2、Request对象
2.1 Request继承体系
在学习这节内容之前,我们先思考一个问题,前面在介绍Request和Reponse对象的时候,比较细心的同学可能已经发现:
-
当我们的Servlet类实现的是Servlet接口的时候,service方法中的参数是ServletRequest和ServletResponse
-
当我们的Servlet类继承的是HttpServlet类的时候,doGet和doPost方法中的参数就变成HttpServletRequest和HttpServletReponse
那么,
-
ServletRequest和HttpServletRequest的关系是什么?
-
request对象是有谁来创建的?
-
request提供了哪些API,这些API从哪里查?
首先,我们先来看下Request的继承体系:
从上图中可以看出,ServletRequest和HttpServletRequest都是Java提供的,所以我们可以打开JavaEE提供的API文档[参考: 资料/JavaEE7-api.chm],打开后可以看到:
所以ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法创建对象,这个时候就引发了下面这个问题:
-
该类实现了HttpServletRequest接口,也间接实现了ServletRequest接口。
-
Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的,所以Tomcat提供了方法参数接口的具体实现类,并完成了对象的创建
-
要想了解RequestFacade中都提供了哪些方法,我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档,因为RequestFacade实现了其接口就需要重写接口中的方法
对于上述结论,要想验证,可以编写一个Servlet,在方法中把request对象打印下,就能看到最终的对象是不是RequestFacade,代码如下:
@WebServlet("/demo2") public class ServletDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(request); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
启动服务器,运行访问http://localhost:8080/request-demo/demo2
,得到运行结果:
小结
-
Request的继承体系为ServletRequest-->HttpServletRequest-->RequestFacade
-
Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法
-
使用request对象,可以查阅JavaEE API文档的HttpServletRequest接口中方法说明
2.2 Request获取请求数据
HTTP请求数据总共分为三部分内容,分别是==请求行、请求头、请求体==,对于这三部分内容的数据,分别该如何获取,首先我们先来学习请求行数据如何获取?
2.2.1 获取请求行数据
请求行包含三块内容,分别是请求方式
、请求资源路径
、HTTP协议及版本
-
获取请求方式:
GET
String getMethod()
-
获取虚拟目录(项目访问路径):
/request-demo
String getContextPath()
-
获取URL(统一资源定位符):
http://localhost:8080/request-demo/req1
StringBuffer getRequestURL()
-
获取URI(统一资源标识符):
/request-demo/req1
String getRequestURI()
-
获取请求参数(GET方式):
username=zhangsan&password=123
String getQueryString()
介绍完上述方法后,咱们通过代码把上述方法都使用下:
/** * request 获取请求数据 */ @WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // String getMethod():获取请求方式: GET String method = req.getMethod(); System.out.println(method);//GET // String getContextPath():获取虚拟目录(项目访问路径):/request-demo String contextPath = req.getContextPath(); System.out.println(contextPath); // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1 StringBuffer url = req.getRequestURL(); System.out.println(url.toString()); // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1 String uri = req.getRequestURI(); System.out.println(uri); // String getQueryString():获取请求参数(GET方式): username=zhangsan String queryString = req.getQueryString(); System.out.println(queryString); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
启动服务器,访问http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123
,获取的结果如下:
对于请求头的数据,格式为key: value
如下:
所以根据请求头名称获取对应值的方法为:
String getHeader(String name)
接下来,在代码中如果想要获取客户端浏览器的版本信息,则可以使用
/** * request 获取请求数据 */ @WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求头: user-agent: 浏览器的版本信息 String agent = req.getHeader("user-agent"); System.out.println(agent); //遍历所有的请求头信息 Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { //注意:这里每次回拿到下一个节点的key,每一次循环只允许调用一次 String key = headerNames.nextElement(); System.out.println(key + ":" +request.getHeader(key)); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
重新启动服务器后,http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123
,获取的结果如下:
对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:
-
获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
ServletInputStream getInputStream() 该方法可以获取字节
-
获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
BufferedReader getReader()
接下来,大家需要思考,要想获取到请求体的内容该如何实现?
具体实现的步骤如下:
1.准备一个页面,在页面中添加form表单,用来发送post请求
2.在Servlet的doPost方法中获取请求体数据
3.在doPost方法中使用request的getReader()或者getInputStream()来获取
4.访问测试
-
在项目的webapp目录下添加一个html页面,名称为:
req.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- action:form表单提交的请求地址 method:请求方式,指定为post --> <form action="/request-demo/req1" method="post"> <input type="text" name="username"> <input type="password" name="password"> <input type="submit"> </form> </body> </html>
2.在Servlet的doPost方法中获取数据
/** * request 获取请求数据 */ @WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //在此处获取请求体中的数据 } }
3.调用getReader()或者getInputStream()方法,因为目前前端传递的是纯文本数据,所以我们采用getReader()方法来获取
/** * request 获取请求数据 */ @WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取post 请求体:请求参数 //1. 获取字符输入流 BufferedReader br = req.getReader(); //2. 读取数据 String line = br.readLine(); System.out.println(line); } }
==注意==
BufferedReader流是通过request对象来获取的,当请求完成后request对象就会被销毁,request对象被销毁后,BufferedReader流就会自动关闭,所以此处就不需要手动关闭流了。
4.启动服务器,通过浏览器访问http://localhost:8080/request-demo/req.html
点击提交
按钮后,就可以在控制台看到前端所发送的请求数据
小结
HTTP请求数据中包含了请求行
、请求头
和请求体
,针对这三部分内容,Request对象都提供了对应的API方法来获取对应的值:
-
请求行
-
getMethod()获取请求方式
-
getContextPath()获取项目访问路径
-
getRequestURL()获取请求URL
-
getRequestURI()获取请求URI
-
getQueryString()获取GET请求方式的请求参数
-
-
请求头
-
getHeader(String name)根据请求头名称获取其对应的值
-
request.getHeaderNames() 获取所有请求头的key
-
-
请求体
-
注意: ==浏览器发送的POST请求才有请求体==
-
如果是纯文本数据:getReader()
-
如果是字节数据如文件数据:getInputStream()
-
2.2.4 获取请求参数的通用方式
在学习下面内容之前,我们先提出两个问题:
-
什么是请求参数?
-
请求参数和请求数据的关系是什么?
1.什么是请求参数?
为了能更好的回答上述两个问题,我们拿用户登录的例子来说明
1.1 想要登录网址,需要进入登录页面
1.2 在登录页面输入用户名和密码
1.3 将用户名和密码提交到后台
1.4 后台校验用户名和密码是否正确
1.5 如果正确,则正常登录,如果不正确,则提示用户名或密码错误
上述例子中,用户名和密码其实就是我们所说的请求参数。
2.什么是请求数据?
请求数据则是包含请求行、请求头和请求体的所有数据
3.请求参数和请求数据的关系是什么?
3.1 请求参数是请求数据中的部分内容
3.2 如果是GET请求,请求参数在请求行中
3.3 如果是POST请求,请求参数一般在请求体中
对于请求参数的获取,常用的有以下两种:
-
GET方式:
String getQueryString()
-
POST方式:
BufferedReader getReader();
有了上述的知识储备,我们来实现一个案例需求:
(1)发送一个GET请求并携带用户名,后台接收后打印到控制台
(2)发送一个POST请求并携带用户名,后台接收后打印到控制台
此处大家需要注意的是GET请求和POST请求接收参数的方式不一样,具体实现的代码如下:
@WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String result = req.getQueryString(); System.out.println(result); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { BufferedReader br = req.getReader(); String result = br.readLine(); System.out.println(result); } }
-
对于上述的代码,会存在什么问题呢?
-
如何解决上述重复代码的问题呢?
当然,也可以在doGet中调用doPost,在doPost中完成参数的获取和打印,另外需要注意的是,doGet和doPost方法都必须存在,不能删除任意一个。
==GET请求和POST请求获取请求参数的方式不一样,在获取请求参数这块该如何实现呢?==
要想实现,我们就需要==思考==:
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,是否可以提供一种==统一==获取请求参数的方式,从而==统一==doGet和doPost方法内的代码?
解决方案一:
@WebServlet("/req1") public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取请求方式 String method = req.getMethod(); //获取请求参数 String params = ""; if("GET".equals(method)){ params = req.getQueryString(); }else if("POST".equals(method)){ BufferedReader reader = req.getReader(); params = reader.readLine(); } //将请求参数进行打印控制台 System.out.println(params); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
使用request的getMethod()来获取请求方式,根据请求方式的不同分别获取请求参数值,这样就可以解决上述问题,但是以后每个Servlet都需要这样写代码,实现起来比较麻烦,这种方案我们不采用
解决方案二:
request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可,在request的方法中都实现了哪些操作?
(1)根据不同的请求方式获取请求参数,获取的内容如下:
(2)把获取到的内容进行分割,内容如下:
(3)把分割后端数据,存入到一个Map集合中:
注意:因为参数的值可能是一个,也可能有多个,所以Map的值的类型为String数组。
基于上述理论,request对象为我们提供了如下方法:
-
获取所有参数Map集合
Map<String,String[]> getParameterMap()
-
根据名称获取参数值(数组)
String[] getParameterValues(String name)
-
根据名称获取参数值(单个值)
String getParameter(String name)
接下来,我们通过案例来把上述的三个方法进行实例演示:
1.修改req.html页面,添加爱好选项,爱好可以同时选多个
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/request-demo/req2" method="get"> <input type="text" name="username"><br> <input type="password" name="password"><br> <input type="checkbox" name="hobby" value="1"> 游泳 <input type="checkbox" name="hobby" value="2"> 爬山 <br> <input type="submit"> </form> </body> </html>
2.在Servlet代码中获取页面传递GET请求的参数值
2.1获取GET方式的所有请求参数
/** * request 通用方式获取请求参数 */ @WebServlet("/req2") public class RequestDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //GET请求逻辑 System.out.println("get...."); //1. 获取所有参数的Map集合 Map<String, String[]> map = req.getParameterMap(); for (String key : map.keySet()) { // username:zhangsan lisi System.out.print(key+":"); //获取值 String[] values = map.get(key); for (String value : values) { System.out.print(value + " "); } System.out.println(); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
获取的结果为:
2.2获取GET请求参数中的爱好,结果是数组值
/** * request 通用方式获取请求参数 */ @WebServlet("/req2") public class RequestDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //GET请求逻辑 //... System.out.println("------------"); String[] hobbies = req.getParameterValues("hobby"); for (String hobby : hobbies) { System.out.println(hobby); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
获取的结果为:
2.3获取GET请求参数中的用户名和密码,结果是单个值
/** * request 通用方式获取请求参数 */ @WebServlet("/req2") public class RequestDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //GET请求逻辑 //... String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username); System.out.println(password); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
获取的结果为:
3.在Servlet代码中获取页面传递POST请求的参数值
3.1将req.html页面form表单的提交方式改成post
3.2将doGet方法中的内容复制到doPost方法中即可
小结
-
req.getParameter()方法使用的频率会比较高
-
以后我们再写代码的时候,就只需要按照如下格式来编写:
public class RequestDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //采用request提供的获取请求参数的通用方式来获取请求参数 //编写其他的业务代码... } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
2.3 IDEA快速创建Servlet
使用通用方式获取请求参数后,屏蔽了GET和POST的请求方式代码的不同,则代码可以定义如下格式:
由于格式固定,所以我们可以使用IDEA提供的模板来制作一个Servlet的模板,这样我们后期在创建Servlet的时候就会更高效,具体如何实现:
(1)按照自己的需求,修改Servlet创建的模板内容
(2)使用servlet模板创建Servlet类
2.4 请求参数中文乱码问题
问题展示:
(1)将req.html页面的请求方式修改为get
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/request-demo/req2" method="get"> <input type="text" name="username"><br> <input type="password" name="password"><br> <input type="checkbox" name="hobby" value="1"> 游泳 <input type="checkbox" name="hobby" value="2"> 爬山 <br> <input type="submit"> </form> </body> </html>
(2)在Servlet方法中获取参数,并打印
/** * 中文乱码问题解决方案 */ @WebServlet("/req4") public class RequestDemo4 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获取username String username = request.getParameter("username"); System.out.println(username); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
(3)启动服务器,页面上输入中文参数
(4)查看控制台打印内容
(5)把req.html页面的请求方式改成post,再次发送请求和中文参数
(6)查看控制台打印内容,依然为乱码
通过上面的案例,会发现,不管是GET还是POST请求,在发送的请求参数中如果有中文,在后台接收的时候,都会出现中文乱码的问题。具体该如何解决呢?
2.4.1 POST请求解决方案
-
分析出现中文乱码的原因:
-
POST的请求参数是通过request的getReader()来获取流中的数据
-
TOMCAT在获取流的时候采用的编码是ISO-8859-1
-
ISO-8859-1编码是不支持中文的,所以会出现乱码
-
-
解决方案:
-
页面设置的编码格式为UTF-8
-
把TOMCAT在获取流数据之前的编码设置为UTF-8
-
通过request.setCharacterEncoding("UTF-8")设置编码,UTF-8也可以写成小写
-
修改后的代码为:
/** * 中文乱码问题解决方案 */ @WebServlet("/req4") public class RequestDemo4 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 解决乱码: POST getReader() //设置字符输入流的编码,设置的字符集要和页面保持一致 request.setCharacterEncoding("UTF-8"); //2. 获取username String username = request.getParameter("username"); System.out.println(username); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
重新发送POST请求,就会在控制台看到正常展示的中文结果。
至此POST请求中文乱码的问题就已经解决,但是这种方案不适用于GET请求,这个原因是什么呢&