ServletContext&Response

来源:互联网 发布:南昌淘宝学校在哪里 编辑:程序博客网 时间:2024/06/05 20:07

ServletContext&Response

  • 案例一:统计一下网站被访问的总次数

  • 案例二: 文件下载

  • 案例三: 生成验证码

  • 使用response成功发送中文数据

  • 使用response可以设置响应头

案例一:统计一下网站被访问的总次数.

一,需求分析

img

  • 在页面中显示您是第x位访问的用户.

二,技术分析

1.servletContext
1.1概述
  • 服务器为每一个应用都创建了一个servletContext。servletContext属于整个应用的,不局限于某个servlet。
  • 可作为域对象存取数据,进行数据共享 .
1.2应用场景
  • 聊天室
  • 统计网站访问次数
1.3作为域对象存取数据

​ 在当前应用,使多个Servlet共享数据

  • getAttribute(String name) ;向ServletContext对象的map取数据

  • setAttribute(String name, Object object) ;从ServletContext对象的map中添加数据

  • removeAttribute(String name) 根据name去移除数据

三,思路分析

  • 在CountServlet的init方法里面,存储登录次数(0次)
  • 在CountServlet的doGet()方法里面,取出值+1,再存储
  • 在ShowServlet里面取出值展示

四,代码实现

五,总结

1.servletContext
1.1作为域对象存取值
  • getAttribute(String name) ;向ServletContext对象的map取数据
  • setAttribute(String name, Object object) ;从ServletContext对象的map中添加数据
  • removeAttribute(String name) ;根据name去移除数据
1.2获得文件类型
  • getMimeType(String file)
1.3获得全局初始化参数
  • String getInitParameter(String name) ; //根据配置文件中的key得到value
1.4获取web资源路径(重点
  • String getRealPath(String path);根据资源名称得到资源的绝对路径.
  • getResourceAsStream(String path) ;返回指定路径文件的流

注意: path:直接从项目的根目录开始写

​ eg:

        //getRealPath的路径已经到了项目的根目录        //String realPath = servletContext.getRealPath("/WEB-INF/classes/a.txt");        //System.out.println(realPath);        //InputStream is = new FileInputStream(realPath);        //路径已经到了项目的根目录        //InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/a.txt");        servletContext.getResourceAsStream("/file/b.txt");

案例二:完成文件下载

一需求分析

  • 创建文件下载的列表的页面,点击列表中的某些链接,下载文件.

img

二,技术分析

1. HttpServletResponse对象

​ 在Servlet API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为状态行、响应头、响应体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应头、响应体的方法。

1.1响应行: 协议版本 状态码 状态描述

img

​ 常用的状态码:

​ 200:成功

​ 302:重定向,需要和一个响应头

​ 304:访问缓存

​ 404:客户端错误

​ 500:服务器错误

1.2响应头: key:value; 这个value可以有多个

​ 一个key对应一个value

img

​ 一个key对应多个value

img

​ 常用的响应头

​ Refresh:定时跳转

​ Location:重定向(地址)

​ Content-Disposition:设置文件下载时候的头

​ Content-Type:设置响应内容的MIME类型

1.3响应体

img

2.文件下载
2.1什么是文件下载

​ 将服务器上已经存在的文件,输出到客户端浏览器.

2.2文件下载的方式
  • 第一种:超链接方式(不推荐)

    链接的方式:直接将服务器上的文件的路径写到href属性中.如果浏览器不支持该格式文件,那么就会提示进行下载, 如果 浏览器支持这个格式的文件,那么直接打开

  • 第二种:手动编码方式(推荐)

    手动编写代码实现下载.无论浏览器是否识别该格式的文件,都会提示下载.

2.3手动编码方式要求

设置两个头和一个流

​ 设置的两个头:

    1.Content-Dispostion:浏览器识别该格式文件,提示下载.
//告诉浏览器去下载response.setHeader("Content-Disposition", "attachment;filename="+filename);
    2.Content-Type:文件类型.(MIME的类型)  
//response.setHeader("Content-Type", mimeType);response.setContentType(mimeType);

​ 设置一个流:

     获得要下载的文件的输出流(字节流).
//得到输出流OutputStream os = response.getOutputStream();

三,思路分析

1.超链接方式

  • 创建资源下载页面。
  • 设置超链接,href值设置资源的路径

2.编码方式

  • 创建资源下载页面
  • 设置超链接,把文件名提交到downloadServlet中,设置两头一流,进行下载

四,代码实现

        String fileName = request.getParameter("fileName");        System.out.println("fileName=" + fileName);        // 设置两头一流(文件下载类型和指示客户端下载文件)        // 告诉浏览器要下载        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);        // 告诉浏览器的文件类型        String type = getServletContext().getMimeType(fileName);        // response.setContentType(type);        response.setHeader("Content-Type", type);        // 设置文件的输入流        String realPath = getServletContext().getRealPath("/download/" + fileName);        InputStream is = new FileInputStream(realPath);        OutputStream os = response.getOutputStream();        byte[] b = new byte[1024];        int len = 0;        while ((len = is.read(b)) != -1) {            os.write(b, 0, len);        }

五,总结

1.下载中文的文件

​ 中文文件在不同的浏览器中编码方式不同:火狐是Base64编码,其它浏览器是URL编码

    //获得浏览器信息    String agent = request.getHeader("User-Agent");    if(agent.contains("Firefox")){            // 火狐浏览器            filename = base64EncodeFileName(filename);        }else{            // IE,其他浏览器            filename = URLEncoder.encode(filename, "UTF-8");        }    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);        }    }
2 Response其他操作
2.1定时刷新
response.setHeader("refresh","秒数;url=跳转的路径"); 几秒之后跳转到指定的路径上
2.2重定向(重要)

img

  • 两次请求
  • 地址栏变了
2.3 向页面输出内容:

img

​ 页面输出只能使用其中的一个流实现,两个流是互斥的.

  • 解决字符流输出中文乱码问题
    //设置缓冲器的编码    response.setCharacterEncoding("utf-8");    //告知浏览器用什么编码解析    response.setHeader("Content-Type", "text/html;charset=utf-8");    //或者,是前面两句的封装    response.setContentType("text/html;charset=utf-8");    response.getWriter().println("你好!")
  • 使用字节输出流输出中文乱码问题
//设置浏览器打开方式response.setHeader("Content-type", "text/html;charset=utf-8");//得到字节输出流ServletOutputStream outputStream = response.getOutputStream();outputStream.write("你好".getBytes("utf-8"));// 使用平台的默认字符(utf-8)集将此 String 编码为 byte 序列
  • 这两个流互斥,两个不能同时使用

案例三:验证码

一,需求分析

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

img

二,技术分析

img

三,思路分析

  • 修改login.html页面,确定验证码图片显示的位置
  • 编写CodeServlet实现类

四,代码实现

生成验证码的Servlet:

public class CodeServlet extends HttpServlet {    private static final long serialVersionUID = 1L;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws           ServletException, IOException {        //参数1:图片的宽度 参数2:图片的高度  参数3:验证码的个数  参数4:干扰线的个数        ValidateCode vc = new ValidateCode(150, 50, 4, 9);        vc.write(response.getOutputStream());//使用响应字节流把图片响应给客户端浏览器    }    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        doGet(request, response);    }}

五,扩展

  • 添加点击图片,更换验证码
<script>    function changeImg(){        //获得img标签对象        var imgObj =  document.getElementById("imgId");        console.log(new Date().getMilliseconds());        imgObj.src = "/web16Response/code?aa="+new Date().getMilliseconds();    }</script>