07_Response

文章目录

    • 案例(请求分发案例)
  • Response
    • 响应行
    • 响应头
    • 响应体
    • 特殊响应头
      • refresh
      • Content-type
      • Content-disposition
      • location
    • 案例(登录案例)

案例(请求分发案例)

  • 场景:有多个请求
    • Http://localhost:8080/user/login → 登录
    • Http://localhost:8080/user/register → 注册
    • Http://localhost:8080/user/info → 查看用户信息

eg:

/**
 * localhost:8080/demo1/user/login
 * localhost:8080/demo1/user/register
 * localhost:8080/demo1/user/info
 */

//@WebServlet(value = {"/user/login", "/user/register", "/user/info"})
@WebServlet("/user1/*")
public class UserServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

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

    private void process(HttpServletRequest request, HttpServletResponse resp) {
        String operation = null;
        // /demo1/user/login
        String requestURI = request.getRequestURI();
        operation = requestURI.substring(requestURI.lastIndexOf("/") + 1);
//        if("login".equals(operation)) {
//            login(request,resp);
//        } else if("info".equals(operation)) {
//            info(request,resp);
//        }
        switch (operation) {
            case "login":
                login(request, resp);
                break;
            case "info":
                info(request, resp);
                break;
            case "register":
                register(request, resp);
                break;
            case "remove":
                remove(request, resp);
                break;
        }
    }

    private void remove(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void register(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void info(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void login(HttpServletRequest request, HttpServletResponse resp) {
    }
}

优化版本

eg:

  • DispatchUtil.java
    • 通过反射的方式,实现其通用性
public class DispatchUtil {
    @SneakyThrows
    public static void dispatch(String operation, HttpServletRequest request
            , HttpServletResponse response, HttpServlet instance) {

// java.lang.Class.getDeclaredMethod()方法返回一个Method对象,
// 它反映此Class对象所表示的类或接口的指定已声明方法。
// name 参数是一个字符串,指定所需的方法的简单名称,
// parameterTypes 参数是一个数组的Class对象识别方法的形参类型,在声明的顺序
                        
        Method method = instance.getClass().getDeclaredMethod(operation
                , HttpServletRequest.class, HttpServletResponse.class);

        method.setAccessible(true);

        method.invoke(instance, new Object[]{request, response});
    }
}
//@WebServlet(value = {"/user/login", "/user/register", "/user/info"})
@WebServlet("/user2/*")
public class UserServlet2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

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

    private void process(HttpServletRequest request, HttpServletResponse resp) {
        String operation = null;
        // /demo1/user/login
        String requestURI = request.getRequestURI();
        operation = requestURI.substring(requestURI.lastIndexOf("/") + 1);
//        if("login".equals(operation)) {
//            login(request,resp);
//        } else if("info".equals(operation)) {
//            info(request,resp);
//        }
        // 不需要再switch判断,直接写方法名函数就可以
        DispatchUtil.dispatch(operation, request, resp, this);
    }

    private void remove(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void register(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void info(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void login(HttpServletRequest request, HttpServletResponse resp) {
    }

    private void logout(HttpServletRequest request, HttpServletResponse resp) {
        System.out.println("logout");
    }
}

Response

响应报文的封装,设置响应报文

eg:

HTTP/1.1 200
Vary: accept-encoding,origin,access-control-request-headers,access-control-request-method,accept-encoding
Set-Cookie: rememberMe=deleteMe; Path=/; Max-Age=0; Expires=Sun, 12-Feb-2023 06:51:56 GMT
Set-Cookie: JSESSIONID=24287278-5ebb-407d-a3f7-56b74782c4c7; Path=/; HttpOnly
Access-Control-Allow-Origin: *
Content-Type: application/json;charset=UTF-8
Date: Mon, 13 Feb 2023 06:51:56 GMT
Content-Length: 200

{"errno":0,"data":{"adminInfo":
{"nickName":"admin123","avatar":"https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif"},
"token":"24287278-5ebb-407d-a3f7-56b74782c4c7"},"errmsg":"成功"}

响应行

设置一下响应状态码

方法名参数说明
setStatus(int)参数就是状态码设置响应状态码

eg:

/**
 * 常用的响应状态码:200、404、302、400、500
 * 响应行中的响应状态码
 */
@WebServlet("/line")
public class LineServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        response.setStatus(302);
    }
}

在这里插入图片描述


响应头

  • 响应头是key:value的格式,提供了通用的方法,可以设置响应头的key和value
  • 提供了一些特定的方法,特定的方法做的事情,就是设置特定响应头的值
方法参数说明
setHeader(String,String)参数1提供key,参数2提供value通用的方法

eg:

@WebServlet("/header")
public class HeaderServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        // 第一个参数是key,第二个参数是value
        response.setHeader("custom-header","aaaaaa");
    }
}

