Javaweb-ServletContext&Response

目录

ServletContext

ServletContext对象的作⽤

如何获取ServletContext对象

代码演示

作用一:获取WEB应用程序的初始化参数

作用二:获取WEB应用程序下任意资源的绝对路径

作用三:ServletContext作为域对象

案例 统计访问的次数

Servlet

 注解开发取代web.xml

注解servlet配置

 

Response对象

Response设置响应行

Response设置响应头

Response设置响应体

字节流向浏览器写数据

重定向

重定向的代码实现

案例 文件下载

案例 验证码


ServletContext

Tomcat中的项目也称为应用程序,Java思想中,万物皆对象,那web应用程序也可以看为一个对象,在Java Web开发中,提供了一个对象“ServletContext”来表示应用程序。

说明:
1. 在⼀个 WEB 应⽤程序中,只能存在⼀个 ServletContext 对象。
2. 每个应⽤程序 , 都有它⾃⼰所对应的⼀个 ServletContext 对象。
3. 在服务器启动的时候,为每个 web 应⽤程序创建⼀个单独的 ServletContext 对象。
4. ServletContext 是接⼝ , 此接⼝的实现类是 tomcat 引擎提供
 

ServletContext对象的作⽤

  • 获取WEB应⽤程序的初始化参数
  • 获取WEB应⽤程序下任意资源的绝对路径
  • ServletContext作为域对象,存储数据

如何获取ServletContext对象

⼀个 web 应⽤程序只有⼀个 ServletContext 对象
 
⽅式 1 :通过 ServletConfig 接⼝获取,它提供了⽅法 getServletContext()
public interface ServletConfig {
    ServletContext getServletContext();
 
}
⽅式 2 :通过继承的 HttpServlet 类的⽗类 GenericServlet 获取, GenericServlet类 提供了⽅法getServletContext() ,下⾯是源码分析
class Context1Servlet extends HttpServlet {}
     ↓
     ↓
public abstract class HttpServlet extends GenericServlet{}
     ↓
     ↓
public abstract class GenericServlet implements Servlet,ServletConfig,Serializable {
     //⽤transient关键字标记的成员变量不参与序列化过程。
     private transient ServletConfig config;
 
     public ServletConfig getServletConfig() {
         return this.config;
     }
 
     public ServletContext getServletContext() {
         return this.getServletConfig().getServletContext();
     }
     //省略其他
}

代码演示

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     //⽅式1:通过ServletConfig对象获取,它提供了⽅法 getServletContext()
     ServletConfig config = super.getServletConfig();
     ServletContext servletContext = config.getServletContext();
     System.out.println("servletContext = "+servletContext);
     //⽅式2:通过继承的HttpServlet类的⽗类GenericServlet获取, GenericServlet类提供了⽅法 getServletContext()
     ServletContext servletContext2 = super.getServletContext();
     System.out.println("servletContext2 = "+servletContext2);
}

作用一:获取WEB应用程序的初始化参数

因为⼀个 web 应⽤程序只有⼀个 ServletContext对象,所以这个对象对整个应⽤程序的相关内容都是了解的
web.xml 配置 WEB 应⽤程序的初始化参数
 
<!-- 配置的是WEB程序的初始化参数-->
<context-param>
    <param-name>name</param-name>
    <param-value>wensong</param-value>
</context-param>
API 操作
⽅法
返回值
描述
getInitParameter(String name)
String
获取 web 应⽤程序的初始化参数
代码演示:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     /*
     * 获取ServletContext对象
     * ⽗类的⽅法
     * org.apache.catalina.core.ApplicationContextFacade实现接⼝ServletContext
     */
     ServletContext context = getServletContext();
     System.out.println(context);
     //context对象,获取配置⽂件中的初始化参数
     String value = context.getInitParameter("name");
     System.out.println(value);
}

作用二:获取WEB应用程序下任意资源的绝对路径

⽅法
返回值
描述
getRealPath(String path)
String
接收⼀个资源的相对路径,返回真实路径 ( 完整路径)的字符串
  • 获取web⽬录下的a.txt绝对路径
  • 获取web⽬下WEB-INF⽬录下的b.txt绝对路径
  • 获取src⽬录下的c.txt绝对路径
  • 获取web02下的d.txt绝对路径,获取不到

