javaee之response响应、ServletContext对象

之前写了我们可以向服务器发送请求,那么服务器自然也可以给我们进行响应

请求有HttpServletRequest来获取,那么数据的响应自然也有一个对象来处理HttpServletResponse,

原理与resquest一样

也是去继承了一个接口,然后服务器给我们做了一个实现类,

 

 在我们实现一个HttpServlet的时候,doPost与doGet方法里面参数传递的是:

HttpServletReponse hsr = new HttpServletResponseWrapper()这个类

OK,现在说一下响应消息的格式,与请求消息一样

这里还不得不说一点,就是响应头的状态码 ,简单来说,就是告诉你你访问的页面现在处于一个什么状态

 

 下面来说,设置状态码,与设置响应头信息,这些都是给客户端看的。

setStatus(一个三位数的响应状态码)

setHeader(String name,String value)

响应是为了给客户端传送数据的,那么我们就需要输出流

上面的流一个是字符流,一个是字节流。

下面直接上代码:

package datatransmisson;

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("/servlet1")
public class ResponseServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //防止写给客户端的数据出现乱码
        response.setContentType("text/html;charset=utf-8");
        //向客户端回写响应数据
        PrintWriter pw =  response.getWriter();
        char[] buf = {'我','来','了','啊'};
        pw.write(buf);

    }

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

结果:

也可以通过字节码传输数据

 下面说一下重定向,之前说请求的时候,说过一个页面转发,这两者还是有很大区别的。

话不多说,直接上代码

 先来看看页面的站内转发

ResponseServlet1

package changedirection;

import javax.servlet.RequestDispatcher;
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;

//从1重定向到2
@WebServlet("/responseServlet1")
public class ResponseServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("i am demo1....");

        /*response.setStatus(302);
        response.setHeader("location","/response/responseServlet2");*/

        //转发
        //内部需要一个你要传入到什么位置去的参数实例
        RequestDispatcher rd = request.getRequestDispatcher("/responseServlet2");
        rd.forward(request,response);
    }

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

上面的页面会跳转到responseServlet2页面

package changedirection;

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("/responseServlet2")
public class ResponseServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("i am demo2,.....");
    }

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

 浏览器显示,无跳转,无变化 

 

上面把demo1与demo2都打印出来了。

下面我们来看页面重定向,修改一下上面的代码

 

 

访问ResponseServlet1,直接跳转到ResponseDsevlet2页面。

 还可以写成这样

 上面需要注意到路径

重定向:

页面跳转: 

 重定向必须把虚拟目录写才能访问,而内部的资源跳转只需要写上java的映射文件名字

下面来说一下ServletContext对象

代表了整个web应用对象,简单来说,就是它的域是全局的。

我之前说过,一个请求之间,是可以共享数据的,当然是针对于内部服务器资源,一个资源跳转到另外一个资源,可以携带数据过去,但是这两个资源以外的资源想要访问这些数据,是不可以的。但是ServletContext对象就不一样,只要你在一个资源文件中设置了数据,在其他任何一个资源文件,你只要获得这个ServletContext对象就可以,这也说明了这个类的实例化对象是采用的单例设计模式来设计。

话不多说,直接上源代码:

RequestServlet1

package servletcontext;

import javax.servlet.RequestDispatcher;
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("/requestServlet1")
public class RequestServlet1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //利用request来创造数据
        request.setAttribute("name","i am requestServlet1, i will go requestServlet2");
        ServletContext sc = request.getServletContext();
        //同时设置一个全局属性
        sc.setAttribute("where","anywhere");
        //我们必须设置页面分发
        RequestDispatcher rd = request.getRequestDispatcher("/requestServlet2");
        //把request与response带过去
        rd.forward(request,response);
    }

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


RequestServlet2

package servletcontext;

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("/requestServlet2")
public class RequestServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取Servlet1传递过来的属性值
        Object value = request.getAttribute("name");
        System.out.println("access the data :"+ value);
        //另外有一个全局属性,需要来获取
        ServletContext sc = this.getServletContext();
        Object value1 = sc.getAttribute("where");
        System.out.println(value1);
    }

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

然后来看另外一个文件ServletContext1

package servletcontext;

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("/servletContext1")
public class ServletContext1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //整个域数据共享
        ServletContext sc = request.getServletContext();
        Object res = sc.getAttribute("where");
        System.out.println(res);


    }

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

运行结果:

下面说一下在ServletContext对象中常用的方法

1.getRealpath("相对路径")-》得到文件真实路径

 

 上面也就是我们真实的项目文件访问路径

2.String getMimeType(String file) 得到互联网一种文件类型,他是大类型包含了小类型,比如text/html,一种文件类型格式,在下载的时候,我们就要指明这种格式

ok,下面说你一个文件下载案例

首先来一个前端展示页面,让用户点击下载

先来看看我的文件结构

资源我放在img目录下面,点击链接,然后去访问一个java文件,然后下载资源,同时传递了一个文件真实名字,注意filename要与文件真实名字一一对应

话不多说,直接上代码

download.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件下载页面</title>
</head>
<body>
<a href="/response/downloadServlet?filename=图片.jpg">图片1</a>
<a href="/response/downloadServlet?filename=01.mp4">视频</a>
</body>
</html>

然后看一个下载的java页面

DownloadServlet

package download;

import utils.DownLoadUtils;

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.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //先把filename拿过来
        String filename = request.getParameter("filename");
        //下面获取文件在服务器的真实路径
        //开发路径与服务器真实路径是不一样,所以必须获取真实的路径
        ServletContext sc = request.getServletContext();
        String path = sc.getRealPath("/img/" + filename);
        //采用字节输入流和响应输出流
        FileInputStream fis = new FileInputStream(path);
        //得到文件的Mime类型
        String mimeType = sc.getMimeType(filename);

        //设置响应头类型mime类型,固定步骤
        response.setHeader("content-type",mimeType);
        //获取请求浏览器
        String agent = request.getHeader("user-agent");
        //对文件名字进行一个处理,主要是中文文件名字问题不处理就展示不了
        filename = DownLoadUtils.getFileName(agent,filename);
        //设置下载打开方式,固定步骤
        response.setHeader("content-disposition","attachment;filename=" + filename);
        //得到响应输出流,输出到客户端
        ServletOutputStream sos = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int res = 0;
        while((res = fis.read(buffer)) != -1) {
            sos.write(buffer,0,res);
        }
        fis.close();
    }

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

其中有一个不同浏览器处理中文的名字的函数,是通过DownLoadUtils类调用的 

 

这个类里面获取文件名字的方法不用去记,直接用就行,

DownLoadUtils

package utils;

import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;


public class DownLoadUtils {

    public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
        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");
        }
        return filename;
    }
}

展示一下

今天就说到这吧。 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值