Response

response对象的概念

HttpServletResponse对象封装了向客户端发送数据,发送三响应头,响应状态码的方法
因此,必须学会HttpServletResponse,才能给浏览器发送数据

response操作相应行

组成
响应行,响应头,响应体
响应行是http响应内容的第一行。

响应行一般数据为:
HTTP/1.1 200(tomcat8.5)
HTTP/1.1 200 OK(tomcat7)

响应行分为三个部分: HTTP/1.1:协议版本
200:响应状态码
OK:对响应状态码的解释

常见的响应状态码:
200 OK 请求已成功,请求所希望的响应头或数据体将随此响应返回。出现此状态码是表示正常状态。
302 Move temporarily 重定向,请求的资源临时从不同的 URI响应请求。
304 Not Modified 从缓存中读取数据,不从服务器重新获取数据。
403 Forbidden 服务器已经理解请求,但是拒绝执行它,一般在权限不够的时候常见。
404 Not Found 请求失败,请求所希望得到的资源未被在服务器上发现。
405 Method Not Allowed 请求行中指定的请求方法不能被用于请求相应的资源。
500 Internal Server Error 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
了解了http协议有关响应行的部分,对于response对象来说 , 只有响应状态码可以操作 , 并且我们一般也不操作状态码 。

API介绍
void setStatus(int sc) 设置响应的状态代码(一般用来设置 1xx 2xx 3xx)
void setError(int sc) 设置响应的状态代码(一般用来设置 4xx 5xx)
注意 : 状态码的一般不需要我们手动设置

操作响应头
常见的响应头介绍
1. location :
重定向操作:通常告知浏览器马上向该地址发送请求,通常和响应码302一起使用
两次请求,一次手动,一次自动

  1. refresh :
    定时刷新操作 , 指定时间后跳转到指定页面
  2. content-encoding :
    设置当前数据的压缩格式,告知浏览器以何种压缩格式解压数据
  3. content-disposition :
    通知浏览器以何种方式获取数据(直接解析数据(网页,图片文本),或者以附件方式attachment(下载文件))

  4. content-type :
    实体头部用于指示资源的MIME类型(MIME类型:用于提示当前文件的媒体类型,例如图片为 : image/png、音频为:audio/ogg)。它的作用与传统上Windows上的文件扩展名相同。该名称源于最初用于电子邮件的
    MIME标准。)
    setContentType(“text/html;charset=UTF-8”);
    底层是如下
    setHeader(“content-type”,”text/html;charset=UTF-8”);

注意:我们content‐type常用的设置一般都是“text/html;charset=utf‐8”
“text/html”用来设置浏览器以指定文件格式解析数据;
“charset=utf‐8”用来响应数据的编码表,若不需要设置编码可以不写。
方法
设置头
setHeader(String 名字,String 值) –> 都是字符串
setIntHeader(String 名字, int 值)
setDataHeader(String 名字,long 值)
添加头
addHeader(String 名字, String 值) –> 字符串

操作响应体

API介绍(字符+字符串)
ServletOutputStream getOutputStream() 获取字节输出流
PrintWriter getWriter() 获取字符输出流

注意:两个流不能同时使用(互斥),这两个流使用完成后如果没有关闭,Servlet容器会帮我们将其关闭

代码实例
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//字符流的方式写数据
response.getWriter().write(“hello response…”);
//字节流的方式写数据
response.getOutputStream().write(“hahhahaha”.getBytes());
}

1.向浏览器输出中文数据(无乱码)

以字符流输出
–> response.getWriter().write(“..”);
//中文乱码
//字符流的方式写数据
//此处写出去的文字,默认使用的是ISO-8859-1,我们可以指定写出去的时候所使用的编码
//1.指定输出到客户端的时候,这些文字使用UTF-8码
response.setCharacterEncoding(“UTF-8”);
//2.直接规定浏览器看这份数据的时候,使用的编码
response.setHeader(“Content-Type”, “text/html; charset=UTF-8”);
response.getWriter().write(“你好”);

以字节流输出
//设置相应的数据类型是html文本,并且告知浏览器,使用UTF-8来编码
response.setContentType(“text/html;charset=UTF-8”);
–> 不管字节流还是字符流, 一行代码即可

