20. Введение в сервлет — введение и использование ответа

20. Введение в сервлет — введение и использование ответа

Обзор ответов

В предыдущих главах мы уже знали соответствующие функции запроса-запроса, поэтому давайте продолжим разбираться в ответе-ответе.

8cc53256cecf8aa3acb5ceb7fa54f619.png
изображение-20210108214841273

Обзор HttpServletResponse

В Servlet API определен интерфейс HttpServletResponse (параметры методов doGet, doPost), который наследуется от интерфейса ServletResponse и специально используется для инкапсуляции ответных сообщений HTTP. Поскольку сообщение ответа HTTP разделено на три части: строка ответа, заголовок ответа и тело ответа, методы отправки кода состояния ответа, заголовка ответа и тела ответа клиенту определяются в интерфейсе HttpServletResponse.

эффект

  • Три части ответа операции (строка ответа, заголовок ответа, тело ответа)

краткое содержание

  1. Response представляет объект ответа, прототипом является HttpServletResponse, созданный сервером, и есть методы doGet()/doPost() в виде формальных параметров

  2. Роль ответа

  • Три части ответа операции (строка, заголовок, тело)

Response задает код состояния ответа (строка ответа операции)

Когда сервлет возвращает информацию об ответе в браузер, вы можете установить код состояния ответа, возвращаемый в браузер.

Например:

HTTP/1.1 200

Вы можете использовать метод setStatus(int sc) для установки кода состояния ответа:

d48e4c98e8a8d33a91d5324d4aab0584.png

картинка/

Обычно используемые коды состояния:

200: успех

302: перенаправление

304: доступ к кешу

404: Ошибка клиента

500: Ошибка сервера

Давайте напишем демо, чтобы продемонстрировать это.

1. Создайте демонстрационную программу сервлета и установите код состояния ответа 403.

037a581640f5255ecb8c77bc8c4f6c0f.png

изображение-20210108220708037
@WebServlet("/ResponseDemo1")
public class ResponseDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("访问 ResponseDemo1 ....");
        //设置响应状态码: 403 forbidden
        response.setStatus(403);
    }
}

2. Проверить доступ в браузере

c77e04efcc7a56860f66d67e97fead67.png

изображение-20210108220811810

3. Резюме

  1. Установить API: response.setStatus(int code);

  2. Как правило, никаких настроек не требуется, возможно, необходимо установить перенаправление 302.

  3. Общие коды состояния ответа

  • 200 успешных

  • 302 редирект

  • 304 кэш чтения

  • 404 ошибка клиента

  • 500 ошибка сервера

Ответ устанавливает заголовок ответа обновления для выполнения временного перехода (заголовок ответа операции).

Мы узнали, как использовать Response для установки кода состояния ответа выше, поэтому давайте поработаем с заголовком ответа.

1. Введение в API для управления заголовками ответов

Заголовок ответа: указывает ли сервер браузеру, что делать

Ключ соответствует значению

8676437153927e0387f2f10d4d853e2f.png

Один ключ соответствует нескольким значениям

59563cd9797e0767ac92282991b5003c.png

Рассматриваемый метод: setHeader (имя строки, значение строки);

Общие заголовки ответов

Обновить: скачок по времени (например, сервер сообщает браузеру перейти к Baidu через 5 секунд)

Местоположение: адрес перенаправления (например, сервер указывает браузеру перейти на xxx)

Content-Disposition: Скажите браузеру загрузить

Content-Type: Установите MIME-тип содержимого ответа (сервер сообщает браузеру тип содержимого)

Давайте продемонстрируем, как Refresh выполняет временные скачки.

2. Создайте демонстрационную программу сервлета и настройте заголовок ответа так, чтобы он регулярно переходил

9a52a57a52684f6468d7f96de1446c2f.png

изображение-20210108223112151
@WebServlet("/ResponseDemo2")
public class ResponseDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //目标: 让浏览器在访问ResponseDemo2后三秒,跳转到百度首页
        System.out.println("ResponseDemo2收到了请求。。。");
        //通过"Refresh"响应头
        response.setHeader("Refresh","3;url=https://www.baidu.com");
    }
}

3. Тестовый доступ в браузере

f88b2916ec54173a9ae99ed6d2c30c34.png

изображение-20210108224213961

Подождав 3 секунды, он автоматически перейдет к Baidu следующим образом:

203fd7ce9648ce308dd7fb71dd74da4e.png

изображение-20210108224233411

Ответ инициирует перенаправление (заголовок ответа операции)

Выше мы реализовали временной скачок, установив заголовок ответа, поэтому давайте теперь рассмотрим перенаправление.

1. Ответ устанавливает заголовок ответа Location для перенаправления (немедленный переход).

Сначала создайте программу сервлета для демонстрации перенаправления следующим образом:

fe33a07eb40694be39f50499ea9f0e8b.png

изображение-20210108225507845
@WebServlet("/ResponseDemo3")
public class ResponseDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ResponseDemo3收到了一个请求...");
        //目标1:浏览器访问ResponseDemo3,会跳转到百度首页
        //重定向跳转的步骤:1. 设置响应状态码为302  2. 设置响应头Location的值为要跳转到的地址
        response.setStatus(302);
        response.setHeader("Location","https://www.baidu.com");
    }
}

2. Тестовый доступ браузера, обнаружил, что браузер работает успешно и сразу переходит на Baidu.

Посетите http://localhost:8080/ResponseDemo3

43191cdb347ad81de0ee67baee7ad1f8.png

изображение-20210108225751120

В этом тесте мы можем убедиться, что перенаправления могут быть перенаправлены на ресурсы вне проекта. Итак, давайте направим его на ресурсы в проекте, чтобы увидеть.

3. Установите перенаправление на ресурсы в проекте

3.1 Создайте index.html в WEB-INF

b3f875418e4025b160b6d4cc5fc0edb8.png

изображение-20210108230052784

3.2 Установите перенаправление на index.html в сервлете следующим образом:

1745652f83355573c310bc103ecc1ea6.png

изображение-20210108231529080
@WebServlet("/ResponseDemo3")
public class ResponseDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ResponseDemo3收到了一个请求...");
        //目标1:浏览器访问ResponseDemo3,会跳转到百度首页
        //重定向跳转的步骤:1. 设置响应状态码为302  2. 设置响应头Location的值为要跳转到的地址
//        response.setStatus(302);
//        response.setHeader("Location","https://www.baidu.com");

        //目标2:浏览器访问ResponseDemo3,会跳转到本项目的index.html页面
        response.setStatus(302);
        response.setHeader("Location","/index.html"); // 路径设置: /项目部署路径/文件在webapp下的路径
    }
}

Используйте браузер для доступа к http://localhost:8080/ResponseDemo3 следующим образом:

8c56021e6ce73b0a0cfdaf9cc847875e.png

изображение-20210108231635621

Могу ли я получить доступ к ресурсам в WEB-INF?

3.3 Попытка перенаправления на ресурсы в WEB-INF

1b80ee3c5b36eae2b745e31da1a410fd.png

изображение-20210108231939579

Видно, что браузер не может получить доступ к ресурсам в WEB-INF, поэтому на него нельзя перенаправить.

3.4 Сокращенное перенаправление с помощью sendRedirect

В приведенном выше, поскольку мы перенаправляем, чтобы установить код ответа или установить заголовок запроса, есть ли сокращенный метод? Конечно есть, см. ниже.

81954971877d6e20a9aa6cf83e5f936f.png

изображение-20210108232209845
// 重定向的简写方法
response.sendRedirect("/index.html");

Протестируйте его в браузере следующим образом:

b2598b19aa343ac9e67f0bcb5f3ce417.png

изображение-20210108232249318

Видно, что эффекта перенаправления можно добиться, поэтому нам просто нужно запомнить этот способ написания.

4. Резюме

0b66dd8ca6ac1abaf40e690d8397b859.png

картинка/
  1. Перенаправления заставляют браузер делать два запроса

  2. Путь перенаправленной адресной строки меняется

  3. Напишите абсолютный путь для перенаправленного пути (с доменным именем/ip-адресом, если он находится в том же проекте, доменное имя/ip-адрес можно не указывать)

  4. Путь перенаправления может быть как внутри проекта, так и за его пределами (например, Baidu).

  5. Перенаправления не могут перенаправлять на ресурсы в WEB-INF

  6. Хранить данные в запросе, перенаправление недоступно

//方式一: 重定向
//1.设置状态码
//response.setStatus(302);
//2.设置重定向的路径(绝对路径,带域名/ip地址的,如果是同一个项目里面的,域名/ip地址可以省略)
//response.setHeader("Location","https://www.baidu.com");
//response.setHeader("Location","/index.html");

//方式二:  直接调用sendRedirect方法, 内部封装了上面两行
response.sendRedirect("/index.html");
  • перенаправить

response.sendRedirect("重定向的路径");

Сравнение перенаправления и переадресации запроса

f4877fdc79e94a51d7b6bbf98e62e7bc.png

1. Особенности перенаправления:

  1. Переход с перенаправлением инициируется браузером, и во время этого процесса браузер инициирует два запроса.

  2. Переходы перенаправления могут переходить к ресурсам любого сервера, но не могут переходить к ресурсам в WEB-INF.

  3. Переходы перенаправления нельзя использовать с объектами домена запроса.

  4. Адрес в адресной строке браузера станет путем перенаправления

2. Особенности переадресации запросов:

1. 请求转发的跳转是由服务器发起的,在这个过程中浏览器只会发起一次请求
2. 请求转发只能跳转到本项目的资源,但是可以跳转到WEB-INF中的资源
3. 请求转发可以和request域对象一起使用

Используйте поток вывода символов Response для вывода текстового содержимого тела ответа в браузер (тело ответа операции).

1. API для управления телом ответа

ca1bd508a129048d71336b38eb41fa29.png

Вывод страницы может быть достигнут только с использованием одного из потоков, и эти два потока являются взаимоисключающими.

Общее использование:

  • Если вы выводите текстовое содержимое в браузер, то вам нужно вывести символы в браузер, используйтеgetWriter()

  • Если это для загрузки ресурсов, таких как картинки, то вам нужно вывести поток байтов в браузер, используйтеgetOutputStream()

Давайте сначала продемонстрируем ситуацию вывода текстового контента.

2. Используйте getWriter() для вывода текстового содержимого в браузер

2.1 Метод response.getWriter().writer() может выводить только строки, если он выводит int, float и т.д., то будут проблемы

71f27ab0071fcaccbe9964650e49a623.png

изображение-20210109085839072
@WebServlet("/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //要向浏览器输出响应体的信息,需要通过流来进行操作
        //第一种:字符串,输出文本内容
        PrintWriter writer = response.getWriter();
        //使用字符流往浏览器输出文本
        //1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
        writer.write("hello world");
    }
}

Если выводятся типы int и float, об ошибке будет сообщено следующим образом:

60a0c78541470009d40f5a733328e18b.png

изображение-20210109085940913

Видно, что цифры не могут нормально отображаться, так зачем же нужно отображать цифры? В настоящее время он обычно выводится в виде строки следующим образом:

685e2e8e37b843cedce4f21f292b2b11.png

изображение-20210109090049756

Но если вы не хотите этого делать, что вы можете сделать, если хотите напрямую выводить int, float и т. д.? можно использовать writer.print()метод .

2.2 Метод response.getWriter().print() может выводить числа и строки

d43dcf4b86c401e0541bd2c57063e0a8.png

изображение-20210109092911409
//2. print()方法,可以输出数字、字符串
writer.print(123456);

Можно видеть, что использование print()метода действительно может выводить числа, но обычно нам нужно только помнить writer(), что метод должен использоваться для вывода строк.

2.3 Вывод строк китайских символов, появляются искаженные символы

Можно вывести английские строки и числа выше, но когда мы попытаемся вывести китайский контент, будут искажены символы, как показано ниже:

f6c24090067a5e909b2b91eea8c36bf7.png

изображение-20210109093255116

Итак, почему появляются искаженные символы, конечно, это вызвано несовместимыми форматами кодирования. Итак, давайте посмотрим, как решить искаженную проблему.

3. Решить проблему искаженных символов китайского ответа

Проблема искажения китайских символов вызвана несоответствием между форматом кодировки сервера и форматом кодировки браузера. Затем нам нужно только установить формат кодировки сервера на UTF8, а затем сообщить браузеру, чтобы он также установил формат кодировки на UTF8.

Так что, если браузер уведомлен о необходимости установить формат кодировки UTF8? Он может быть установлен следующим образом при ответе:

  • Решить проблему вывода потока символов с искаженными китайскими символами.

response.setContentType("text/html;charset=utf-8");
/*
 * 这句代码底层做了什么?
 * 1. 设置服务器响应的字符集为UTF-8
 * 2. 设置Content-Type响应头的信息为 "text/html;charset=UTF-8"
 *    让浏览器知道了服务器的响应字符集UTF-8,那么浏览器也会使用UTF-8解码
 */

3.1 Демонстрация решения проблемы вывода искаженных китайских символов

5c300f5595296ce850f4b4418b7c2e94.png

изображение-20210109094414469
@WebServlet("/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决响应中文乱码
        response.setContentType("text/html;charset=utf-8");

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

        //2. print()方法,可以输出数字、字符串
//        writer.print(123456);
    }
}

3.2 Ярлыки для настройки формата кодирования ответа

Хотя для решения искаженных китайских символов в ответе требуется всего одна строка кода, запоминать каждый раз довольно сложно. Таким образом, мы можем установить его как ярлык для входа.

Файл | Настройки | Редактор | Живые шаблоны

6d192c623212b9fa5937e3efe34e46ca.png

изображение-20210109094658303

95699273e39e562cc175555e72b1eb8c.png

изображение-20210109094926227
//解决响应中文乱码
response.setContentType("text/html;charset=utf-8");

Результаты теста следующие:

d102337eb473ab797d04b0e4a749399b.png

изображение-20210109094950444

08c28008c2776480888fee88139c2592.png

изображение-20210109095004275

