Javaweb复习资料(二)(中)

简介: Javaweb复习资料(二)

四、响应


1 响应对象


1.1 响应对象概述


1.1.1 关于响应


响应,它表示了服务器端收到请求,同时也已经处理完成,把处理的结果告知用户。简单来说,指的就是服务器把请求的处理结果告知客户端。在B/S架构中,响应就是把结果带回浏览器。


响应对象,顾名思义就是用于在JavaWeb工程中实现上述功能的对象。


1.1.2 常用响应对象


响应对象也是是Servlet规范中定义的,它包括了协议无关的和协议相关的。


  • 协议无关的对象标准是:ServletResponse接口


  • 协议相关的对象标准是:HttpServletResponse接口


类结构图如下:



下面介绍涉及的响应对象都是和HTTP协议相关的。即使用的是HttpServletResponse接口的实现类。


这里有些同学可能会产生疑问,我们在使用Servlet时,需要定义一个类,然后实现Servlet接口(或者继承它的实现类)。现在我们想要实现响应功能,要不要定义一个类,然后实现HttpServletResponse接口呢?


此问题的答案是否定的,我们无需这么做。我们只需要在自己写的Servlet中直接使用即可,因为这个对象的实现类是由Tomcat提供的,无须我们自定义。同时它还会帮我们把对象创建出来并传入doGet和doPost方法中。


1.2 常用方法介绍


1.2.1 API 介绍


在官网中我们可以查看到:https://javaee.github.io/javaee-spec/javadocs/


在HttpServletResponse接口中提供了很多方法,接下来我们通过API文档,来了解一下这些方法。



我们对上面函数进行中文解释,如下图。



1.2.2 常用响应状态码


常用状态码:


image.png


状态码首位含义:


image.png


1.3 响应对象的使用示例


1.3.1 响应字节流输出中文乱码问题


内容过多,请移驾我的另一篇博客:


https://yangyongli.blog.csdn.net/article/details/117877830


1.3.2 响应-生成验证码


内容过多,请移驾我的另一篇博客:


https://yangyongli.blog.csdn.net/article/details/117878306


1.3.3 设置响应消息头 —— 控制缓存


/**
 * 设置缓存时间
 *  使用缓存的一般都是静态资源
 *  动态资源一般不能缓存。
 *  我们现在目前只掌握了Servlet,所以用Servlet做演示
 *
 */
public class ResponseDemo4 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String str = "设置缓存时间";
        /*
         * 设置缓存时间,其实就是设置响应消息头:Expires 但是值是一个毫秒数。
         * 使用的是
         *  response.setDateHeader();
         *
         * 缓存1小时,是在当前时间的毫秒数上加上1小时之后的毫秒值
         */
        response.setDateHeader("Expires",System.currentTimeMillis()+1*60*60*1000);
        response.setContentType("text/html;charset=UTF-8");
        response.getOutputStream().write(str.getBytes());
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}




1.3.4 设置响应消息头 —— 定时刷新


/**
 * 设置响应消息头:
 * 通过定时刷新演示添加消息头
 */
public class ResponseDemo5 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String str = "用户名和密码不匹配,2秒后转向登录页面...";
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write(str);
        //定时刷新,其实就是设置一个响应消息头
        response.setHeader("Refresh", "2;URL=/login.html");//Refresh设置的时间单位是秒,如果刷新到其他地址,需要在时间后面拼接上地址
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}



1.3.5 请求重定向:注意地址栏发生改变。


/**
 * 设置响应状态码,实现重定向
 * 重定向的特点:
 *   两次请求,地址栏改变,浏览器行为,xxxx
 *
 */
public class ResponseDemo6 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.设置响应状态码
//    response.setStatus(302);
        //2.定向到哪里去: 其实就是设置响应消息头,Location
//    response.setHeader("Location", "ResponseDemo7");
        //使用重定向方法
        response.sendRedirect("ResponseDemo7");//此行做了什么事,请看上面
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


重定向到了这


/**
 * 重定向的目的地
 */
public class ResponseDemo7 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getWriter().write("welcome to ResponseDemo7");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}



1.3.6 响应和消息头组合应用 —— 文件下载


首先,在工程的web目录下新建一个目录uploads,并且拷贝一张图片到目录中,如下图所示:



文件下载的Servlet代码如下:


/**
 * 文件下载
 *
 */
public class ResponseDemo8 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /*
         * 文件下载的思路:
         *    1.获取文件路径
         *    2.把文件读到字节输入流中
         *    3.告知浏览器,以下载的方式打开(告知浏览器下载文件的MIME类型)
         *    4.使用响应对象的字节输出流输出到浏览器上
         */
        //1.获取文件路径(绝对路径)
        ServletContext context = this.getServletContext();
        String filePath = context.getRealPath("/uploads/6.jpg");//通过文件的虚拟路径,获取文件的绝对路径
        //2.通过文件路径构建一个字节输入流
        InputStream in  = new FileInputStream(filePath);
        //3.设置响应消息头
        response.setHeader("Content-Type", "application/octet-stream");//注意下载的时候,设置响应正文的MIME类型,用application/octet-stream
        response.setHeader("Content-Disposition", "attachment;filename=1.jpg");//告知浏览器以下载的方式打开
        //4.使用响应对象的字节输出流输出
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] by = new byte[1024];
        while((len = in.read(by)) != -1){
            out.write(by, 0, len);
        }
        in.close();
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}