//字节流的方式写数据
//如果想让服务器端出去的中文,在客户端正常显示
//那么,只要保证客户端看的编码和这数据的编码相同即可
//默认情况下,字节输出流,输出使用的是UTF-8编码

//如果想要获取具体的编码,可以在byte数组的时候
    //1.指定浏览器看这份数据使用的码表
    response.setHeader("Content-Type", "text/html;charset=UTF-8");
    //2.指定输出的中文用的码表
    response.getOutputStream().write("你好".getBytes("UTF-8"));

字符串的String里面的getByte方法使用的码表是UTF-8,与tomcat没关系

实际开发时
//设置response使用的码表,以控制response以什么码表向浏览器写出数据
response.setCharacterEncoding(“码表”);
//指定浏览器以什么码表打开服务器发送的数据
response.setContentType(“text/html;charset=UTF-8”);

2.以附件形式下载文件

tomcat8.5之前需要设置2个响应头
1.设置下载文件的媒体;自行MIMEType
让浏览器知道下载格式
String mimgtype = this.getServletContext.getMIMEType(filename);
content-type:mimetype
2.设置下载头
按照附件的形式打开
content-dispositon:attachment; filename = "名字";

tomcat8.5之后只要2即可

1.直接以连接的形式下载

让tomcat的默认servlet去提供下载<br/>
<a href="download/aa.jpg">aa.jpg</a><br/>
<a href="download/bb.txt">bb.jpg</a><br/>
<a href="download/cc.rar">cc.jpg</a><br/>

原因是tomcat里有一个默认的Servlet—DefaultServlet
–>专门用于处理放在tomcat服务器上的静态资源

2.手动模式下载

String filename = “xjj.jpg”;
//设置响应头
response.setHeader(“Content-Disposition”,”attachmenet;filename=” + “xjj.jpg”);
//获取文件的真实路径
String realPath = this.getServletContext().getRealPath(filename);
//需要字节输入流
FileInputStream fis = new FileInputStream(realPath);
//将字节数据写给浏览器
ServletOutputStream out = response.getOutputStream();
//边读边写
int len;
byte[] buffer = new byte[8*1204];
while ((len = fis.read(buffer) )!= -1){
out.write(buffer,0,len);
}
out.close();
fis.close();

3.多种类型通用下载
在下载链接上加上?的操作,即是完成请求携带参数的操作
小姐姐
aaa.txt

String filename = request.getParameter(“filename”);
//设置响应头
response.setHeader(“Content-Disposition”,”attachmenet;filename=” + filename);
//获取文件的真实路径
String realPath = this.getServletContext().getRealPath(“download/”+ filename);
//需要字节输入流
FileInputStream fis = new FileInputStream(realPath);
//将字节数据写给浏览器
ServletOutputStream out = response.getOutputStream();
//边读边写
int len;
byte[] buffer = new byte[8*1204];
while ((len = fis.read(buffer) )!= -1){
out.write(buffer,0,len);
}
out.close();
fis.close();

4.下载带有中文名字的资源
响应头的编码只能通过转码进行传递
–> 需要进行编码处理
如果是IE或者Chrome,使用URLEncoding编码
如果是Firefox,使用Base64编码

代码案例

String filename = request.getParameter(“filename”);
//获取文件的真实路径
String realPath = this.getServletContext().getRealPath(“download/”+ filename);

String agent = request.getHeader("User-Agent");
if (agent.contains("Firefox")){
    filename = util.base64EncodeFileName(filename);
}else{
    filename = URLEncoder.encode(filename,"UTF-8");
}

//设置响应头
response.setHeader("Content-Disposition","attachmenet;filename=" + filename);
//需要字节输入流
FileInputStream fis = new FileInputStream(realPath);
//将字节数据写给浏览器
ServletOutputStream out = response.getOutputStream();
//边读边写
int len;
byte[] buffer = new byte[8*1204];
while ((len = fis.read(buffer) )!= -1){
    out.write(buffer,0,len);
}
out.close();
fis.close();

}

Base64编码 –> 可以做成工具类