在这里插入图片描述


响应体

  • 可以使用字符流,也可以使用字节流
  • 场景:
    • 字符流:响应文本数据,最主要的场景就是前后端分离之后,通过字符流响应Json数据
    • 字节流:响应图片、文件,也通常在文件下载的场景下使用
方法返回值描述
getWriter()PrintWriter字符流
getOutputStream()ServletOutputStream字节流

eg:

  • 字符流举例
@WebServlet("/body1")
public class BodyServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        // response.getWriter().write("hello world");
        // 如果把响应体里的字符以utf-8的方式编码,不一定能解决中文乱码的问题
        // 因为浏览器不一定以utf-8的方式来解码
        // 从根本上解决这个问题通知浏览器以utf-8的方式解码
        // content-type:指响应体里的正文类型
        response.setHeader("content-type","text/html;charset=utf-8");
        // response.getWriter().write("hello world");
        // 默认的编码:iso-8859-1
        response.getWriter().println("hello world");
    }
}

在这里插入图片描述

  • 字节流举例
@WebServlet("/body2")
public class BodyServlet2 extends HttpServlet {

    // http://localhost:8080/demo1/body2?pic=1.jpg
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String pic = request.getParameter("pic");
        String path = "D:\\test_photo";
        File file = new File(path, pic);
        // 要显示图片,需要在响应体中提供其字节数据 -> 浏览器就会显示图片
        ServletOutputStream outputStream = response.getOutputStream();
        FileInputStream inputStream = new FileInputStream(file);

        int length = 0;
        byte[] bytes = new byte[1024];

        while((length = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0 ,length);
        }
        inputStream.close();
        outputStream.close();
    }
}

特殊响应头

  • 特殊的几个响应头:
    1. refresh → 定时刷新、跳转
    2. content-type → 限定响应的正文(也可以解决中文乱码问题)
    3. content-disposition → 文件下载
    4. location → 重定向

refresh

eg:

/**
 * 自动显示当前的时间
 */
@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        response.setHeader("refresh", "1");

        String pattern = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        String dateStr = simpleDateFormat.format(new Date());


        response.getWriter().println(dateStr);
    }
}

@WebServlet("/refresh2")
public class RefreshServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        // 指3s之后去访问demo2/hello.jsp
        response.setHeader("refresh", "3;url=/demo1/hello.jsp");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().println("请稍后马上跳转到欢迎页面");
    }
}

Content-type

  • 通常不需要设置
  • 比如我们响应Json数据给前端,我们可以设置Content-Type:application/json
  • 我们要在这里做字符集的设置,如果没有做有可能出现中文乱码

Content-disposition

  • 下载的场景会使用
    • eg:content-disposition: attachment;filename=1.jpg
    • 1.jpg来下载正文

eg:

@WebServlet("/download")
public class ContentDispositionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String pic = request.getParameter("pic");
        String path = "D:\\test_photo";

        // 如果代码没有这行内容,那么就是显示该图片
        // 如果做下载,需要设置header content-disposition
        response.setHeader("content-disposition", "attachment;" + pic);

        FileInputStream inputStream = new FileInputStream(new File(path, pic));

        ServletOutputStream outputStream = response.getOutputStream();

        int length = 0;
        byte[] bytes = new byte[1024];

        while ((length = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, length);
        }
        inputStream.close();
    }
}

location

  • 重定向
  • 状态码:302

eg:

@WebServlet("/location")
public class LocationServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("访问到LocationServlet");
        resp.setStatus(302);
        resp.setHeader("location","http://localhost:8080/demo1/refresh");
    }
}

案例(登录案例)

  • 这个请求由登录页面提供,我们可以通过html提供一个登录表单,该表单会发出请求
  • http://localhost:8080/user/login→ Servlet → 检查用户名和密码是否正确(使用一下MyBatis) →
    • 如果正确,那么就提示登录成功
    • 如果错误,那么刷新登录页面

任务拆解:

  1. 包含登录表单的 login.html文件,放在webapp目录下
  2. 开发UserServlet
    1. /user/login对应的处理方法,使用MyBatis做查询
    2. /user/info对应的处理方法
  3. 整合MyBatis,在应用程序中维护SqlSessionFactory实例
  • Mybatis的配置:
public interface UserMapper {
    List<User> selectByUserNameAndPassword
            (@Param("username") String username, @Param("password") String password);

    User selectByPrimaryKey(Integer id);
}
<mapper namespace="com.coo1heisenberg.demo2.mapper.UserMapper">

    <select id="selectByUserNameAndPassword" resultType="com.coo1heisenberg.demo2.bean.User">
        select id, username, password, age, birthday, createDate, mobile from test_user
        <where>
            username = #{username} and password = #{password}
        </where>
    </select>

    <select id="selectByPrimaryKey" resultType="com.coo1heisenberg.demo2.bean.User">
        select id, username, password, age, birthday, createDate, mobile from test_user
        <where>
            id = #{id}
        </where>
    </select>
