Java Web Servlet Response响应案例操作
2018/8/15
今天根据视频操作了一些响应的案例
案例需求:
1.完成响应重定向
将ResponseDemo1重定向到ResponseDemo2
ResponseDemo1代码如下
package cn.zsc.web.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;
/***
* 完成相应重定向
*/
@WebServlet(name = "ResponseDemo1",urlPatterns = "/RDemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo1被访问,开始重定向");
//案例功能:访问RDemo1,会自动跳转到RDemo2
//1.设置状态码
/*response.setStatus(302);
//2.设置响应头
response.setHeader("location","/zsc/RDemo2");*/
//更简单的响应重定向,
//1.先动态获取虚拟目录
String contextPath = request.getContextPath();
//2.使用sendRedirect方法,参数为重定向的location,因为是客户端访问所以要加上虚拟目录
response.sendRedirect(contextPath+"/RDemo2");
//响应重定向可以访问其他站点的资源
//response.sendRedirect("http://www.baidu.com");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
ResponseDemo2代码如下
package cn.zsc.web.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;
@WebServlet(name = "ResponseDemo2",urlPatterns = "/RDemo2")
public class ResponseDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("重定向成功,demo2被访问,");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
在ResponseDemo1中一开始是使用这样的代码来设置响应重定向的
//案例功能:访问RDemo1,会自动跳转到RDemo2
//1.设置状态码
response.setStatus(302);
//2.设置响应头
response.setHeader("location","/zsc/RDemo2");
实际上可以使用更简单的方法
//1.先动态获取虚拟目录
String contextPath = request.getContextPath();
//2.使用sendRedirect方法,参数为重定向的location,因为是客户端访问所以要加上虚拟目录
response.sendRedirect(contextPath+"/RDemo2");
在其中使用了动态获取虚拟目录的方法来获取虚拟目录,这样在修改虚拟目录后不需要修改此处的代码
附上视频笔记:
介绍响应重定向和请求转发的区别以及讲解了上面时候用要加虚拟路径,什么时候不需要加虚拟路径
2.服务器输出字符数据到浏览器
代码如下
package cn.zsc.web.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 java.io.PrintWriter;
/***
* 服务器输出字符数据到浏览器
* 使用字符输出流
*/
@WebServlet(name = "ResponseDemo3",urlPatterns = "/RDemo3")
public class ResponseDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//在servlet开始时一定要解决中文乱码的问题,而且要在获取流之前设置
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter out = response.getWriter();
//2.调用输出流的println方法输出数据
out.println("<h1>你好</h1>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
这个案例要注意中文乱码的问题,以及解决方法
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
附上视频笔记:
3.服务器输出字节数据到浏览器
这里是字节数据不是字符数据,使用要使用字节输出的流,ServletOutputStream。
如果使用的流为字节输出流通过getBYtes后就不需要设置编码了,不会出现中文乱码的问题
字节流会根据计算机的编码方式来选择编码方式
代码如下
package cn.zsc.web.servlet;
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 = "ResponseDemo4",urlPatterns = "/RDemo4")
public class ResponseDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//如果使用的流为字节输出流通过getBYtes后就不需要设置编码了,不会出现中文乱码的问题
//1.获取字节输出流,ServletOutputStream对象,使用response.getOutputStream()方法获取
ServletOutputStream sout = response.getOutputStream();
//2.输出数据
sout.write("你好".getBytes());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
4.写验证码
步骤
1.创建一个对象,在内存中的图片(验证码图片对象)
使用BufferedImage来创建对象,
代码如下
//1.创建一个对象,在内存中的图片(验证码图片对象)
//定义图片的长和宽
int width=100;
int heigh=50;
//在内存中画图要使用BufferedImage来创建对象
BufferedImage image=new BufferedImage(width,heigh,BufferedImage.TYPE_INT_RGB);
BufferedImage对象的第三个参数
//指定宽高、图像字节灰度
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY)
//创建一个不带透明色的对象
BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//创建一个带透明色的对象
new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
2.美化图片
这时的图片就只是一个黑色长方形,所以要对该图像进行美化
在美化时会用到画笔Graphics这个类
所以先要创建画笔这个类对象
Graphics g = image.getGraphics(); //通过图像的对象的getGraphics()方法获取画笔对象
然后开始使用该对象去填充,画边框,字符,以及干扰线
填充代码:
//2.1填充背景色
g.setColor(Color.pink); //设置画笔颜色为粉色
g.fillRect(0,0,width,heigh); //参数为开始画的(x,y)点,到width长和到height高
画边框代码:
//2.2画图像的边框
g.setColor(Color.BLUE); //设置画笔颜色为蓝色
g.drawRect(0,0,width-1,heigh-1); //参数为为开始画的(x,y)点,因为边框占一个像素使用在width和height要减一
画边框时要注意边框也是有大小的,所以给长度时要留出边框的长度,要不然会被挤掉
画字符代码:
//2.3先选取随机的字符并将验证码写到图像上
String str="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm0123456789"; //存放字符的字符串
Random random=new Random(); //创建随机数的类
for (int j = 0; j < 4; j++) {
int i = random.nextInt(str.length()); //定义随机的下标数,并且给定范围
char c = str.charAt(i); //取随机字符
g.drawString(c+"",width/5*(j+1),heigh/2); //使用drawString方法来画字符串
}
因为画字符要产生随机的字符所以要使用Randow的nextInt(随机数的范围)方法来产生字符串集的下标数然后charAt(下标数)来取随机字符
取到随机字符然后使用drawSting方法来画字符,因为该方法第一个参数为String使用使用c+“”来解决
画干扰线代码:
//2.5先选取随机的10组点并画随机的直线
g.setColor(Color.GREEN); //设置线的颜色
for (int z = 0; z < 11; z++) {
int x1 = random.nextInt(width); //生成x1的随机数
int x2 = random.nextInt(width); //生成x2的随机数
int y1 = random.nextInt(heigh); //生成y1的随机数
int y2 = random.nextInt(heigh); //生成y2的随机数
g.drawLine(x1,y1,x2,y2); //给定x1,y1,x2,y2,使用drawLine开始画线
}
这里一样要取随机数,该随机数分别为drawLine方法的两个点的坐标,所以这样画出来的线是随机位置的
3.将图片输出到页面上
使用ImageIO的静态方法write进行输出
参数为当前的图像对象,输出图像的图像格式,响应的字节输出流
ImageIO.write(image,"jpg",response.getOutputStream());
全代码:
package cn.zsc.web.servlet;
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 = "CheckCodeServlet",urlPatterns = "/ccsdemo1")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.创建一个对象,在内存中的图片(验证码图片对象)
//定义图片的长和宽
int width=100;
int heigh=50;
//在内存中画图要使用BufferedImage来创建对象
BufferedImage image=new BufferedImage(width,heigh,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics(); //通过图像的对象的getGraphics()方法获取画笔对象
//2.美化图片
//2.1填充背景色
g.setColor(Color.pink); //设置画笔颜色为粉色
g.fillRect(0,0,width,heigh); //参数为开始画的(x,y)点,到width长和到height高
//2.2画图像的边框
g.setColor(Color.BLUE); //设置画笔颜色为蓝色
g.drawRect(0,0,width-1,heigh-1); //参数为为开始画的(x,y)点,因为边框占一个像素使用在width和height要减一
//2.3先选取随机的字符并将验证码写到图像上
String str="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm0123456789"; //存放字符的字符串
Random random=new Random(); //创建随机数的类
for (int j = 0; j < 4; j++) {
int i = random.nextInt(str.length()); //定义随机的下标数,并且给定范围
char c = str.charAt(i); //取随机字符
g.drawString(c+"",width/5*(j+1),heigh/2); //使用drawString方法来画字符串
}
//2.5先选取随机的10组点并画随机的直线
g.setColor(Color.GREEN); //设置线的颜色
for (int z = 0; z < 11; z++) {
int x1 = random.nextInt(width); //生成x1的随机数
int x2 = random.nextInt(width); //生成x2的随机数
int y1 = random.nextInt(heigh); //生成y1的随机数
int y2 = random.nextInt(heigh); //生成y2的随机数
g.drawLine(x1,y1,x2,y2); //给定x1,y1,x2,y2,使用drawLine开始画线
}
//3.将图片输出到页面上
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
图片输出完了以后就要将此图片写到html页面上所以就要使用html的img标签来加载图片
html的测试此图片的代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码</title>
<script type="text/javascript">
//1.给超链接和图片绑定单机事件
//2.重新设置图片的src属性值
window.onload=function () {
//1.获取图片,并绑定单机事件
document.getElementById("checkcode").onclick=function () {
//为了解决同一张图片被浏览器缓存的问题,可以加时间戳,因为时间戳永不重复解决是同一个链接缓存问题
var date=new Date().getTime();
this.src="/zsc/ccsdemo1?"+date;
}
//2.获取超链接,并绑定单机事件
document.getElementById("a1").onclick=function () {
var date=new Date().getTime();
this.hred="/zsc/check.html?"+date;
}
}
</script>
</head>
<body>
<img id="checkcode" src="/zsc/ccsdemo1">
<a id="a1" href="">看不清,换一张</a>
</body>
</html>
如果要达到点击图片和超链接就会更新图片的效果,所以使用了JavaScript的代码来对图片和超链接进行和单击事件的绑定
图片单击事件:
单击后只要改变图片的src就可以了,但是因为浏览器的缓存问题就会导致单击图片并不会更新图片,所以这里在src后给了一个?,然后在?后接值来骗过浏览器,这里加的是当前时间的时间戳保证不会重复出现相同的地址就可以
//1.获取图片,并绑定单机事件
document.getElementById("checkcode").onclick=function () {
//为了解决同一张图片被浏览器缓存的问题,可以加时间戳,因为时间戳永不重复解决是同一个链接缓存问题
var date=new Date().getTime();
this.src="/zsc/ccsdemo1?"+date;
}
单击超链接更新图片事件:
这里改变的是超链接的hred属性来更新图片,一样使用时间戳来骗过浏览器
//2.获取超链接,并绑定单机事件
document.getElementById("a1").onclick=function () {
var date=new Date().getTime();
this.hred="/zsc/check.html?"+date;
}
在实际中并不会使用自己写的验证码代码,而是在网上找一些别人美观精致的验证码改一下来使用
,自己可以练习练习,知道思路。