代码演示:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     //获取servletContext对象
     ServletContext servletContext = super.getServletContext();
     //获取web⽬录下的a.txt绝对路径
     String apath = servletContext.getRealPath("a.txt");
     System.out.println("apath = " + apath);
     //获取web⽬录下WEB-INF⽬录下的b.txt绝对路径
     String bpath = servletContext.getRealPath("WEB-INF/b.txt");
     System.out.println("bpath = " + bpath);
     //获取src⽬录下的c.txt绝对路径
     String cpath = servletContext.getRealPath("WEB-INF/classes/c.txt");
     System.out.println("cpath = " + cpath);
     //获取web02下的d.txt绝对路径
     //tomcat的webapps中 没有部署该⽂件, ⽆法获取到
}

 

作用三:ServletContext作为域对象

JavaWeb 四⼤域对象
根据有作⽤范围由⼩到⼤:
  • page(jsp有效)------page域指 在当前⻚⾯中有效, ⼀旦⻚⾯超出该⻚⾯就不能访问了.
  • request(⼀次请求)---request域指 在本次请求与响应过程中, 都能够访问.
  • session(⼀次会话)---session域指 在本次打开浏览器访问服务器开始, 到本次浏览器关闭之间访问有效
  • application(当前web应⽤)---application域指 在当前web项⽬中均可访问. ServletContextapplication
之所以他们是域对象,原因是他们都内置了 map 集合,都有 setAttribute getAttribute ⽅法。
 
ServletContext 作为域对象
ServletContext 是在服务器启动的时候为每个 web 项⽬ 单独创建⼀个 ServletContext 对象。当 web项⽬从服务器中移除,或者是关闭服务器的时候 ServletContext 对象会被销毁。向 ServletContext中保存的数据⼀直存在(当服务器关闭的时 ServletContext 对象被销毁,然后⾥⾯数据才会失效)。

 

  • ServletContext作⽤范围:整个web应⽤
⽅法
返回值
描述
setAttribute(String key, Object value)
void
向域对象存储数据
getAttribute(String key)
Object
取出域对象数据
removeAttribute(String key)
void
移除域对象数据
代码演示 :
第⼀个 Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     //获取servletcontext对象
     ServletContext context = super.getServletContext();
     //存储数据 type=java
     context.setAttribute("type","java");
     //读取数据 type的值
     Object value = context.getAttribute("type");
     System.out.println("Context4Servlet type = " + value);
}
第⼆个 Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     //获取ServletContext域对象
     ServletContext context = super.getServletContext();
     //获取域对象中 指定键的值
     Object value = context.getAttribute("type");
     System.out.println("Context5Servlet type = " + value);
}

案例 统计访问的次数

⽬的 : 练习域对象ServletContext 的使⽤
分析 :
  • 第⼀次访问Servlet的时候,数据 1 存储到域对象中
  • 第⼆次访问Servlet的时候,从域中取出数据++,再存储回去
 
@Override
public void init() throws ServletException {
     //第⼀次访问Servlet的时候,数据 1 存储到域对象中
     ServletContext context = super.getServletContext();
     context.setAttribute("count",1);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     //第⼆次访问Servlet的时候,从域中取出数据++,再存储回去
     ServletContext context = super.getServletContext();
     Integer count = (Integer) context.getAttribute("count");
     System.out.println("welcome " + count);
     count++;
     context.setAttribute("count",count);
}

 

Servlet

 注解开发取代web.xml

Servlet版本JavaEE版本
4.08.0
3.18.0
3.17.0
3.06.0
2.55.0
Servlet 2.5 版本时
  • Servlet、过滤器(Filter)和监听器(Listener)的声明都必须使⽤web.xml
Servlet 3.0 版本时
  • 新增的注解⽀持:该版本新增了若⼲注解,⽤于简化 Servlet、过滤器(Filter)和监听器 Listener)的声明,这使得 web.xml ⽂件从该版本开始不再是必选的了

注解servlet配置