</mapper>
  • Servlet的配置
@WebServlet("/user/*")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    private void process(HttpServletRequest request, HttpServletResponse response) {
        String requestURI = request.getRequestURI();
        String operation = null;
        operation = requestURI.substring(requestURI.lastIndexOf("/") + 1);

        switch (operation) {
            case "login":
                login(request, response);
                break;
            case "info":
                info(request, response);
                break;
        }
    }

    @SneakyThrows
    private void info(HttpServletRequest request, HttpServletResponse response) {
        Object user = request.getAttribute("user");
        response.getWriter().println(user);
    }

    @SneakyThrows
    private void login(HttpServletRequest request, HttpServletResponse response) {
        // 1. 首先获得username和password
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 2. 查询user记录
        UserMapper userMapper = MybatisUtil.getSqlSession().getMapper(UserMapper.class);
        List<User> users = userMapper.selectByUserNameAndPassword(username, password);

        // 3. 根据user记录判断登录状态
        response.setContentType("text/html;charset=utf-8");
        // 4. 判断登录状态 user的list是否为空
        if (users == null || users.size() == 0) {
            // 如果登陆失败(list == null || list.size() == 0)
            // 刷新到refresh --> 2;url=/demo2/login.html
            // 响应登录失败信息
            response.getWriter().println("登录失败,即将跳转登录页面");
            response.setHeader("refresh", "2;url=/demo2/login.html");
        } else {
            // 如果登录成功(list.size > 0)
            // 响应登录成功信息
            response.getWriter().println("登录成功");
            request.setAttribute("user", users.get(0));
            request.getRequestDispatcher("/user/info").forward(request, response);
            // 跳转到info -> 分享user的id信息(直接分享user信息)
        }
    }
}

  • HTML的配置
<body>
<h1>登录页面</h1>
<!--action:表示当前表单中的内容提交给哪个页面进行处理-->
<!--method:表示当前表单提交的方式,常见的有get和post方式,默认是get提交-->
<form action="/demo2/user/login" method="post">
  用户名:<input type="text" name="username"><br>
  密码:<input type="password" name="password"><br>
  <input type="submit">
</form>

</body>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/494263.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python Flask扩展:如何查找高效开发的第三方模块(库/插件)

如何找到扩展以及使用扩展的文档 一、背景二、如何寻找框架的扩展&#xff1f;三、找到想要的扩展四、找到使用扩展的文档五、项目中实战扩展 一、背景 刚入门python的flask的框架&#xff0c;跟着文档学习了一些以后&#xff0c;想着其实在项目开发中&#xff0c;经常会用到发…

设计模式之建造者模式精讲

也叫生成器模式。将一个复杂的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 在建造者模式中&#xff0c;有如下4个角色&#xff1a; 抽象建造者&#xff08;Builder&#xff09;&#xff1a;用于规范产品的各个组成部分&#xff0c;并进行抽象&…

HTTP请求走私!!!(一)

想都是问题&#xff0c;做才是答案 什么是请求走私&#xff1f; HTTP请求走私是针对于服务端处理一个或者多个接收http请求序列的方式&#xff0c;进行绕过安全机制&#xff0c;实施未授权访问一种攻击手段&#xff0c;获取敏感信息&#xff0c;并直接危害其他用户。 Web 应用…

集合系列(十五) -CopyOnWriteArrayList详解

一、摘要 在介绍 CopyOnWriteArrayList 之前&#xff0c;我们一起先来看看如下方法执行结果&#xff0c;代码内容如下&#xff1a; public static void main(String[] args) {List<String> list new ArrayList<String>();list.add("1");list.add(&quo…

RabbitMQ(简单模式)

2种远程服务调用 1openFeign&#xff1a; 优点&#xff1a;能拿到被调用的微服务返回的数据&#xff0c;系统系耦度高&#xff0c;系统稳定。 缺点&#xff1a;同步调用&#xff0c;如果有很多服务需要被调用&#xff0c;耗时长。 MQ,消息队列&#xff0c;RabbitMQ是消息we…

windows DNS 服务器常用配置

Windows Server 上的 DNS 服务器配置主要包括以下步骤和常见设置&#xff1a; 安装 DNS 服务 打开服务器管理器&#xff0c;在 "角色和功能" 添加或删除角色中安装 DNS 服务器角色。 配置 DNS 服务器基础设置 添加 DNS 区域&#xff1a; 在 DNS 管理器中&#xff…

WPF 窗体样式 WindowStyle 设置 none, 如何移动窗体

当窗体样式设为None时&#xff0c;因为标题栏被隐藏&#xff0c;我们无法移动窗体&#xff0c;为了使窗体可以移动&#xff0c;我们要为window中的布局控件添加MouseDown事件的事件处理器&#xff0c;并且要为其设置一个背景(window设置为允许透明&#xff0c;当grid没有背景时…

