JavaWeb = ServletContext,Response详解

一。ServletContext对象

1.ServletContext概述

ServletContext 是一个容器(域对象)可以存储键值对数据( String key,Object value ),保存在 ServletContext 中的
数据不仅可以提供给所有的 servlet 使用,而且可以在整个项目范围内使用(有些框架的过滤器、监听器也可以使用
ServletContext )。
 
web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象
 
它代表:当前web项目
 

作用:

  1. 域对象(共享数据)

  2. 获取资源在服务器的真实地址

  3. 获取全局的配置参数

  4. 获取文件MIME类型

2.获取ServletContext对象

1. 通过request对象获得
		ServletContext sc = request.getServletContext();
		
2. 继承HttpServlet后,可以直接调用
		ServletContext sc = getServletContext();

3.域对象(共享数据)

在同一个项目范围内,共享数据(多个servlet都可以获取)

相关APi

1. 存储数据
		void setAttribute(String name,Object value)
2. 获取数据
		Object getAttribute(String name)
3. 删除数据
		void removeAttribute(String name)

0. ServletContext getServletContext() 
获取ServletContext对象

1. void setAttribute(String name, Object object) 
往servletcontext容器中存入数据,name为数据名称,object为数据的值 

2. Object getAttribute(String name) 
从ServletContext中获取数据,根据指定的数据名称 

3. void removeAttribute(String name)
 从ServletContext中移除数据,根据指定的数据名称
@WebServlet("/OneServlet")
public class OneServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 向servletContext域存数据....
        ServletContext sc1 = request.getServletContext();
        ServletContext sc2 = getServletContext();
        sc1.setAttribute("user", "ack");
        System.out.println("OneServlet存了数据。。。");
    }

}
@WebServlet("/TwoServlet")
public class TwoServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 从servletContext域获取数据
        String user = (String) request.getServletContext().getAttribute("user");
        System.out.println("TwoServlet获取数据:"+user);
    }

}

4.ServletContext生命周期

1. 何时创建?
        项目加载时,创建
2. 何时销毁?
        项目卸载时,销毁

3. 作用范围?
        与项目共存亡(多个servlet都可以操作它)

保存在 ServletContext 中的数据是项目全局共享的数据

5.获取资源在服务器的真实地址

相关api
1. getRealPath(String path) 
获取WEB项目的资源文件路径 

2. getResourceAsStream(String path) 
根据WEB项目的文件获取流 

3. getInitParameter(String name) 

获取初始化参数

可实现web项目的移植型,动态获取文件真实路径

@WebServlet("/RealpathServlet")
public class RealpathServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取c.jpg 文件真实路径
        String carPath = request.getServletContext().getRealPath("/img/c.jpg");
        System.out.println(carPath);
        // 获取web.xml 文件真实路径
        String webPath = request.getServletContext().getRealPath("/WEB-INF/web.xml");
        System.out.println(webPath);
    }

}

6.获取全局配置参数

读取web.xml配置文件中<context-param>标签信息,实现参数和代码的解耦(多个servlet都可以获取)

<?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_3_1.xsd"
         version="3.1">
    <!--全局配置参数:所有的servlet都可以读取...-->
    <context-param>
        <param-name>encode</param-name>
        <param-value>UTF-8</param-value>
    </context-param>
</web-app>
@WebServlet("/ContextPathServlet")
public class ContextPathServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取全局参数
        String value = request.getServletContext().getInitParameter("encode");
        System.out.println("全局配置参数:"+value);
    }

}

7.获取文件的MIME类型

在互联网通信中定义的一种文件数据类型

格式:大类型/小类型 例如:text/html image/jpeg

<a href="/servletContext/MimeServlet?filename=la.avi">获取文件的mime类型</a><br>

@WebServlet("/MimeServlet")
public class MimeServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取指定文件的mime类型
        // 获取请求参数
        String filename = request.getParameter("filename");
        // 获取文件的mime类型
        String mimeType = request.getServletContext().getMimeType(filename);
        response.getWriter().write(filename + "---" + mimeType);
    }

}