1.3.7 响应对象注意事项


第一: response得到的字符流和字节流互斥,只能选其一


第二:response获取的流不用关闭,由服务器关闭即可


/**
 * 使用Response对象获取流时候的注意事项:
 *  1.我们使用response获取的流,可以不用关闭。服务器会给我们关闭。
 *  2.在response对象中,字节流和字符流互斥,输出的时候,只能选择一个
 *
 */
public class ResponseDemo9 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String str = "test";
        response.getOutputStream().write(str.getBytes());
        //response.getWriter().write(str);
//    response.getOutputStream().write("haha".getBytes());
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}



五、请求对象


2 请求对象


2.1 请求对象概述


2.1.1 关于请求


请求,顾明思议,就是使用者希望从服务器端索取一些资源,向服务器发出询问。在B/S架构中,就是客户浏览器向服务器发出询问。在我们的JavaEE工程中,客户浏览器发出询问,要遵循HTTP协议所规定的。


请求对象,就是在JavaEE工程中,用于发送请求的对象。我们常用的对象就是ServletRequest和HttpServletRequest,它们的区别就是是否和HTTP协议有关。


2.1.2 常用请求对象



2.2 常用方法介绍


官网:https://javaee.github.io/javaee-spec/javadocs/



我们进行中文解释如下图:



2.3 请求对象的使用示例


2.3.1 请求对象常用方法1-获取各种路径


/**
 * 请求对象的各种信息获取
 */
public class RequestDemo1 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //本机地址:服务器地址
        String localAddr = request.getLocalAddr();
        //本机名称:服务器名称
        String localName = request.getLocalName();
        //本机端口:服务器端口
        int localPort = request.getLocalPort();
        //来访者ip
        String remoteAddr = request.getRemoteAddr();
        //来访者主机
        String remoteHost = request.getRemoteHost();
        //来访者端口
        int remotePort = request.getRemotePort();
        //统一资源标识符
        String URI = request.getRequestURI();
        //统一资源定位符
        String URL = request.getRequestURL().toString();
        //获取查询字符串
        String queryString = request.getQueryString();
        //获取Servlet映射路径
        String servletPath = request.getServletPath();
        //输出内容
    System.out.println("getLocalAddr() is :"+localAddr);
    System.out.println("getLocalName() is :"+localName);
    System.out.println("getLocalPort() is :"+localPort);
    System.out.println("getRemoteAddr() is :"+remoteAddr);
    System.out.println("getRemoteHost() is :"+remoteHost);
    System.out.println("getRemotePort() is :"+remotePort);
    System.out.println("getRequestURI() is :"+URI);
    System.out.println("getRequestURL() is :"+URL);
        System.out.println("getQueryString() is :"+queryString);
        System.out.println("getServletPath() is :"+servletPath);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


运行结果:



2.3.2 请求对象常用方法2-获取请求头信息


/**
 * 获取请求消息头
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class RequestDemo2 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.根据名称获取头的值 一个消息头一个值
        String value = request.getHeader("Accept-Encoding");
        System.out.println("getHeader():"+value);
        //2.根据名称获取头的值 一个头多个值
        Enumeration<String> values = request.getHeaders("Accept");
        while(values.hasMoreElements()){
            System.out.println("getHeaders():"+values.nextElement());
        }
        //3.获取请求消息头的名称的枚举
        Enumeration<String> names = request.getHeaderNames();
        while(names.hasMoreElements()){
            String name = names.nextElement();
            String value1 = request.getHeader(name);
            System.out.println(name+":"+value1);
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


结果如下图



2.3.3 请求对象常用方法3-获取请求参数(非常重要)


内容较多,请移驾另一篇博客:


https://yangyongli.blog.csdn.net/article/details/117880162


2.3.4 用流的形式读取请求信息


我们除了使用2.3.3小节中获取请求参数之外,还可以使用下面代码中的 方式来获取:


/**
 * 使用流的方式读取请求正文
 */
