Servlet Response对象

Response

一、Response对象

1)Response理解

response是由tomcat创建的
response对象是来设置响应信息

2)Response的作用

针对页面发送的请求做出数据响应,向页面输出信息,包括文本、图片、视频等。
响应分类:
响应行、响应头、响应体。

1. 响应行

响应行中包含的信息:可以通过开发者模式F12-Network查看

image

由上图可知, 响应行中包含协议和状态码

状态码

响应状态码200表示响应成功,不同的状态码代表不同的含义。
1xx -信息,服务器收到请求,需要请求者继续执行操作
2xx -成功,操作被成功接收并处理
3xx -重定向,需要进一步的操作以完成请求
4xx -客户端错误,请求包含语法错误或无法完成请求
5xx -服务器错误,服务器在处理请求的过程中发生了错误

几中常见的状态码:
200 表示响应成功
302 表示资源重定向
304 表示缓存
404 表示请求资源找不到
出现的原因:
1.浏览器访问路径错误
2.tomcat服务未开启,项目没有部署到tomcat服务器中
3.你要访问的页面资源在WEB-INF文件夹中,无法访问
500 表示服务器端代码出错,可以通过控制台查看异常消息。看异常(1.浏览器上的异常 2.idea控制台上的异常)

2. 设置响应头

当我们在浏览器中打开network工具时,每一次的请求响应数据,都可以被捕捉到,而在内容中Response Headers 中的内容就是当前这一次请求响应的响应头信息。

image

重要的响应头信息:
1、Content-Type: 响应内容的MIME类型 (text/html;charset=utf-8)
MIME类型:大类型/小类型   
例如:text/html     image/jpg   video/mp4 (只有指定为文本类型时才需要设置编码格式)
具体的格式可以通过 https://tool.oschina.net/commons 查询
2、Content-Disposition:告诉浏览器以下载方式打开数据(做文件下载时使用)
3、Location: 页面跳转
4、refresh:	页面刷新或者指定时间后跳转到某个页面

image

image

image

设置响应头
设置响应头信息可以通过以下方法:
response.setHeader("Content-Type", "text/html;charset=utf-8");

案例

package com.offcn.web;

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("/responseHeader")
public class ResponseHeaderServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置一个自定义的头信息
        //resp.setHeader("name","jack");

        //设置头信息
        //resp.setHeader("content-type","text/html;charset=utf-8");
        //resp.setContentType("text/html;charset=utf-8");  设置响应内容格式
        //resp.getWriter().print("<a href=''>杰克</a>");

        //定时跳转到指定的资源
        //resp.setHeader("refresh","3;url='http://www.baidu.com'");
    }
}

3. 设置响应体(重要)

响应的数据就是响应体。响应对象response在返回数据、响应数据的时候,会将一些HTML、text、流数据等信息通过响应主体返回给页面,而响应体绝大多数都是文本类型。

响应数据需要通过流来进行数据传输,而response自带的流有两个:
response.getWriter() ==> PrintWriter 输出文本信息
response.getOutputStream ==> ServletOutputStream 输出字节信息,比如图片、音频、视频

案例实现:

package com.ujiuye.response;

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.OutputStream;

@WebServlet("/responseBody")
public class ResponseBody extends HttpServlet {

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  
  //响应文本信息
  response.getWriter().print("liuyan");
  }
  }

案例: 响应表格

案例实现:

package com.ujiuye.response;

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("/table")
public class TableServlet extends HttpServlet {

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  request.setCharacterEncoding("utf-8");
  response.setContentType("text/html;charset=utf-8");
  //响应表格信息
  PrintWriter writer = response.getWriter();
  writer.print("<table border='1px' width='300px' align='center'>");
  writer.print("<tr align='center'><th>学号</th><th>姓名</th><th>地址</th></tr>");
  writer.print("<tr align='center'><td>1001</td><td>柳岩</td><td>湖南</td></tr>");
  writer.print("<tr align='center'><td>1002</td><td>热巴</td><td>新疆</td></tr>");
  writer.print("<tr align='center'><td>1002</td><td>苍老湿</td><td>岛国</td></tr>");
  writer.print("</table>");
}
}

实现效果:

image

案例实现-响应js脚本

package com.offcn.web;

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;
import java.io.PrintWriter;

@WebServlet("/responseBody")
public class ResponseBodyServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setHeader("content-type","text/html;charset=utf-8");
        //拿输出流 (1.纯文本的  2.二进制)
        PrintWriter printwriter = resp.getWriter();  //可以输出纯文本
        
        //向浏览器响应一个弹窗  alert
        printwriter.print("<script>alert('今天星期三');location.href='http://www.baidu.com'</script>");
      
    }
}