8.统计网站访问次数

有一个 servlet(countServlet), 每访问一次这个 servlet, 将访问的次数 +1,
当我们访问另一个 servlet(showServlet), 展示访问 CountServlet 的次数

需求如下图所示:

@WebServlet(value = "/CountServlet", loadOnStartup = 4) // 服务器启动时,创建此servlet对象
public class CountServlet extends HttpServlet {

    @Override
    public void init() throws ServletException {
        getServletContext().setAttribute("count", 0);
    }

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置response响应编码
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("<h1>博客网站</h1>");

        // 用户每次访问,从域中取出,加1,再存进去
        ServletContext servletContext = request.getServletContext();
        // 从域中取出
        Integer count = (Integer) servletContext.getAttribute("count");
        // 加1
        count++;
        // 再存进去
        servletContext.setAttribute("count", count);

        response.getWriter().write("<div>你是,第" + count + "位访问</div>");
    }

}


@WebServlet(urlPatterns = "/bokeCountServlet",loadOnStartup = 4)
public class bokeCountServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        ServletContext servletContext =getServletContext();
        servletContext.setAttribute("bokeCount",0);
    }

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

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("<h1>wsl的博客网站</h1>");
        ServletContext servletContext =request.getServletContext();
        Integer bokeCount = (Integer) servletContext.getAttribute("bokeCount");
        bokeCount++;
        servletContext.setAttribute("bokeCount",bokeCount);
        response.getWriter().write("<div>博客访问的次数:"+bokeCount+"次</div>");
    }
}

二.Response对象

1.概述:

  • response对象表示web服务器给浏览器返回的响应信息

  • 作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息

2.Response体系结构

response 对象原形是 javax.servlet.http.HttpServletResponse ,它继承自 javax.servlet.ServletResponse, 我们
先来看下官方文档截图:
HttpServletResponse 对象封装了向客户端发送数据、发送响应头,发送响应状态码的方法。开发人员可以使用
HttpServletResponse ,才能给浏览器发送数据。

3.Response操作响应行

响应行的组成:
 
响应行是 http 响应内容的第一行。
响应行一般数据为: HTTP/1.1 200 tomcat8.5 ) 或者 HTTP/1.1 200 OK tomcat7
 
响应行分为三个部分:
 
HTTP/1.1 :协议版本
200 :响应状态码
OK :对响应状态码的解释
 

demo:

* 格式
	 	协议/版本号 状态码
	 
* 例如
		HTTP/1.1 200
		
* API
	1. 设置状态码
			void setStatus(int sc)  
void setStatus(int sc) 
设置响应的状态代码(一般用来设置 1xx 2xx 3xx) 
void sendError(int sc) 
设置响应的状态代码(一般用来设置 4xx 5xx)
注意:
状态码的一般不需要我们手动设置

状态码:

以上即是我们常用的响应的状态码。

响应头:

常见的响应头介绍:

API介绍:

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

demo

* 格式
		响应头名称:响应头的值
		
* 例如
		Location:http://www.wsl.cn
		
* API
	1. 设置指定头名称和对应的值
			void setHeader(String name, String value) 

响应体

API介绍

ServletOutputStream getOutputStream() 
获取字节输出流
 PrintWriter getWriter() 
获取字符输出流

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

demo案例:

(1).重定向:用户访问AServlet后,服务器告诉浏览器重定向到BServlet

两种方法:

* 方式一
	// 1.设置状态码
		response.setStatus(302);
	// 2.设置响应头 Location
		response.setHeader("Location","重定向网络地址");
		
		
* 方式二
	// 1.response这哥们封装专门处理重定向的方法
		response.sendRedirect("重定向网络地址");

重定向特点:

1. 地址栏会发生改变

2. 重定向是二次请求

3. 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源...

4. 不能使用request域共享数据