public class RequestDemo4 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.获取请求正文的字节输入流
        ServletInputStream sis = request.getInputStream();
        //2.读取流中的数据
        int len = 0;
        byte[] by = new byte[1024];
        while((len = sis.read(by)) != -1){
            System.out.println(new String(by,0,len));
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


2.3.5 请求正文中中文编码问题


内容过多,请移驾另一篇博客:


https://yangyongli.blog.csdn.net/article/details/117880598


2.3.6 请求转发(与重定向的区别)


在实际开发中,重定向和请求转发都是我们要用到的响应方式,那么他们有什么区别呢?我们通过下面的示例来看一下:


/**
 * 重定向特点:
 *  两次请求,浏览器行为,地址栏改变,请求域中的数据会丢失
 * 请求转发:
 *  一次请求,服务器行为,地址栏不变,请求域中的数据不丢失
 *
 * 请求域的作用范围:
 *   当前请求(一次请求),和当前请求的转发之中
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class RequestDemo6 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.拿到请求调度对象
        RequestDispatcher rd = request.getRequestDispatcher("/RequestDemo7");//如果是给浏览器看的,/可写可不写。如果是给服务器看的,一般情况下,/都是必须的。
        //放入数据到请求域中
        request.setAttribute("CityCode", "bj-010");
        //2.实现真正的转发操作
        rd.forward(request, response);//实现真正的转发操作
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


/**
 * 转发的目的地
 * @author 黑马程序员
 * @Company http://www.itheima.com
 */
public class RequestDemo7 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取请求域中的数据
        String value = (String)request.getAttribute("CityCode");
        response.getWriter().write("welcome to request demo 7    "+value);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


2.3.7 请求包含


在实际开发中,我们可能需要把两个Servlet的内容合并到一起来响应浏览器,而同学们都知道HTTP协议的特点是一请求,一响应的方式。


所以绝对不可能出现有两个Servlet同时响应方式。


那么我们就需要用到请求包含,把两个Servlet的响应内容合并输出。我们看具体使用示例:


/**
 * 请求包含
 *
 * 它是把两个Servlet的响应内容合并输出。
 * 注意:
 *  这种包含是动态包含。
 *
 * 动态包含的特点:
 *    各编译各的,只是最后合并输出。
 */
public class RequestDemo8 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getWriter().write("I am request demo8 ");
        //1.拿到请求调度对象
        RequestDispatcher rd = request.getRequestDispatcher("/RequestDemo9");
        //2.实现包含的操作
        rd.include(request, response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


/**
 * 被包含者
 */
public class RequestDemo9 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.getWriter().write("include request demo 9 ");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}


2.3.8 更细节问题


请求转发的注意事项:负责转发的Servlet,转发前后的响应正文丢失,由转发目的地来响应浏览器。


请求包含的注意事项:被包含者的响应消息头丢失。因为它被包含起来了。

相关文章
|
26天前
|
JavaScript Java 大数据
基于JavaWeb的销售管理系统设计系统
本系统基于Java、MySQL、Spring Boot与Vue.js技术,构建高效、可扩展的销售管理平台,实现客户、订单、数据可视化等全流程自动化管理,提升企业运营效率与决策能力。
|
4月前
|
算法 Java 数据库连接
2025 最新 Java 面试资料及详细答案整理
这是一份全面的Java面试资料整合,涵盖基础到进阶技术知识点,包括Java核心语法、面向对象编程、异常处理、集合框架、JVM原理、多线程与并发编程、网络编程等。同时深入解析主流框架如Spring、MyBatis,以及项目实战经验分享。资料结合实例辅助理解,助你高效备考,提升面试竞争力。资源地址:[点击获取](https://pan.quark.cn/s/14fcf913bae6)。
983 6
|
3月前
|
Java 编译器 数据安全/隐私保护
Java 大学期末考试真题与答案 含知识点总结 重难点归纳及题库汇总 Java 期末备考资料
本文汇总了Java大学期末考试相关资料,包含真题与答案、知识点总结、重难点归纳及题库,涵盖Java基础、面向对象编程、异常处理、IO流等内容,并提供完整代码示例与技术方案,助你高效复习备考。
136 3
|
3月前
|
SQL 前端开发 Java
JavaWeb 学习日记案例详解及 javaweb 完整项目案例实战指南
本文介绍了一个基于Spring Boot的JavaWeb企业员工管理系统完整案例,涵盖部门管理、员工管理、登录、异常处理、事务管理及AOP等核心功能实现,结合CSDN相关技术文章,提供详细技术方案与应用实例,适合JavaWeb开发者学习与参考。
143 0
|
4月前
|
人工智能 前端开发 Java
Java 面试资料中相关代码使用方法与组件封装方法解析
这是一份详尽的Java面试资料代码指南,涵盖使用方法与组件封装技巧。内容包括环境准备(JDK 8+、Maven/Gradle)、核心类示例(问题管理、学习进度跟踪)、Web应用部署(Spring Boot、前端框架)、单元测试及API封装。通过问题库管理、数据访问组件、学习进度服务和REST接口等模块化设计,帮助开发者高效组织与复用功能,同时支持扩展如用户认证、AI推荐等功能。适用于Java核心技术学习与面试备考,提升编程与设计能力。资源链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
121 6
Java 面试资料中相关代码使用方法与组件封装方法解析
|
9月前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
165 4
|
前端开发 Java 关系型数据库
JavaWeb开发简介
JavaWeb开发简介
139 0
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
836 37
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
前端开发 Java 应用服务中间件
Javaweb学习
【10月更文挑战第1天】Javaweb学习
113 2