@WebServlet, 注解添加到⾃⼰定义的 Servlet 中的类声明上即可 , 注解的属性 urlPatterns,属性值就是浏览器的访问地址
//创建servlet,在@WebServlet注解中添加urlPatterns= "/test",作为请求路径
@WebServlet(urlPatterns = "/test")
注解 servlet 模板修改
  • doPost⽅法内, 添加 doGet(request, response);
  • 修改注解⼩括号内容为 ("/${Entity_Name}")

 

Response对象

负责对浏览器进⾏响应的对象
什么是响应 : 服务器接收到请求需要进⾏处理,将处理以后的结果显示回浏览器端(将这个过程称为是响应 Response )。
  • 查看Servlet中的service⽅ 法得知, Servlet中使⽤的ServletResponse接⼝, ⽽我们使⽤的是
  • ServletResponse的⼦接⼝HttpServletResponse, 它继承⾃ServletResponse, 是与HTTP协议相关Response响应对象
  • 我们使⽤的⼦接⼝HttpServletResponse, 此接⼝对象由Tomcat引擎提供
  • 可以实现对客户端的响应, 响应内容包括: 响应⾏,响应头,响应体

Response设置响应行

方法返回值描述
setStatus(int sc)void设置响应的状态码
设置响应的状态码
  • 200 正确
  • 302 重定向
  • 304 查找本地缓存
  • 404 请求资源不存在
  • 500 服务器内部错误
response.setStatus(500);

Response设置响应头

HTTP 协议的响应头 , 数据格式键值对 k:v
包含指导性信息 , 指导客户端
⽅法
返回值
描述
addHeader(String key,String value)
void
添加响应头,值为 String 类型
addIntHeader(String key,int value)
void
添加响应头,值为 int 类型
addDateHeader(String key,long l)
void
添加响应头,值为⽇期类型
setHeader(String key,String value)
void
更改响应头,值为 String 类型
setIntHeader(String key,int value)
void
更改响应头,值为 int 类型
setDateHeader(String key,long l)
void
更改响应头,值为⽇期类型
add 开头的⽅法:针对⼀个 key 对应多个 value 的情况。
⽐如已有⼀个响应头 hello:java
然后执⾏ addHeader(“hello”,”java2222”);
最终得到响应头的结果:hello:java,java2222
set 开头的⽅法:针对⼀个 key 对应⼀个 value 的情况。
 
⽐如已有⼀个响应头 hello:java
然后执⾏ addHeader(“hello”,”java2222”);
最终得到响应头的结果:hello:java2222
演示:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     /*
     * response对象设置响应头
     */
     response.addHeader("hello","java");
     
     response.addDateHeader("date",System.currentTimeMillis());
     /*
     * addHeader() 添加,实现⼀个键对应多个值
     * setHeader() 设置,原来的键覆盖
     */
     response.setHeader("hello","java2222");
}

Response设置响应体

HTTP的响应体,就是⻚⾯的正⽂部分

字符流向浏览器写数据

⽅法
返回值
描述
write()
PrintWriter
使⽤字符串数据 , 没有差别 , 输出是整数 , 查询编码表
print()
PrintWriter
⽆论是什么 , 原样打印
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     /*
     * response对象⽅法getWriter()
     * 打印流的响应体
     * write() 使⽤字符串数据,没有差别, 输出是整数,查询编码表
     * print() ⽆论是什么,原样打印
     */
     PrintWriter pw = response.getWriter();
     pw.write(100);
     pw.print(100);
}
字符流的中⽂乱码问题
产⽣乱码原因 : 编码和解码不⼀致
提问:在 Servlet 中编写以下代码,向⻚⾯输出中⽂是否会产⽣乱码?
response.getWriter().print("中⽂");
会乱码:
  • 原因:
    • 字符流是有缓冲区的,response获得字符流,response设计默认的缓冲区编码是ISO-8859-1。这个字符集不⽀持中⽂的。
  • 解决:
    • 设置response获得字符流缓冲区的编码 与 设置浏览器默认打开时候采⽤的字符集⼀致即可。
