ответ, объект запроса
Tomcat получает http-запрос от клиента и создает отдельный для каждого запроса.Объект запроса, представляющий запрос,а такжеобъект ответа, представляющий ответ
Поскольку объект запроса представляет собой HTTP-запрос, мыПолучить данные, отправленные браузером, и найти объект запросаВот и все. Объект ответа представляет ответ http, затем мыВывести данные в браузер и найти объект ответаВот и все.
Что такое объект HttpServletResponse?
HTTP-ответ состоит из строки состояния, содержимого сущности, заголовков сообщений и пустой строки.Объект HttpServletResponse инкапсулирует информацию ответа http.
Применение HttpServletResponse
Вызовите метод getOutputStream() для вывода данных в браузер.
- Вызовите метод getOutputStream() для вывода данных в браузер,Метод getOutputStream() может использовать print() или write()., какая между ними разница? Давайте попробуем. код показывает, как показано ниже
//获取到OutputStream流
ServletOutputStream servletOutputStream = response.getOutputStream();
//向浏览器输出数据
servletOutputStream.print("aaaa");
- Выход успешный, вроде ничего страшного в этом нет.
- Попробуем вывести китайский
//获取到OutputStream流
ServletOutputStream servletOutputStream = response.getOutputStream();
//向浏览器输出数据
servletOutputStream.print("中国!");
- Что-то пошло не так! ! !
- Почему есть исключение? В ио мы узнали,outputStream - это вывод двоичных данных,Метод print() получает строку,Метод print () должен преобразовать «Китай» в двоичные данные, Tomcat использует кодировку IOS 8859-1 для его преобразования, «Китай» вообще не поддерживает кодировку ISO 8859-1.. Так что есть исключение
- Давайте еще раз посмотрим на метод write(), сначала выводя данные на английском языке в браузер.
response.getOutputStream().write("aaa".getBytes());
- нет проблем
- Попробуйте снова вывести китайские данные
response.getOutputStream().write("你好呀我是中国".getBytes());
- Кажется, нет проблем.
- Зачем использовать метод write() для нормального вывода китайского языка в браузер?
"你好呀我是中国".getBytes()
Этот код находится вПри преобразовании в массив byte[] по умолчанию используется кодировка gb2312., а **"Привет, я из Китая" поддерживает кодировку gb2312**, поэтому может отображаться нормально. - Тем не менее, программаДля универсальности следует использовать кодировку UTF-8.,мы вУкажите кодировку UTF-8 при преобразовании строки в массив байтов, и посмотрим, что произойдет.
response.getOutputStream().write("你好呀我是中国".getBytes("UTF-8"));
- Хорошо, успешно испортил это! ! !
- Почему оно стало искаженным? Причина в следующем: я вывожу на серверКитайский кодируется в UTF-8, а браузер использует GBK, который хочет отображать китайские данные в UTF-8.!
- В этом случае я попробую изменить кодировку браузера на UTF-8.
- Испорченная проблема снова решена. Однако каждый разНужно ли переходить на веб-страницу, чтобы изменить формат кодировки при написании программ UTF-8? это очевидно невозможно.
- Поскольку ответ HTTP имеет заголовок сообщения, который сообщает браузеру, какой тип данных отправляется обратно, объект HttpServletResponse должен иметь соответствующий метод, сообщающий браузеру, какой формат кодирования данных.
- Итак, я пошел искать Servlet API и нашел его.Как настроить заголовки сообщений
//设置头信息,告诉浏览器我回送的数据编码是utf-8的
response.setHeader("Content-Type", "text/html;charset=UTF-8");
response.getOutputStream().write("你好呀我是中国".getBytes("UTF-8"));
- Когда браузер отображает данные, он автоматически заменяет формат кодировки страницы на UTF-8., проблема с искажениями также решена
-
Кроме того, вместо использования метода объекта HttpServletResponse для установки заголовков сообщений я могуИспользуйте HTML-теги для имитации заголовка HTTP
-
Вот код:
//获取到servletOutputStream对象
ServletOutputStream servletOutputStream = response.getOutputStream();
//使用meta标签模拟http消息头,告诉浏览器回送数据的编码和格式
servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
servletOutputStream.write("我是中国".getBytes("UTF-8"));
- Искаженная проблема также может быть решена
Вызовите метод getWriter() для вывода данных в браузер.
- Для метода getWriter() это подкласс Writer, тогдаМожет выводить в браузер только символьные данные, а не двоичные данные
- Используйте метод getWriter() для вывода данных на китайском языке, код выглядит следующим образом:
//获取到printWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("看完博客点赞!");
- То, что мне нравится слышать и видеть, произошло снова, и я снова исказил символы.
- Почему существует искаженный код? Поскольку Tomcat написан иностранцами,Кодировка Tomcat по умолчанию — ISO 8859-1., когда мы выводим китайские данные,Tomcat будет кодировать наши данные в соответствии с кодовой таблицей ISO 8859-1. Китайский язык не поддерживает эту кодовую таблицу., так что там искажено
- В таком случае, почему бы мне не установить кодировку?Код выглядит следующим образом:
//原本是ISO 8859-1的编码,我设置成UTF-8
response.setCharacterEncoding("UTF-8");
//获取到printWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("看完博客点赞!");
- Я посетил снова и о мой! Это выглядит грязнее!
- Почему до сих пор не решена кривая проблема? Внимательные друзья обнаружат, что я всего лишьПри преобразовании китайского языка установите кодовую таблицу в UTF-8.,ноБраузер не обязательно использует кодовую таблицу UTF-8 для отображения данных.
- Хорошо, давайте посмотрим на формат кодировки браузера, браузер использует GB2312 для отображения данных UTF-8.
- Мы уже решили эту проблему двумя способами [используя теги для имитации заголовков сообщений и устанавливая заголовки сообщений], и Servlet также предоставляет нам метод
//设置浏览器用UTF-8编码显示数据
response.setContentType("text/html;charset=UTF-8");
- Ладно, зайдем еще
-
Поскольку в Servlet так много способов решить проблему искаженных символов, есть ли самый простой? Вот так! Следующий способ самый простой, онНе только настройте браузер на использование UTF-8 для отображения данных, но также установите внутреннюю кодовую таблицу китайского транскодирования на UTF-8., то есть,
response.setContentType("text/html;charset=UTF-8");
Пучокresponse.setCharacterEncoding("UTF-8")
дела сделаны! -
Используйте getWriter() для отображения данных на китайском языке, вам нужен только один метод!
//设置浏览器用UTF-8编码显示数据,
response.setContentType("text/html;charset=UTF-8");
//获取到printWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("看完博客点赞!");
Реализовать загрузку файлов
Скачивание ресурсов также очень распространено в нашей повседневной жизни, как это делается?Чтобы иметь возможность скачивать для других, на сервере должен быть этот ресурс
- Теперь у меня есть фотография под моим сайтом!
-
Так как все запросы на поиск сервлета отправляет браузер, то я напишу сервлет,Когда другие посещают мой сервлет, они могут скачать мою картинку!
-
Загрузка и скачивание файлов в java выполняются через поток io.Поскольку вы хотите загрузить изображение, вы должны сначала иметь возможность его прочитать.
//获取到资源的路径
String path = this.getServletContext().getRealPath("/download/1.png");
//读取资源
FileInputStream fileInputStream = new FileInputStream(path);
//获取到文件名,路径在电脑上保存是\\形式的。
String fileName = path.substring(path.lastIndexOf("\\") + 1);
- Сообщить браузеру, что я хочу скачать этот файл
//设置消息头,告诉浏览器,我要下载1.png这个图片
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
- Отправить прочитанное содержимое обратно в браузер
//把读取到的资源写给浏览器
int len = 0;
byte[] bytes = new byte[1024];
ServletOutputStream servletOutputStream = response.getOutputStream();
while ((len = fileInputStream.read(bytes)) > 0) {
servletOutputStream.write(bytes, 0, len);
}
//关闭资源
servletOutputStream.close();
fileInputStream.close();
-
Когда я захожу, браузер предлагает загрузить.
-
Его также можно успешно открыть!
- Теперь опять проблема, а что если имя моего файла китайское?
- Давайте снова зайдем и обнаружим, что имя искажено (хотя оно искажено)
- Чтобы решить искаженное имя файла, нам нужно выполнить кодирование URL, код показан ниже:
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
- При повторном доступе проблема с искаженными именами файлов решена!
Реализовать автоматическое обновление
Обновляйте страницу в указанное время для обновления ресурсов
- Пусть браузер достигнет автоматического обновления, он должен снова модифицировать заголовок сообщения.
//每3秒自动刷新网页一次
response.setHeader("Refresh", "3");
- Чтобы лучше видеть результаты, мы добавляем ценность во время
response.getWriter().write("time is :" + System.currentTimeMillis());
- Значение времени меняется каждые три секунды
- После изучения вышеизложенного кажется, что это бесполезно.Кто может видеть такие вещи, когда они в сети.Автоматическое обновление, способное реализовать переход на страницу】
- После того, как мы войдем на сайт, много раз мы увидим [Успешный вход, автоматический переход через 3 секунды....], на самом деле это делается с помощью Refresh.
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("3秒后跳转页面.....");
//三秒后跳转到index.jsp页面去,web应用的映射路径我设置成/,url没有写上应用名
response.setHeader("Refresh", "3;url='/index.jsp'");
- Эффект взгляда
установить кеш
Сам браузер имеет механизм кэширования
- Когда я впервые посетил index.jsp, браузер отправил на сервер два запроса [один для веб-страницы и один для изображения]
- Когда я посещаю index.jsp во второй раз,Браузер кэширует изображение! Изображение не перезагружается, оно взято из кеша.
- Веб-страницы, такие как типы акций, не могут получить доступ к кэшированным данным, и данные должны постоянно обновляться. Ниже я отключу функцию кеша
//浏览器有三消息头设置缓存,为了兼容性!将三个消息头都设置了
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma", "no-cache");
//这里为了看效果
PrintWriter printWriter = response.getWriter();
printWriter.print("你好啊" + new Date().toString());
- Конечно,Если какие-то данные на странице долго не обновляются, вы можете установить их как кеш, что может повысить производительность сервера
Реализовать сжатие данных
Объем информации на веб-странице очень велик, еслиНе сжимайте данные и не отправляйте их обратно в браузер, который очень интенсивно использует трафик.
- Теперь у меня есть статья для вывода в браузер
response.setContentType("text/html;charset=UTF-8");
String ss = "fsdfhsdfhuisdhfusdhfuids" +
"fsdfdsfsdfsdfdsfdafdsfhsdjfhsdjkfhkjds" +
"fdsfjdslkfjsldkfjsdlkfjsdkfsdjkff" +
"fsjdfjdsklfjdsklfjkldsfjlksdjflksdjflkds" +
"dsjfklsdjflsdjfkldsfkjsdkfjsldkfjsdlfk" +
"fdsjlkfjdslkfjsdlkfjlkasjflk";
response.getWriter().write("原来的长度是:"+ss.getBytes().length+"</br>");
//输出给浏览器
response.getWriter().write(ss);
- Посетите, чтобы увидеть,Оригинальная длина 201
- Каков принцип сжатия? мы знаемИ getOutputStream(), и getWriter() выводят данные непосредственно в браузер.. Теперь все, что мне нужно сделать, этоЧтобы данные не выводились напрямую в браузер, позвольте мне сначала их сжать, а потом выводить в браузер.Java предоставляет нам класс сжатия GZIP.
- Давайте используем класс GZIP для сжатия данных
//GZIP的构造方法需要一个OutputStream子类对象,究竟哪个对象适合,我们看下write()方法
GZIPOutputStream gzipOutputStream = new GZIPOutputStream();
//查看了下API,write()接收的是byte[]类型的。
gzipOutputStream.write();
- Так что яПередайте ему ByteArrayOutputStream в конструкторе
//既然是byte[]类型,那么我就给他一个ByteArrayOutputStream
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new ByteArrayOutputStream());
- и использоватьКогда GZIPOutputStream записывает данные, он записывает данные в ByteArrayOutputStream, а позже извлекает данные и записывает их в браузер., такВы не можете указать GZIPOutputStream как анонимный внутренний класс, вы должны определить ByteArrayOutputStream,
//创建GZIPOutputStream对象,给予它ByteArrayOutputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
//GZIP对数据压缩,GZIP写入的数据是保存在byteArrayOutputStream上的
gzipOutputStream.write(ss.getBytes());
//gzipOutputStream有缓冲,把缓冲清了,并顺便关闭流
gzipOutputStream.close();
- ПучокСжатые данные вынимаются и записываются в браузер
//将压缩的数据取出来
byte[] bytes = byteArrayOutputStream.toByteArray();
//将压缩的数据写给浏览器
response.getOutputStream().write(bytes);
- Сравним размер до сжатия и размер после сжатия
- Данные действительно сжаты, но почему они снова искажены? очень просто, так какВы сжимаете данные, вы пишете их в браузер, браузер не знает, что это сжатые данные, он открывает данные в обычном режиме. Это, конечно, приводит к искажению символов! , теперь я хочуСкажите браузеру, что я сжимаю данные.
//告诉浏览器这是gzip压缩的数据
response.setHeader("Content-Encoding","gzip");
//再将压缩的数据写给浏览器
response.getOutputStream().write(bytes);
- посетить снова
Генерировать случайные картинки
Очень часто генерируются случайные изображения.Когда мы входим в систему, нам часто приходится писать коды подтверждения, и эти коды подтверждения представляют собой картинку, которая записывается в браузер через HttpServletResponse.
- Чтобы создать изображение,java предоставляет класс BufferedImage для использования
//在内存中生成一张图片,宽为80,高为20,类型是RGB
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//获取到这张图片
Graphics graphics = bufferedImage.getGraphics();
//往图片设置颜色和字体
graphics.setColor(Color.BLUE);
graphics.setFont(new Font(null, Font.BOLD, 20));
//往图片上写数据,先写个12345,横坐标是0,纵坐标是20【高度】
graphics.drawString("12345", 0, 20);
- Хорошо, теперь создаем образ в памяти и пишем 12345. Далее мы будемЗаписать изображение в браузер.Запишите изображение в браузер, и java предоставит нам поток изображений [ImageIO].
//要往浏览器写一张图片,那要告诉浏览器回送的类型是一张图片
response.setHeader("ContentType", "jpeg");
//java提供了图片流给我们使用,这是一个工具类
//把图片传进去,类型是jpg,写给浏览器
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
- Давайте посетим и посмотрим, как выглядит картина
- Это так некрасиво, давайте изменим фон на белый и посмотрим
//把白色填充整张图片
graphics.setColor(Color.white);
graphics.fillRect(0, 0, 80, 20);
- Посмотрите на эффект еще раз, он явно намного лучше
- Хорошо, наши номера картинок не могут быть написаны от руки, числа должны генерироваться случайным образом! **Это просто. Теперь я хочу сгенерировать 7-значное случайное число, метод генерации случайного числа выглядит следующим образом
private String makeNum() {
Random random = new Random();
//这样就会生成0-7位的随机数,现在问题又来了,如果随机数不够7位呢?如果不够7位,我们加到7位就行了
int anInt = random.nextInt(9999999);
//将数字转成是字符串
String num = String.valueOf(anInt);
//判断位数有多少个,不够就加
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 7 - num.length(); i++) {
stringBuffer.append("0");
}
return stringBuffer.append(num).toString();
}
- еслиЧтобы сгенерировать китайский язык, просто найдите таблицу сопоставления китайского языка..
перенаправить прыжок
Что такое редирект-прыжок? Нажмите на гиперссылку,Уведомить браузер о переходе на другую страницуЭто называется перенаправление. ** сообщает браузеру о переходе, что очень важно. **Есть два способа перехода между страницами:перенаправить и впередЧто касается того, когда использовать перенаправление и что использовать переадресацию, я подробно объясню, когда закончу говорить об объекте HttpServletRequest.
- Давайте перенаправим, используя следующий объект HttpServletResponse
//重定向到index.jsp页面
response.sendRedirect("/zhongfucheng/index.jsp");
- существуетАдресная строка браузера для доступа к Servlet222
- Перейти на страницу index.jsp, адресная строка изменилась
- мы приходим сновапосмотреть, что случилось с протоколом http
- На картинке мы видим два кода состояния, один из них 302. Один 200.Код состояния 302 представляет собой временное перенаправление в протоколе http.. Например:Я пошел в Дисциплинарную комиссию и сказал: дайте мне бланк на увольнение, я хочу домой. В Дисциплинарном комитете мне сказали: у меня здесь нет бланка на отпуск, идите к вожатому.. Оглянитесь назад, когда я посетил Sevlet222: я искал Servlet222, и Servlet222 сказал браузеру: у меня нет нужного вам ресурса, нужный вам ресурс находится на странице index.jsp, вы можете найти его самостоятельно.
- легко увидетьПо перенаправлению кода 302 состояния 302 и реализации адреса прыжка. Так,Мы можем установить заголовок сообщения http для достижения перенаправления и перехода
//设置状态码是302
response.setStatus(302);
//HttpServletResponse把常用的状态码封装成静态常量了,所以我们可以使用SC_MOVED_TEMPORARILY代表着302
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
//跳转的地址是index.jsp页面
response.setHeader("Location", "/zhongfucheng/index.jsp");
- На самом деле метод sendRedirect() должен инкапсулировать setStatus() и setHeader()., принцип setStatus() и setHeader()
Детали getWriter и getOutputStream
- Два метода getWriter() и getOutputStream() не могут быть вызваны. При одновременном вызове произойдет исключение
- Программа сервлета для объекта ServletOutputStream или PrintWriterЗаписанные данные будут получены из ответа механизмом сервлета, который будет использовать данные в качестве тела ответного сообщения, а затем объединит их со строкой состояния ответа и заголовками ответа и выведет их клиенту..
- СервлетПосле завершения метода serice() [то есть после завершения doPost() или doGet()], обработчик сервлета проверит, вызывал ли объект выходного потока, возвращаемый методом getWriter или getOutputStream, метод close,Если нет, механизм сервлета вызовет метод close, чтобы закрыть объект выходного потока.
Если в статье есть ошибки, пожалуйста, исправьте меня и поделитесь друг с другом. Студенты, которые привыкли читать технические статьи о WeChat, могут обратить внимание на публичный аккаунт WeChat: Java3y.