4. 重定向

① 理解

重定向是客户端行为,当客户端浏览器向AServlet发送一个请求,经过处理后向客户端做出响应,这个响应就是向服务器再次发送新的请求,去请求BServlet,而这个新请求的地址将为浏览器做出第二次响应,此时浏览器地址栏会发生改变,由于一次请求/响应结束后,request对象会自动销毁,所以两次请求的request对象并非同一个,所以两次请求域中的数据信息不会共享。由此可见,重定向是做了两次请求和响应。

② 实现

案例:在OneServlet中向request作用域中保存信息并以重定向的方式跳转到TwoServlet,此时,在TwoServlet中就无法获取到先前存到域对象中的值了,并且地址栏发生了改变。

案例实现:

AServlet

package com.offcn.web;

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("/AServlet")
public class AServlet  extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("a","10"); //使用request作用域存值
        //转发
        //req.getRequestDispatcher("/BServlet").forward(req,resp);
        //重定向
        resp.sendRedirect("/BServlet");
    }
}

BServlet

package com.offcn.web;

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("/BServlet")
public class BServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object a = req.getAttribute("a");
        resp.getWriter().print(a);
    }
}

③ 特点

重定向的特点:

  1. 重定向发生在浏览器和服务器之间
  2. 重定向的过程url地址发生变化
  3. 重定向发生至少两次请求中
  4. 重定向访问不到WEB-INF的资源
  5. 重定向可以访问当前应用外的资源
  6. 重定向一般使用绝对路径(访问外网资源时)

注意:一般选择了request请求域,就不会选择重定向跳转。

image

二、ServletContext对象

1)ServletContext理解

当 Tomcat 启动时,Tomcat 会为每个 Web 应用创建一个唯一的 ServletContext 对象代表当前的 Web 应用,该对象封装了当前 Web 应用的所有信息。可以利用该对象获取整个Web 应用程序的初始化信息、读取资源文件等。使用ServletContext作用域存储的数据可以被所有Servlet共享.

2)ServletContext的获取

获取方式有两种:

  1. request.getServletContext();
  2. this.getServletContext();

3)ServletContext作用域

域对象:共享数据

ServletContext是一个全局作用域对象,在整个Web应用内所有用户所有请求的数据(周期长)。

ServletContext作用域:

  • 在MyFirstServlet中存值
package com.ujiuye.scope;

import javax.servlet.ServletContext;
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("/myFirstServlet")
public class MyFirstServlet extends HttpServlet {

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  //向servletContext作用域中存储数据
  ServletContext servletContext = request.getServletContext();
  servletContext.setAttribute("name", "苍老湿");
}
}
  • 在MySecondServlet中取值
package com.ujiuye.scope;

import javax.servlet.ServletContext;
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("/mySecondServlet")
public class MySecondServlet extends HttpServlet {

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  //从servletContext作用域中取出数据
  ServletContext servletContext = request.getServletContext();
  //获取数据
  String name = (String) servletContext.getAttribute("name");
  System.out.println(name);
  //移除数据
  servletContext.removeAttribute("name");
  //获取数据
  name = (String) servletContext.getAttribute("name");
  System.out.println(name);
}

}

总结:
request作用域仅限于一次请求范围内可以实现信息的共享,一次请求结束,request对象消失,内部的值也随之消失,周期短,但效率高,不会占用过多的内存资源;而ServletContext是一个全局作用域对象,整个web项目的所有组件(Servlet、jsp)共享信息,周期长,可用来保存所有web组件之间需要共享的信息。它在tomcat服务器启动时创建,关闭时销毁。

4)案例:文件下载

文件下载分为两种下载方法:

  1. 超链接下载: 使用a标签可以下载文件,但具有局限性,如果能被浏览器识别的文件格式会直接打开显示,如果浏览器无法识别,则进行下载。
  2. 后台下载
① 超链接下载

案例实现:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>下载</title>
</head>
<body>
<!-- 使用超链接方式提供下载链接 -->

<a href="1.mp3">下载音乐</a><br>
<a href="020.mp4">下载视频</a><br>
<a href="msl.jpeg">下载图片</a><br>
<a href="tomcat.zip">下载文件</a><br>
</body>
</html>
② 后台下载