@WebServlet("/AServlet")
public class AServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("AServlet执行了....");
       /* // 1.设置状态码
        response.setStatus(302);
        // 2.设置响应头 Location
        response.setHeader("Location","/dresponse/BServlet");*/

        // 1.response封装专门处理重定向的方法
        response.sendRedirect("http://www.baidu.cn");
    }

}
@WebServlet("/BServlet")
public class BServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("BServlet执行了....");
    }

}

总结:

转发和重定向的区别:

1. 哪个对象
	转发(request对象的方法)		
		request.getRequestDispatcher("/bServlet").forward(request,response);
	重定向(response对象的方法)		
		response.sendRedirect("/dresponse/bServlet");
		
2. 几次请求
	转发
		地址栏: 没有改变
		浏览器: 发了一次请求
		服务器: 只有一对请求和响应对象
		发生的位置: 服务器
	重定向
		地址栏: 发生了改变
		浏览器: 发了两次请求
		服务器: 有两对请求和响应对象
		发生的位置: 浏览器
			
3. 小结
	写法 
		转发("/servlet资源路径") 服务器内部行为
		重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为
	使用场景
		如果需要传递数据,使用转发
		如果不需要传递数据,使用重定向

(2)响应定时刷新

在当前页面停留3秒钟之后 ,跳转到baidu

分析:

1. 通过response设置响应头 Refresh
        response.setHeader("Refresh","间隔时间(秒);跳转页面");

@WebServlet("/RefreshServlet")
public class RefreshServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. 通过response设置响应头 Refresh
        response.setHeader("Refresh", "3;http://www.baidu.cn");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("操作成功,3秒后跳转到百度...");
    }

}

(3)中文响应

即在页面响应中返回中文信息

1. 通过response获取字符输出流
        PrintWriter pw = response.getWriter();
        
2. 通过字符输出输出文本
        pw.write("中文....");

解决中文乱码问题:

1. 指定服务器响应编码方式
		response.setCharacterEncoding("GBK");
		
2. 统一浏览器和服务器编码
		response.setContentType("text/html;charset=utf-8"); 
@WebServlet("/EncodeServlet")
public class EncodeServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //  指定服务器响应编码方式
        // response.setCharacterEncoding("UTF-8");
        // 统一浏览器和服务器编码
        response.setContentType("text/html;charset=utf-8");

        // 1. 通过response获取字符输出流
        PrintWriter pw = response.getWriter();
        // 2. 通过字符输出输出文本
        pw.write("中文....");
    }

}

三.案例分享

1.生成验证码:

/*
	
 */
@WebServlet("/CheckcodeServlet")
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);
	}

}




<img src="/dresponse/CheckcodeServlet" alt="servlet随机验证码" id="img1"> <br>
<script>
    // 给图片绑定一个点击事件
    document.getElementById('img1').οnclick=function () {
        // 重置src路径,重写发送请求
        this.src='/dresponse/CheckcodeServlet?'+new Date().getTime(); // 后面加一个毫秒值的时间戳,否则浏览器不刷新
    }
</script>

2.文件下载:点击页面链接,下载

(1)使用链接下载文件

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>donload.html</title>

</head>
<body>
<h3>文件下载</h3>
<h5>超链接下载</h5>
<a href="/dresponse/download/demo.docx">word文档</a><br>
<a href="/dresponse/download/abc.jpg">图片下载</a><br>
<a href="/dresponse/download/test.zip">压缩包下载</a><br>
<h5>servlet下载</h5>
</body>
</html>

缺点:

  1. 浏览器可识别的媒体类型,是直接打开而不是下载...

  2. 不能判断用户是否登录等,进行限制

(2)使用Servlet下载文件:(重要)

分析:

1. 被下载文件的字节输入流
		FileInputStream
		
2. response字节输出流
		ServletOutputStream
		
3. 告知客户端下载文件的MIME类型(最新的浏览器此步骤可以省略....)
		Content-Type:MIME类型
		
4. 告知浏览器以附件的方式保存
		Content-Disposition:attachment;filename=文件名
			attachment 附件
			filename=文件名

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>d7</title>
</head>
<body>
<h1>博客访问次数</h1>
<h3>
    <a href="/d7/bokeCountServlet">博客访问</a>