⽅法
返回值描述
setHeader("Content-Type", "text/html;charset=UTF-8")
void
设置浏览器打开⻚⾯时采⽤的字符集
setContextType(String type)
void
设置浏览器打开⻚⾯时采⽤的字符集
// 设置浏览器默认打开的时候采⽤的字符集:
// response.setHeader("Content-Type", "text/html;charset=UTF-8");
// 简化代码
response.setContentType("text/html;charset=UTF-8");
// 输出中⽂汉字
response.getWriter().println("中⽂");

字节流向浏览器写数据

方法返回值描述
getOutputStream()
OutputStream
返回字节输出流 OutputStream ,响应⾮⽂本类型的数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     /*
     * response对象的⽅法getOutputStream,响应⾮⽂本类型的数据
     */
     //获取图⽚的绝对路径
     String aFile = getServletContext().getRealPath("download/a.jpg");
     FileInputStream fis = new FileInputStream(aFile);
     OutputStream out = response.getOutputStream();
     int len = 0;
     byte[] bytes = new byte[1024];
     while ((len = fis.read(bytes))!=-1){
         out.write(bytes,0,len);
     }
     fis.close();
}

重定向

重定向的写法
浏览器进⾏重新的定向 :
  • 设置302状态码: setStatus(302)
  • 设置重定向资源的地址: setHeader("location","资源")
通过 HttpServletResponse 对象中的以下⽅法实现重定向
方法返回值描述
sendRedirect(String location)
void重定向

重定向的代码实现

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     /*
     * 浏览器进⾏重新的定向:
     * 设置302状态码: setStatus(302)
     * 设置重定向资源的地址: setHeader("location","/web02/servlet2")
     */
     //response.setStatus(302);
     //response.setHeader("location","/web02/servlet2");
     // web02是发布设置的虚拟地址
 
     response.sendRedirect("/web02/servlet2");
}

案例 文件下载

需求 :
  • 客户端浏览器从服务器下载⽂件

分析

  • 超链接地址 ,连接的地址是服务器端⽂件的路径
  • 当点击下载⽂件时:
    • 若浏览器识别该⽂件类型, 并不会下载⽂件, ⽽是直接打开运⾏
    • 若浏览器不识别该⽂件类型, 直接下载⽂件
实现 :
html 代码
<body>
 <a href="/web02/download?fileName=cat.png" name="">下载猫咪图⽚</a>
 </body>
编写服务器端代码 , 告诉浏览器下载 , 不要打开
@WebServlet(urlPatterns = "/download")
public class DownloadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String filename= request.getParameter("fileName");
        String filePath = filename;    
        String agent = request.getHeader("User-Agent");
        if (agent.contains("MSIE")) {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
         } else 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");
         }
         //通知浏览器请你下载,不要打开   
        response.setHeader("Content-Disposition","attachment;filename=" +filename);
        System.out.println("filePath = " + filePath);
        String path = getServletContext().getRealPath("download/"+filePath);
        FileInputStream fis = new FileInputStream(path);
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] bytes = new byte[8*1024];
        while ((len = fis.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        fis.close();
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

案例 验证码

验证码的本质是个图⽚,图⽚⾥⾯是个随机⽣成字符串

随机字符串的思想:
String str ="abcdefABCDE1234567890";
Random.nextInt( str.length() )产⽣整数随机数
str.charAt(索引)

html:

<!DOCTYPE html>
<html>
 <head>
     <meta charset="UTF-8">
     <title>验证码</title>
     <script type="text/javascript">
       function fnChange() {
         /*
         * ⻚⾯打开的时候,请求服务器资源/web02/code
         * 点击图⽚js函数中,发了请求/web02/code
         *
         * 请求的资源没有变化,服务器端程序也没有变化
         * 浏览器拿缓存吧, 放回状态码304
         *
         * 为了每次请求得到不⼀样的验证码,添加参数保证请求路径不同即可
         */
         //点击图⽚,修改src的属性值
         var code = document.getElementById("code");
         var date = new Date().getTime();
         code.src="/web02/code?t="+date;
     }
 </script>
</head> 
<body>
 <img src="/web02/code" onclick="fnChange()" id="code">
</body>
</html>

数据库端二维码产生:

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());
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值