Используйте поток байтов ответа getOutputStream() для вывода содержимого изображения в браузер (тело ответа операции)

Выше мы реализовали вывод содержимого строки в браузер, поэтому, конечно, нам также нужно подумать о том, как вывести содержимое изображения в браузер.

Во-первых, давайте посмотрим, как DefaultServlet по умолчанию обрабатывает статические ресурсы.

DefaultServlet обрабатывает статические ресурсы

1. Скопируйте изображение в каталог веб-приложения

b2d3796fd71b413643b4b7441dc80a1d.png

изображение-20210109101643743

2. Запустите службу tomcat и используйте путь проекта для доступа к ресурсам изображения.

65ec94186c1f4f90e0151f21c5b1c443.png

изображение-20210109101820588

Итак, если вы сами пишете программу сервлета, как реализовать эту функцию?

Напишите свой собственный сервлет и используйте getOutputStream() для вывода ресурсов изображения в браузер.

681320572d17dab4b6adf3ee1526caea.png

изображение-20210109102247476
@WebServlet("/ResponseDemo5")
public class ResponseDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 读取b.jpg图片,将其转换成字节输入流,使用ServletContext
        ServletContext servletContext = getServletContext();
        InputStream is = servletContext.getResourceAsStream("1.jpeg");

        //2. 使用字节输出流,将is中的字节都输出到浏览器
        //2.1 获取响应字节流
        ServletOutputStream os = response.getOutputStream();
        //2.2 读取文件输入流 拷贝到 响应输出字节流
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
        }

        //3.关闭流
        os.close();
        is.close();
    }
}

В приведенном выше коде мы добились эффекта вывода ресурса изображения в браузер, но мы можем его найти.

Каждый раз, когда мы работаем с потоком байтов, нам приходится писать строку буферов потока байтов для копирования в другой выходной поток, что громоздко:

//2.2 读取文件输入流 拷贝到 响应输出字节流
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
        }

Есть ли более простой способ? Конечно есть, то есть он может быть инкапсулирован как публичный метод, и этот публичный метод был предоставлен третьей стороной, и мы можем использовать его напрямую.

Использование инструментов потока ввода-вывода: упростите операцию копирования байтовых потоков.

  • Представляем jar-пакет commons-io

  • Используйте commons-io для упрощения операции копирования потока байтов.

1. Используйте Maven для импорта зависимостей пакета jar от commons-io.

1.1 Посетите склад Maven и найдите зависимости commons-io

Посетите https://mvnrepository.com и найдите commons-io следующим образом:

5fcf11cdf5bb64311bb11a221264abd5.png

изображение-20210109102853302

125a4f92bf16e94ee9faff17482735f4.png

изображение-20210109103030512

afb56b7be8a1820d2e701a46fe9c261e.png

изображение-20210109103057156
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

1.2 Импорт зависимостей координат commons-io в pom.xml проекта

da7104d8670fd643172d95388ee78533.png

изображение-20210109103247691
<!-- 导入 commons-io       -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

2. Используйте метод IOUtils.copy(is,os); в commons-io, чтобы скопировать поток

023c1f905a3d653d308bd0963fd1a6a8.png

изображение-20210109103429361

c6c97296f33a991f77a7fb2ba6fc167e.png

изображение-20210109103529178
import org.apache.commons.io.IOUtils;

//2.2 使用 commons-io 中的 IOUtils.copy(is,os); 方法来拷贝流
IOUtils.copy(is, os);

3. Просмотр исходного кода IOUtils.copy(is, os)

16dde66bf46e3a02a35cc60da2f93e99.png

изображение-20210109103717733

f16f690ea99e065e3eaa9f353dbc220c.png

изображение-20210109103730824

Видно, что, по сути, этот метод копирования копирует и байтовый поток, но лучше пакетный, которым удобно пользоваться всем нам.

Резюме ответов

  1. Установите код состояния ответа: setStatus()

  2. Установите заголовок ответа: setHeader (имя, значение)

    1. Заголовок ответа на обновление используется для перехода на определенную страницу через несколько секунд.

    2. заголовок ответа местоположения, используемый для перенаправления на определенную страницу

  3. Написание перенаправления: sendRedirect(адрес)

  4. Установить содержимое тела ответа

    1. response.getOutputStream() получает поток вывода байтов

    2. response.getWriter() получает поток вывода символов

    3. строка вывода Writer.write()/print()

    4. Устраните искаженные китайские символы данных ответа: response.setContentType("text/html;charset=UTF-8")

    5. Вывод текстового содержимого с использованием потока вывода символов

    6. выходной файл с использованием байтового потока вывода

  5. Используйте структуру потока ввода-вывода для чтения и записи

Supongo que te gusta

Origin blog.csdn.net/u012887259/article/details/121219917
Recomendado
Clasificación