</h3>

<h1>验证码</h1>
<img src="/d7/verfityCodeServlet" alt="验证码" id="verfityCode">
<h1>下载</h1>
<h3><a href="/d7/DownServlet?filename=ac.jpg">美女图片下载</a></h3>
<h3><a href="/d7/DownServlet?filename=第九套广播体操.gif">第九套广播体操图片下载</a></h3>
<h3><a href="/d7/DownServlet?filename=第九套广播体操.mp4">第九套广播体操视频下载</a></h3>

<script>
    document.getElementById("verfityCode").onclick = function () {
        this.src="/d7/verfityCodeServlet?"+new Date().getTime();
    }
</script>
</body>
</html>
@WebServlet("/DownServlet")
public class DownServlet extends HttpServlet {

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.获取请求文件名
        String filename = request.getParameter("filename");
        // 2.获取文件真实路径,封装到字节输入流
        ServletContext servletContext = request.getServletContext();
        String realPath = servletContext.getRealPath("/download/" + filename);
        FileInputStream in = new FileInputStream(realPath);
        // 3.告诉浏览器mime类型
        String mimeType = servletContext.getMimeType(filename);
        response.setContentType(mimeType);

        // 4.告诉浏览器以附件方式保存
        // 解决中文乱码和浏览器兼容性
        String userAgent = request.getHeader("user-agent");
        // 调用工具类处理
        filename = DownLoadUtils.getName(userAgent, filename);

        response.setHeader("content-disposition", "attachment;filename=" + filename);

        // 5.获取字节输出流
        ServletOutputStream out = response.getOutputStream();

        // 6.io流的拷贝
    //    byte[] b = new byte[4096];// 4kb
    //    int len = -1;
   //     while((len = in.read(b))!=-1){
   //         out.write(b, 0, len);
   //     }
        // 6.io流的拷贝
          //下载:利用工具类:Hutool工具类
        IoUtil.copy(fileInputStream,outputStream);

        // 7.释放资源
        out.close(); // out流对象,可以交给tomcat关闭
        in.close();
    }

}

注意:中文乱码问题:

* 如果该下载文件名是中文的话,会出现乱码...
	谷歌和绝大多数的浏览器是通过 url编码
		URLEncode() 编码
		URLDecode() 解码
	火狐浏览器   base64编码
	
* 所以需要考虑浏览器兼容性问题....
	提供了判断浏览器不同编码的工具类直接使用即可....

如下:


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import sun.misc.BASE64Encoder;

public class DownLoadUtils {
	public static String getName(String agent, String filename) throws UnsupportedEncodingException {
		if (agent.contains("Firefox")) {
			// 火狐浏览器
			BASE64Encoder base64Encoder = new BASE64Encoder();
			filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
		} else {
			// 其它浏览器
			filename = URLEncoder.encode(filename, "utf-8");
		}
		return filename;
	}
}


完整代码:
@WebServlet("/DownServlet")
public class DownServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求文件名
        String filename = request.getParameter("filename");
        // 2.获取文件真实路径,封装到字节输入流
        ServletContext servletContext = request.getServletContext();
        String realPath = servletContext.getRealPath("/down/" + filename);
        System.out.println("====0000="+realPath);
        System.out.println("======1111=="+servletContext.getContextPath());
        FileInputStream fileInputStream = new FileInputStream(realPath);
        // 3.告诉浏览器mime类型
        String mimeType = servletContext.getMimeType(filename);
        response.setContentType(mimeType);

        String header = request.getHeader("user-agent");
        filename= DownLoadUtils.getName(header, filename);
        response.setHeader("content-disposition","attachment;filename=" + filename);
        //
        ServletOutputStream outputStream = response.getOutputStream();
        //下载
        IoUtil.copy(fileInputStream,outputStream);
        outputStream.close();
        fileInputStream.close();
    }

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

学习参考:

ServletContext

ServletContext的使用

ServletConfig

Response详解

发布了141 篇原创文章 · 获赞 27 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u010581811/article/details/105587564