书籍推荐|meta分析R语言实践教程-Doing Meta-Analysis with R: A Hands-On Guide

“The problems are solved, not by giving new information, but by arranging what we have known since long.” – Ludwig Wittgenstein 推荐理由 《Doing Meta-Analysis with R: A Hands-On Guide》是由 Mathias Harrer, Pim Cuijpers, Toshi Furukawa, 和 David Ebert所…

Hides for Mac:应用程序隐藏工具

Hides for Mac是一款功能强大的应用程序隐藏工具&#xff0c;专为Mac用户设计。它能够帮助用户快速隐藏当前正在运行的应用程序窗口&#xff0c;保护用户的隐私和工作内容&#xff0c;避免不必要的干扰。 软件下载&#xff1a;Hides for Mac下载 Hides for Mac的使用非常简单直…

Windows下载使用nc(netcat)命令

‘nc’ 不是内部或外部命令&#xff0c;也不是可运行的程序&#xff1f; 点击链接地址&#xff0c;下载压缩包。 完成后解压 使用方式&#xff08;三种&#xff09;&#xff1a; 1、直接双击exe使用 2、把这个exe放到cmd启动的默认路径下 放到默认路径下&#xff0c;使用nc&a…

0.96寸OLED屏调试 ----(一)

所需设备&#xff1a; 1、USB 转 SPI I2C 适配器&#xff1b;内附链接 2、0.96寸OLED显示模块&#xff1b; 备注&#xff1a;专业版、升级版都适用&#xff1b; 首先介绍一下OLED显示模块&#xff0c;SSD1306是一款OLED驱动芯片&#xff0c;拥有最大128*64像素支持&#xff…

亚马逊云科技:基于老服务器打造的旧实例类型

内容摘要&#xff1a; 2021年&#xff0c;距离第一个EC2实例上线已经十五周年了。 在漫长的开发过程中&#xff0c;很多EC2实例自然会基于旧服务器构建。 随着时间的推移&#xff0c;旧的服务器总是需要更换硬件&#xff0c;实例也得更换&#xff0c;但并不是所有的用户都想迁…

腾讯云免费云服务器申请流程详解

随着云计算的普及&#xff0c;越来越多的企业和个人开始选择使用云服务器。腾讯云作为国内领先的云计算服务提供商&#xff0c;为用户提供了丰富的云产品和服务。本文将为大家详细介绍腾讯云免费云服务器的申请流程。 一、注册腾讯云账号 首先&#xff0c;需要注册一个腾讯云账…

【氮化镓】镁激活退火对p-GaN迁移率和阈值电压的影响

【Mg activation anneal of the p-GaN body in trench gate MOSFETs and its effect on channel mobility and threshold voltage stability】 文献总结&#xff1a; 本研究探讨了在沟道栅MOSFETs中&#xff0c;镁&#xff08;Mg&#xff09;激活退火步骤对p型氮化镓&#xf…

python opencv稍基础初学

傅里叶变换 傅里叶变换f​​​​​傅里叶分析之掐死教程&#xff08;完整版&#xff09;更新于2014.06.06 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/19763358 相当nice 傅里叶变换的作用 高频&#xff1a;变化剧烈的灰度分量&#xff0c;例如边界 低频&#xff1a;变…

如何使用极狐GitLab 自定义 Pages 根域名

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了极狐GitLab Pages …

【Ollama】AI大模型本地部署

Ollama Ollama轻量级、可扩展的框架&#xff0c;用于在本地机器上构建和运行大型语言模型&#xff08;LLM&#xff09;。提供了一个简单的API来创建、运行和管理模型&#xff0c;以及一个预构建模型库&#xff0c;可以轻松用于各种应用程序。 明显优势&#xff1a;易于使用、…

大模型prompt工程学习(一)

目录 调prompt的方法 prompt时好时不好 大模型本质是没有记忆的 划重点:我们发给大模型的 prompt&#xff0c;不会改变大模型的参数 ГLets think step by step」 一步步分析一下 自洽性&#xff0c;同时跑多次&#xff0c;来减少幻觉 逻辑&#xff0c;基本能力来是要有…

【数据结构】计数排序

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解计数排序&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 基本思想二. 计数排序代码 一. 基本思想 计数排序又称为鸽巢原理&#xff0c;是对哈希直…

【爬虫基础】第6讲 opener的使用

在爬虫中&#xff0c;opener是一个用来发送HTTP请求的对象。它可以用来模拟浏览器发送请求&#xff0c;包括设置请求头、处理Cookie等操作。使用opener可以实现一些高级功能&#xff0c;如模拟登录、处理验证码等。 方法1&#xff1a; from urllib.request import Request,bu…