public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return “=?UTF-8?B?” + new String(base64Encoder.encode(fileName.getBytes(“UTF-8”))) + “?=”;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

3.请求转发和重定向

API 介绍(设置)
void setHeader(String name, String value) 用给定名称和值设置响应头
void sendRedirect(String location) 用类设置重定向

使用location响应头实现跳转(重定向)
设置重定向响应头
resp.setHeader(“location”,”http://ntlias-stu.boxuegu.com/#/index“);
//设置状态码
resp.setStatus(302);
//简化模式
// resp.sendRedirect(“http://ntlias-stu.boxuegu.com/#/index“);

//设置编码方式
response.setContentType(“text/html;charset=UTF-8”);

    String userName = request.getParameter("username");
    String password = request.getParameter("password");
    if("admin".equals(userName)&&"123".equals(password)) {

// response.getWriter().write(“登录成功”);
//之前的写法
/* response.setStatus(302);
response.setHeader(“Location”,”login_sucess.html”);*/
//重定向写法:重新定向,参数即为跳转的位置
response.sendRedirect(“login_sucess.html”);

1.地址上显示的是最后的哪个资源的路径地址

请求转发模式:参数即跳转的位置
response.getRequestDispatcher(“login_sucess.html”).forward(request,response);
2.地址上显示的是请求servlet的地址

}else {
response.getWriter().write(“登录失败”);
}

请求转发和重定向区别

  1. 转发在一次请求中完成,重定向是两次请求
  2. 转发操作发生在服务器内部,重定向是浏览器执行操作
  3. 转发地址栏不变(只有一次请求,一个地址–服务器执行后续操作),重定向,地址栏变化(两次请求,两个地址 –第一次请求后,会返回302,以及一个地址,浏览器再根据此地址执行第二次访问)
  4. 转发可以在一次请求中共享数据,重定向不行(重定向两次请求)。
  5. 转发只能跳转自己项目的资源路径,重定向可以跳转其他资源路径
    6.转发效率高一些(1次请求),重定向效率低一些(2次请求)
  6. 转发可以使用上一次request对象,重定向不能使用上次的request对象,因为是两次不同的请求

    3秒钟之后跳转到其他页面
    案例分析

  7. 创建RefreshServlet
  8. 调用setHeader,设置消息头(”Refresh”,” 3;url=网址”)
    resp.setHeader(“Refresh”,”3;url=http://ntlias-stu.boxuegu.com/#/index“);

在访问登录页面时,需要生产验证码。从而防止用户使用程序恶意登录。

验证码
需求:
在访问登录页面时,需要生产验证码。从而防止用户使用程序恶意登录。

分析

3.4.3 代码实现

页面代码

用户名
密码
验证码
function changeImg(obj){ //修改修改src obj.src = "/day15/checkcode?xx="+new Date().getTime(); }

Servlet代码

@WebServlet(name = “CheckcodeServlet”,urlPatterns = “/checkcode”)
public class CheckcodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //  创建画布
    int width = 120;
    int height = 40;
    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    //  获得画笔
    Graphics g = bufferedImage.getGraphics();
    //  填充背景颜色
    g.setColor(Color.white);
    g.fillRect(0, 0, width, height);
    //  绘制边框
    g.setColor(Color.red);
    g.drawRect(0, 0, width - 1, height - 1);
    //  生成随机字符
    //  准备数据
    String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
    //  准备随机对象
    Random r = new Random();
    //  声明一个变量 保存验证码
    String code = "";
    //  书写4个随机字符
    for (int i = 0; i < 4; i++) {
        //  设置字体
        g.setFont(new Font("宋体", Font.BOLD, 28));
        //  设置随机颜色
        g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

        String str = data.charAt(r.nextInt(data.length())) + "";
        g.drawString(str, 10 + i * 28, 30);

        //  将新的字符 保存到验证码中
        code = code + str;
    }
    //  绘制干扰线
    for (int i = 0; i < 6; i++) {
        //  设置随机颜色
        g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

        g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
    }

    //  将验证码 打印到控制台
    System.out.println(code);

    //  将验证码放到session中
    request.getSession().setAttribute("code_session", code);

    //  将画布显示在浏览器中
    ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值