Request与Response

一.Request

1.什么是Request

由于Http协议比较复杂, 所以在API中提供了 HttpServletRequest (继承自ServletRequest) 来封装 Http 请求消息;

2.Request的作用

获取客户端的请求信息;

2.1 获取请求行

@WebServlet("/demo1")
public class ServletDem01 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用request对象获取请求行的信息
        //1. 获取请求的方式(可能会用)
        String method = req.getMethod();
        System.out.println("method = " + method); // method = GET

        //2. 获取客户端的ip地址
        String remoteAddr = req.getRemoteAddr();
        System.out.println("remoteAddr = " + remoteAddr); // 0:0:0:0:0:0:0:1 ipv6地址

        //3. 获取项目部署的路径
        String contextPath = req.getContextPath();
        System.out.println("contextPath = " + contextPath); // /rzc

        //4. 获取请求的url: 统一资源定位符 http://localhost:8080/requestDemo/demo01
        StringBuffer requestURL = req.getRequestURL();
        System.out.println("requestURL = " + requestURL); // http://localhost:8080/rzc/demo1

        //5. 获取请求的uri: 统一资源标识符,在url的基础上省略了服务器路径"http://loaclhost:8080"
        String requestURI = req.getRequestURI();
        System.out.println("requestURI = " + requestURI); // /rzc/demo1
    }
}
  • getServerPort(); 获取服务端的端口
  • getQueryString(); 获取请求参数(get请求的,URL的?后面的. eg:username=zs&password=123456)

2.2 获取请求头

请求头包含的信息比较多, 需要用的时候可以通过 getHeader(String name) 函数来获取;

  • User-Agent: 浏览器信息
  • Referer: 来自哪个网站(防盗链)

2.3 获取请求体




    
    注册页面


    
用户名
密码
性别
兴趣爱好 篮球 足球 乒乓球 羽毛球
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 根据参数名,获取一个参数值
        String username = req.getParameter("username");
        System.out.println("username = " + username);

        //2. 根据参数名,获取多个参数值:比如说注册时候的兴趣爱好的复选框
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println("hobby = " + hobby);
        }

        //3. 获取所有的请求参数
        //getParameterMap()获取所有请求参数,请求参数的参数名就是map的key,请求参数的参数值就是map的value
        Map parameterMap = req.getParameterMap();
        Set> entries = parameterMap.entrySet();
        for (Map.Entry entry : entries) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            for (String value : values) {
                System.out.println("key+\"=\"+value = " + key + "=" + value);
            }
        }
    }
}
使用BeanUtils封装这些参数对象
    1.需要依赖BeanUtils的jar包
    2.Java Bean文件中的属性名需要和参数名一一对应;
    BeanUtils.copyProperties(user,parameterMap);
    // BeanUtils.populate(user,parameterMap);

2.4 请求转发

/**
 * 1. 请求转发的效果的跳转, 跳转到其他页面,或者跳转到其它的servlet
 * 2. 请求转发的跳转, 只能是跳转到本项目的资源
 * 3. 请求转发的原理是: 服务器进行转发操作,将这次请求发给目标地址,由服务器向目标地址响应资源
 */
@WebServlet("/demo5")
public class ServletDemo5 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 访问此 Servlet 将跳转到 /register.html
//        req.getRequestDispatcher("/register.html").forward(req,resp);

        // 访问此 Servlet 将跳转到访问 /demo3
        req.getRequestDispatcher("/demo3").forward(req,resp);
    }
}

2.5 作为域对象

/**
 * request 作为域对象在不同的Servlet之间进行数据的共享,它只能在同一次请求中进行数据共享
 * request 域对象只有和请求转发一起使用才有意义
 */
@WebServlet("/demo6")
public class ServletDemo6 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("name","ccs");
        req.getRequestDispatcher("/demo7").forward(req,resp);
    }
}
@WebServlet("/demo7")
public class ServletDemo7 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object name = req.getAttribute("name");
        System.out.println("name=="+name);
    }
}

二.Response

1.什么是Repsonse

由于Http协议比较复杂, 所以在API中提供了 HttpServletResponse (继承自ServletResponse) 来封装 Http 响应消息;

2.Response的作用

响应客户端的请求

2.1 设置响应行信息

/**
 * response 设置响应行的信息
 * setStatus设置响应状态码
 * 200 响应成功
 * 302 重定向
 * 304 访问缓存
 * 403 没有权限访问
 * 404 客户端错误
 * 500 服务器错误
 */
@WebServlet("/demo8")
public class ServletDemo8 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(403);
    }
}

2.2 设置响应头信息以及重定向

/**
 * 常用的响应头,需要使用其它的响应头可以去文档中查找
 * Refresh 定时跳转
 * Location 重定向地址
 * Content-Disposition 告诉浏览器下载
 * Content-Type 设置响应内容的MiME类型(服务器告诉浏览器内容的类型)
 */
