目录
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象。
首先我们要了解一下Http协议,然后学习HttpServletResponse和HttpServletRequest对象。
关于Http协议可以看之前整理的博客:https://blog.csdn.net/weixin_39478524/article/details/115336677,
Http中很重要的就是请求和响应操作,对应的就是HttpServletRequest对象和HttpServletResponse对象,所有数据的操作都是基于这两个对象封装的。
一、HttpServletResponse
HttpServletResponse对应的是响应消息,负责操作响应的数据,
响应消息可以分为三部分:响应行、响应头和响应正文,我们也分三部分介绍HttpServletResponse如何操作这三部分。
1.1响应行
HTTP/1.1 200 OK
响应消息行主要包括两个部分:协议版本和响应状态码,操作响应行的函数主要就是设置响应状态码,
setStatus(int sc)//设置响应状态码
1.2响应头
响应消息头由一系列的键值对组成,主要有以下方法对响应头进行操作,
sendRedirect(String location)//请求重定向
addHeader(String name, String value)//添加响应头信息
setHeader(String name, String value)//设置响应头信息,没有键时自动添加
我们可以利用setHeader()方法告诉浏览器用什么码表,
response.setHeader("content-type", "text/html;charset=UTF-8");
1.3响应正文
getWrite();//返回字符输出流
getOutputStream();//返回字节输出流
setCharacterEncoding(String charset);//设置字符编码类型
setContentType(String type);//设置文本类型
1.4常见应用
下面我们依次介绍一下response的常见应用
1.4.1响应编码字符输出流
我们测试一下,在响应正文中输出我们想要的字符串,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "ServletDemo1")
public class ServletDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("Unicode");//设置服务器编码方式,否则默认编码中文会乱码
response.setHeader("content-type","text/html;charset=Unicode");//设置响应消息头编码方式
PrintWriter out=response.getWriter();//得到一个字符输出流
out.write("中文测试");//向客户端响应文本内容
}
}
或者也可以直接设置文本编码方式,将设置服务器编码和消息头编码合并为一句,
response.setContentType("text/html;charset=Unicode");//设置文本编码格式
然后配置一下映射的路径,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>servletDemo</servlet-name>
<servlet-class>ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo</servlet-name>
<url-pattern>/demo</url-pattern>
</servlet-mapping>
</web-app>
显示效果如下:
1.4.2响应编码字节输出流
接着测试一下字节输出流输出信息,
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletDemo2")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletOutputStream servletOutputStream=response.getOutputStream();//获取字节输出流
servletOutputStream.write("字节输出流测试".getBytes());//向响应正文输出信息
}
}
修改配置信息,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>servletDemo2</servlet-name>
<servlet-class>ServletDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo2</servlet-name>
<url-pattern>/demo2</url-pattern>
</servlet-mapping>
</web-app>
输出结果:
1.4.3文件下载
我们以图片为例,将资源放在工程的src文件夹下,
我们首先将文件输出到客户端,在网页中显示,
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet(name = "ServletDemo3")
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path=this.getServletContext().getRealPath("/WEB-INF/classes/snow.JPG");//得到文件的路径
FileInputStream fileInputStream=new FileInputStream(path);//通过路径得到输入流
ServletOutputStream servletOutputStream=response.getOutputStream();//获取输出到客户端的字节输出流
int len=1;
byte b[]=new byte[1024];
while((len= fileInputStream.read(b))!=-1){
servletOutputStream.write(b,0,len);//输出到客户端
}
servletOutputStream.close();
fileInputStream.close();
}
}
配置一下web.xml文件,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>servletDemo3</servlet-name>
<servlet-class>ServletDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo3</servlet-name>
<url-pattern>/demo3</url-pattern>
</servlet-mapping>
</web-app>
显示效果:
接下来我们更改一下代码,让用户可以直接下载图片,
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet(name = "ServletDemo3")
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path=this.getServletContext().getRealPath("/WEB-INF/classes/snow.JPG");//得到文件的路径
FileInputStream fileInputStream=new FileInputStream(path);//通过路径得到输入流
ServletOutputStream servletOutputStream=response.getOutputStream();//获取输出到客户端的字节输出流
String filename=path.substring(path.lastIndexOf("\\")+1);//获取需要下载的文件名
response.setHeader("content-disposition","attachment;filename="+filename);//告知客户端要下载文件
response.setHeader("content-type","image/jpeg");//告知客户端下载文件的类型
int len=1;
byte b[]=new byte[1024];
while((len= fileInputStream.read(b))!=-1){
servletOutputStream.write(b,0,len);//输出到客户端
}
servletOutputStream.close();
fileInputStream.close();
}
}
网页效果,网页将图片已经下载好了:
1.4.4验证码
验证码是一种防止暴力破解的工具,在某种程度上可以区分人和机器,现在我们制作一个带验证码的登录界面,
首先我们用代码创建验证码,
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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;
@WebServlet(name = "ServletDemo4")
public class ServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width=100;//图片宽度
int height=25;//图片高度
BufferedImage img=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//在内存中创建一个图像
Graphics g=img.getGraphics();//创建一个画笔
//设置背景
g.setColor(Color.PINK);//设置背景填充颜色
g.fillRect(1,1,width-2,height-2);//设置填充的范围
g.setColor(Color.RED);//设置边框颜色
g.drawRect(0,0,width-1,height-1);//以边框色画出边框
//添加验证码数字
g.setColor(Color.BLUE);//设置文本颜色
g.setFont(new Font("宋体",Font.BOLD|Font.ITALIC,15));//设置字体样式
Random rand=new Random();
String code=rand.nextInt(10)+" "+rand.nextInt(10)+" "+rand.nextInt(10)+" "+rand.nextInt(10);//产生随机验证码
g.drawString(code,20,18);
//添加验证码干扰线
for (int i = 0; i < 5; i++) {
g.drawLine(rand.nextInt(width),rand.nextInt(height),rand.nextInt(width),rand.nextInt(height));//产生随机坐标的直线
}
ImageIO.write(img,"jpg",response.getOutputStream());//将图片对象以流的方式输出到客户端
}
}
配置xml文件检验效果,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>servletDemo4</servlet-name>
<servlet-class>ServletDemo4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo4</servlet-name>
<url-pattern>/demo4</url-pattern>
</servlet-mapping>
</web-app>
输入http://localhost:8080/demo4,看看验证码的效果图,
然后我们在html文件中访问该地址,需要注意要加上http协议,否则访问不成功,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
<script type="text/javascript">
function changeCode(){
var img=document.getElementsByTagName("img")[0];//得到图片元素
img.src="http://localhost:8080/demo4?time="+ new Date().getTime();//重新赋值src路径,加入时间避免浏览器使用缓存的数据不刷新
}
</script>
</head>
<body>
<form action="#" method="post">
用户名:<input type="text" name="userName"/><br>
密码:<input type="password" name="passWord"/><br>
验证码:<input type="text" name="code"/>
<img src="http://localhost:8080/demo4" onclick="changeCode()"/><a href="javascript:changeCode()">看不清换一张</a><br>
<input type="submit" value="登录"/><br>
</form>
</body>
</html>
访问界面:
刷新之后的效果:
1.4.5验证码——工具类实现
首先我们导入外部的工具类,以IDEA为例:
依次点击File->Project Structure->Libraries,点击加号添加我们的jar工具包ValidateCode.jar,然后新建Servlet导入该工具类,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import cn.dsna.util.images.ValidateCode;
@WebServlet(name = "ServletDemo5")
public class ServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width=100;//图片宽度
int height=25;//图片高度
int codeCount=4;//验证码字符数量
int lineCount=5;//干扰线数量
ValidateCode validateCode=new ValidateCode(width,height,codeCount,lineCount);//生成验证码
validateCode.write(response.getOutputStream());//输出到网页
}
}
然后配置一下映射地址,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>servletDemo5</servlet-name>
<servlet-class>ServletDemo5</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo5</servlet-name>
<url-pattern>/demo5</url-pattern>
</servlet-mapping>
</web-app>
可以看到工具类实现的验证码如下,
1.4.6设置客户端不使用缓存
当页面进行刷新时,正常的验证码都会进行更新,但是如果我们不在验证码地址后加时间,那么浏览器就会认为该资源已经加载过了,
刷新的时候不访问服务器,直接从网页的缓存中提取资源,验证码也就不会刷新,这时我们也可以不在资源后加时间后缀,设置客户端不使用缓存,每次访问资源都要走服务器的通道,那么验证码自然刷新就会更新,
response.setHeader("pragma","no-cache");
response.setHeader("cache-control","no-cache");
response.setHeader("expires","0");
这样验证码每次就会从服务器获取,而不会从缓存中获取了。
1.4.7网页定时刷新
定时刷新用到的还是setHeader方法,设置响应消息头,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;
@WebServlet(name = "ServletDemo6")
public class ServletDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("refresh","1");//设置响应消息头,1s刷新一次
Random random=new Random();
response.getWriter().write(random.nextInt(100)+"");
}
}
刷新结果:
还可以刷新的时候跳转到指定的url路径,
response.setContentType("text/html;charset=UTF-8");//设置客户端字符集
response.getWriter().write("3s后跳转到百度");
response.setHeader("refresh","3;url=http://www.baidu.com");
1.5请求重定向
请求重定向和请求转发类似,都是客户端请求Servlet1完成某个功能,但是Servlet1无法完成,转而让Servlet2完成,
二者不同的是:
- 转发在服务器端完成的;重定向是在客户端完成的
- 转发的速度快;重定向速度慢
- 转发的是同一次请求;重定向是两次不同请求
- 转发不会执行转发后的代码;重定向会执行重定向之后的代码
- 转发地址栏没有变化;重定向地址栏有变化
- 转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成
请求转发和请求重定向示意图如下,
请求重定向是通过setStatus方法来告诉客户端要重定向到新的url,
通过设置响应消息头来告诉客户端具体重定向的url地址,
response.setStatus(302);//告诉客户端要重定向操作
response.setHeader("location","url");//告诉客户端重定向的url地址
或者也可以将这两个方法使用一个方法替代,
response.sendRedirect("url");//告知客户端要重定向,并且重定向到url地址
我们测试一下请求重定向,新建两个Servlet:ServletDemo7、ServletDemo8,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletDemo7")
public class ServletDemo7 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("请求重定向");
response.setStatus(302);//告知客户端需要重定向
response.setHeader("location","http://localhost:8080/demo8");//告诉客户端重定向的地址
}
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletDemo8")
public class ServletDemo8 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("收到!");
}
}
我们启动tomcat服务器,请求demo7,http://localhost:8080/demo7,
结果会将请求重定向到demo8,http://localhost:8080/demo8,
1.6 HttpServletResponse对象细节
- getOutputStream和getWriter
- getOutputStream方法用于得到输出二进制数据的ServletOuputStream对象
- getWriter方法用于得到输出文本数据的Printwriter对象
- 这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。会抛异常
- Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端
- Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象
二、HttpServletRequest
HttpServletRequest对象代表了客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,
开发人员通过这个对象的方法,可以获得用户的信息,如下:
getRequestURL();//方法返回客户端发出请求时的完整URL
getRequestURI();//方法返回请求行中的资源名部分
getQueryString();//方法返回请求行中的参数部分
getRemoteAddr();//方法返回发出请求的客户机的IP地址
getRemoteHost();//方法返回发出请求的客户机的完整主机名
getRemotePort();//方法返回客户机所使用的网络端口号
getLocalAddr();//方法返回WEB服务器的IP地址
getLocalName();//方法返回WEB服务器的主机名
getMethod();//得到客户机请求方式
2.1请求行
比如请求行消息:Get http://localhost:8080/demo8?username=zs http/1.1
getMethod();//获得请求方式
getRequestURL();//返回客户端发出请求时的完整URL
getRequestURI();//返回请求行中的资源名部分
getContextPath();//当前应用的虚拟目录 /demo8
getQueryString();//返回请求行中的参数部分
我们测试一下这几个方法,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletRequestDemo1")
public class ServletRequestDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(request.getMethod());//输出请求方式
System.out.println(request.getRequestURL());//输出客户端发出请求时的完整URL
System.out.println(request.getRequestURI());//输出请求行中资源名部分
System.out.println(request.getContextPath());//输出当前应用的虚拟目录
System.out.println(request.getQueryString());//输出请求行中的参数部分
}
}
登录http://localhost:8080/Demo1?username=peru网站,输出结果如下:
2.2请求消息头
String getHeader(String name);/根据头名称得到头信息值
Enumeration getHeaderNames();//得到所有头信息name
Enumeration getHeaders(String name);//根据头名称得到相同名称头信息值
我们输出一下请求消息头的所有信息,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet(name = "ServletRequestDemo2")
public class ServletRequestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Enumeration names=request.getHeaderNames();//获取所有请求消息头的name
while(names.hasMoreElements()){
String nextElement=(String)names.nextElement();
System.out.println(nextElement+":"+request.getHeader(nextElement));//逐个输出请求消息头的键值对
}
System.out.println(request.getHeader("User-Agent"));//获得请求消息头信息
}
}
输出结果如下,
2.3请求正文
2.3.1获取表单数据
getParameter(name);//根据表单中name属性的名,获取value属性的值方法
getParameterValues(String name);//专业为复选框取取提供的方法
getParameterNames();//得到表单提交的所有name的方法
getParameterMap();//得到表单提交的所有值的方法。做框架用,非常实用
getInputStream();//以字节流的方式得到所有表单数据
我们首先制作一个注册界面,设置表单数据让用户填写,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/Demo3" method="post">
用户名:<input type="text" name="userName"/><br/>
密码:<input type="password" name="passWord"/><br/>
性别:<input type="radio" name="sex" value="男" checked="checked"/>男
<input type="radio" name="sex" value="女"/>女<br/>
爱好:<input type="checkbox" name="hobby" value="运动"/>运动
<input type="checkbox" name="hobby" value="听歌"/>听歌
<input type="checkbox" name="hobby" value="看书"/>看书
<input type="checkbox" name="hobby" value="睡觉"/>睡觉<br/>
居住地:<select name="city">
<option>————请选择————</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="武汉">武汉</option>
</select><br/>
<input type="submit" value="注册"/>
</form>
</body>
</html>
然后我们在servlet应用中获取表单数据,并输出(注意这里要将form标签的action属性设置为servlet应用的映射访问地址),获取表单数据一共有四种方法,
1、第一种为直接通过表单项的名字获取表单项的值然后输出,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletRequestDemo3")
public class ServletRequestDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
//获取提交的表单数据
System.out.println("用户名:"+request.getParameter("userName"));//输出用户名
System.out.println("密码:"+request.getParameter("passWord"));//输出密码
System.out.println("性别:"+request.getParameter("sex"));//输出性别
String[] hobbys=request.getParameterValues("hobby");//获取爱好字符串数组
System.out.print("爱好:");
for (int i = 0; hobbys!=null && i < hobbys.length; i++) {
System.out.print(hobbys[i]);
}
System.out.println();
System.out.println("居住地:"+request.getParameter("city"));//输出居住地
}
}
然后我们进入到注册界面,填写好表单数据,点击注册可以看到输出结果:
2、我们还可以先获取所有的表单项名字,通过名字获取表单项的值,
request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
Enumeration names=request.getParameterNames();//获取所有表单项的名字
while(names.hasMoreElements()){
String name=(String) names.nextElement();//获取表单的名字
System.out.print(name+":");
String[] values=request.getParameterValues(name);//得到该表单项的值
for (int i = 0; values!=null && i < values.length; i++) {
System.out.print(values[i]+" ");
}
System.out.println();
}
结果如图,
3、第三种方法为使用getParameterMap(),该方法可以获取表单提交的所有值,一般在框架中经常使用,
首先我们生成用户类,里面存放着对应的用户注册的信息,也就是表单的信息(同时还要实现toString、set和get方法),
//在实体类中的字段要与表单中的name名一致
public class User {
private String userName;
private String passWord;
private String sex;
private String[] hobby;
private String city;
}
然后我们将得到的表单数据封装到用户类中,
User user=new User();
Map<String,String[]> map=request.getParameterMap();//获取提交的表单数据集合
for (Map.Entry<String,String[]> m:map.entrySet()) {
String name=m.getKey();
String[] value=m.getValue();
//创建一个属性描述器
try {
PropertyDescriptor propertyDescriptor=new PropertyDescriptor(name,User.class);//将集合中的值内省到User类的变量上
Method setter=propertyDescriptor.getWriteMethod();//得到User类中的set方法
if (value.length==1){
setter.invoke(user,value[0]);//给一个值的变量赋值
}else{
setter.invoke(user,(Object)value);//给多个值的变量赋值,比如数组
}
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(user);//输出用户信息
结果如下图,
基于这个方法,我们可以直接使用框架来提取表单数据,我们导入两个jar包:commons-beanutils-1.8.3.jar和commons-logging-1.1.1.jar,这种方法代码就很简洁了,jar包地址为:
链接:https://pan.baidu.com/s/1NcpIN_uFD1sIKZKLYIVX4g
提取码:1qyv
复制这段内容后打开百度网盘手机App,操作更方便哦
request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
try {
User user=new User();
BeanUtils.populate(user,request.getParameterMap());
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
}
结果如下,
4、最后一种方式是以字节流的形式获取表单数据,使用的方法为getInputStream(),
ServletInputStream servletInputStream=request.getInputStream();//获取字节输入流
int len=0;
byte[] bytes=new byte[1024];
while((len=servletInputStream.read(bytes))!=-1){
String name=new String(bytes,0,len);
System.out.println(new String(name.getBytes("iso-8859-1"),"UTF-8"));
}
servletInputStream.close();
2.3.2操作非表单数据
非表单数据就是非表单提交的数据,这些数据在request域对象中存储,一般我们使用以下的方法进行操作,
void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);
这里我们用转发来测试一下非表单数据如何进行传输的,我们在Demo4中将非表单数据放在request中,
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletRequestDemo4")
public class ServletRequestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
response.setContentType("text/html;charset=UTF-8");
String str="java";//非表单数据
request.setAttribute("data",str);//将非表单数据添加到request域中
RequestDispatcher requestDispatcher=request.getRequestDispatcher("/Demo5");//获取服务器资源包装器
requestDispatcher.forward(request,response);//请求转发
}
}
然后在Demo5中获取数据,
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletRequestDemo5")
public class ServletRequestDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
String att=(String)request.getAttribute("data");
System.out.println(att);
}
}
输出结果如下,
2.3.3请求转发和请求包含
转发和1.5的重定向类似,都是客户端发送请求给Servlet1,Servlet1无法完成让Servlet2完成,
转发是Servlet1来将请求转发给Servlet2,客户端只用发送一次请求;而重定向则是Servlet1告诉客户端Servlet2可以做,让客户端自己重新发送请求,客户端一共发送了两次请求。
RequestDispatcher getRequestDispatcher(String path);//得到请求转发或请求包含的协助对象
forward(ServletRequest request, ServletResponse response);//转发的方法
include(ServletRequest request, ServletResponse response);//请求包含
我们新建一个Servlet,将请求转发给Demo1,
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "ServletRequestDemo4")
public class ServletRequestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//设置服务器编码方式(要与浏览器编码方式相同),避免获取网页信息时中文显示乱码
response.setContentType("text/html;charset=UTF-8");
RequestDispatcher requestDispatcher=request.getRequestDispatcher("/Demo1");//获取服务器资源包装器
requestDispatcher.forward(request,response);//请求转发
}
}
然后配置一下web.xml配置文件,开启服务器访问http://localhost:8080/Demo4,请求转发结果如下,
请求包含就是Servlet(源组件)把其他Servlet(目标组件)生成的响应结果包含到自身的响应结果中,
request.getRequestDispatcher(“接收请求的Servlet 路径”). include(request,response)
2.3.4请求编码
表单的提交方式一般分为post和get,为了解决乱码问题有不同的方法,
request.setCharacterEncoding("UTF-8");//告诉服务器客户端什么编码,只能处理post请求方式
String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);//对每个字符串进行重新编码,用于处理get请求方式