页面实现:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

	<h2>后台形式下载</h2>
	<p><a href="downLoad?fileName=a.txt">a.txt</a></p>
	<p><a href="downLoad?fileName=liutao.jpg">liutao.jpg</a></p>
	<p><a href="downLoad?fileName=c3p0-0.9.2-pre5.jar">c3p0-0.9.2-pre5.jar</a></p>
	<p><a href="downLoad?fileName=day11_servlet.doc">day11_servlet.doc</a></p>
	<p><a href="downLoad?fileName=day11_servlet.zip">day11_servlet.zip</a></p>
	<p><a href="downLoad?fileName=柳岩.jpg">柳岩.jpg</a></p>
</body>
</html>

案例实现:

package com.offcn.web;

import javax.servlet.ServletContext;
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;
import java.io.InputStream;


@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
   @Override
   protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //先获取传过来的参数 name
       String name = req.getParameter("name");
       //设置响应头
       //跟浏览器之间的数据交互格式设置为以下载的方式打开数据.
       //浏览器能够识别的编码 西欧码  iso-8859-1  目前项目的默认编码是utf-8
       resp.setHeader("content-disposition","attachment;filename="+new String(name.getBytes("utf-8"),"iso-8859-1"));
       //获取整个web应用的唯一对象 ServletContext
       ServletContext servletContext = req.getServletContext();
       //获取文件
       InputStream is = servletContext.getResourceAsStream(name);
       //输出文件数据 响应体响应数据 (1.纯文本的输出流 PrintWriter   2.输出二进制文件 ServletOutputStream )
       ServletOutputStream os = resp.getOutputStream();
       //第一种输出
//        byte[] b = new byte[is.available()];
////        is.read(b);  //读取数据,把数据存放到byte数组中
//        os.write(b);
       //第二种输出
       byte[] b = new byte[2048];
       int len = -1;
       while((len= is.read(b))!=-1){
           os.write(b,0,len);
       }
       os.close();
       is.close();
   }
}

三、生成图片验证码

通过第三方jar包 ValidateCode.jar ,生成图片验证码

代码

ValidateCodeServlet

@WebServlet("/validateCode")
public class ValidateCodeServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //指定验证码的参数
        ValidateCode validateCode = new ValidateCode(120,30,4,0);
        //获取验证码上的字符
        String code = validateCode.getCode();
        System.out.println(code);
        //生成验证码图片响应到浏览器
        validateCode.write(resp.getOutputStream());
    }
}

valid.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>验证码</title>
</head>
<body>
<form>
    <input type="text" />  <img src="validateCode" onclick="changeCode()"/>
</form>
</body>
<script src="js/jquery-1.8.3.js"></script>
<script>
    function changeCode(){
        $("img").prop("src","validateCode?a="+Math.random());
    }
</script>
</html>

四、文件上传

1.准备步骤

1-1.准备html

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadFile" /> <br>
    <input type="submit" values="上传" />
</form>

//表单需要提供multipart/form-data ,把表单的数据按照两个部分传递.
//表单如果需要实现文件上传,提交方式只能是post.
//表单需要提供一个用于上传文件的控件   <input type="file" name="uploadFile" />

1-2.准备Servlet

package com.offcn.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;


@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //允许上传的格式
        List<String> list = Arrays.asList(".jpg", ".jpeg", ".png", ".gif", ".bmp");
        //允许最大图片大小
        long max = 1024*300;
        //处理请求的乱码
        req.setCharacterEncoding("utf-8");
        //处理响应的乱码
        resp.setContentType("text/html;charset=utf-8");
        Part uploadFile = req.getPart("uploadFile");
        //获取文件名
        String fileName = uploadFile.getSubmittedFileName();
        // xx.jpg        xx  .jpg  截取文件扩展名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));

        //如果只能上传图片怎么处理?
        if(list.contains(suffixName)) {
            // 类似  101156789.jpg
            fileName = System.currentTimeMillis() + suffixName;
            //获取文件大小
            long size = uploadFile.getSize();
            if(size<=max){
                //把文件信息保存到服务器磁盘上
                uploadFile.write("F:\\upload\\" + fileName);
            }else{
                //上传失败
                resp.getWriter().print("文件过大!!请重新<a style='color:blue' href='upload.html'>上传</a>");
            }
        }else{
            //上传失败
            resp.getWriter().print("请重新选择合适格式图片<a style='color:blue' href='upload.html'>上传</a>;允许的格式为"+list);
        }
    }
}

posted @ 2021-09-11 17:19  HJ0101  阅读(191)  评论(0)    收藏  举报