@WebServlet("/demo9")
public class ServletDemo9 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Refresh 定时跳转
        // resp.setHeader("Refresh","3,http://www.baidu.com");

        // Location 重定向地址
        resp.setStatus(302);
        resp.setHeader("Location","/rzc/register.html");
        // resp.sendRedirect("/rzc/register.html");
        // resp.sendRedirect("http://www.baidu.com");
    }
}

2.3 设置响应体信息

@WebServlet("/demo9")
public class ServletDemo9 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //给客户端响应一张图片
        //1. 读取b.jpg图片,将其转换成字节输入流,使用ServletContext
//        ServletContext servletContext = getServletContext();
//        InputStream is = servletContext.getResourceAsStream("b.jpg");
//
//        //2. 使用字节输出流,将is中的字节都输出到浏览器
//        ServletOutputStream os = resp.getOutputStream();
//
//        /*byte[] buffer = new byte[1024];
//        int len = 0;
//        while ((len = is.read(buffer)) != -1){
//            os.write(buffer,0,len);
//        }*/
//        IOUtils.copy(is,os);
//        os.close();
//        is.close();

        // 给客户端响应一段字符串
        resp.setContentType("text/html;charset=UTF-8");

        //要向浏览器输出响应体的信息,需要通过流来进行操作
        //第一种:字符串,输出文本内容
        PrintWriter writer = resp.getWriter();
        //使用字符流往浏览器输出文本
        //1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
        writer.write("你好世界");
        //2. print()方法,可以输出数字、字符串
        //writer.print(8);
    }
}

三.请求转发与重定向的区别

1.跳转的发起者不同
    请求转发的跳转发起者:是服务器去重新找到资源响应给浏览器
    重定向的跳转发起者:是服务器响应给浏览器一个新的地址,两次都是浏览器;
2.浏览发起的请求次数不同
    请求转发:只会请求一次;
    重定向:会请求二次;
3.能够跳转到的资源
    请求转发:只能是服务器本项目中的资源;
    重定向:可以是任意地址;
4.地址样的地址是否发生改变
    请求转发:没有发生改变;
    重定向:会发生改变

四.路径问题

完整路径, 相对路径, 绝对路径; 完整路径, 是一个完整的访问地址, 可以在不同的项目中访问; 而相对路径与绝对路径都是针对相同项目而言的;

1.完整Url地址

url的组成部分:

例如 http://localhost:8080/rzc/jstl/jstl_test01.jsp

  • http:// 表示协议是http协议
  • localhost 表示主机地址,就是ip地址
  • :8080 表示服务器的端口号 (通过端口号可以找到服务端程序的进程);
  • rzc 表示项目的虚拟路径(部署路径), 这个在 idea 中一般为项目名, 可以设置成不包含这个路径的访问地址;
  • jstl/jstl_test01.jsp 表示项目上的具体的动态或静态资源;

什么时候会使用完整的url

  • 浏览器地址栏直接访问;

  • 一个项目中,访问另一个项目中的资源;

2.相对路径




    
    路径相关测试


hello world....

访问ServletDemo2

3.绝对路径




    
    路径相关测试


hello world....

访问ServletDemo02

五.案例代码

1.文件下载案例




    
    下载页面


    下载a.jpg
下载b.jpg
下载WEB01.zip
下载美女.jpg
下载霉女.jpg
/**
 * 浏览器访问DownloadServlet,如果是图片直接在浏览器上显示了,现在需要下载这张图片
 * 使用 Content-Disposition 响应头,让浏览器进行文件的下载
 * 当文件名是中文的时候,浏览器下载无法显示中文 URLEncoder
 * file文件应该在web目录下
 */
@WebServlet("/demo10")
public class DownLoadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        //获取请求参数fileName的值
        String fileName = req.getParameter("fileName");

        //读取对应的文件
        InputStream is = req.getServletContext().getResourceAsStream("file/"+fileName);

        //告诉浏览器文件的MIME类型(可以不写)
        String mimeType = getServletContext().getMimeType(fileName);
        System.out.println("mimeType = " + mimeType);
        resp.setHeader("Content-Type",mimeType);

        //使用字节输出流,将文件输出给浏览器
        ServletOutputStream os = resp.getOutputStream();

        //响应头中是无法识别中文的,所以有中文的文件名,在下载的时候显示会出现问题
        //将文件名进行编码转换,将中文转换成英文
        String encodeFileName = URLEncoder.encode(fileName, "UTF-8");

        //在输出内容之前,进行响应头的设置,设置Content-Disposition响应头,让浏览器下载文件
        resp.setHeader("Content-Disposition", "attachment;filename=" + encodeFileName);

        IOUtils.copy(is, os);

        os.close();
        is.close();
    }
}

你可能感兴趣的:(Request与Response)