java servlet 转发和重定向_JavaWeb(一)Servlet中乱码解决与转发和重定向的区别

前言

前面其实已经把Servlet中所有的内容都介绍完了,这篇讲补充一点乱码和重定向与转发之间的区别!

一、request请求参数出现乱码问题

1.1、get请求

1)乱码示例

get请求的参数是在url后面提交过来的,也就是在请求行中。

82bc08117fca9b6ab6e963c7526ed08a.png

6652e48f8cd4255489020b470d68fe86.png

结果:

a15af942aba031a35c9e2a37b9f5dc40.png

Servlet_demo_0040是一个普通的Servlet,浏览器访问它时,使用get请求方式提交了一个username=小明的参数值,在doGet中获取该参数值,并且打印到控制台,发现出现乱码

2)出现乱码原因

前期知识:

码表:是一种规则,用来让我们看得懂的语言转换为电脑能够认识的语言的一种规则,有很多中码表,IS0-8859-1,GBK,UTF-8,UTF-16等一系列码表,

比如GBK,UTF-8,UTF-16都可以标识一个汉字,而如果要标识英文,就可以用IS0-8859-1等别的码表。

编码:将我们看得懂的语言转换为电脑能够认识的语言。这个过程就是编码的作用。

解码:将电脑认识的语言转换为我们能看得懂得语言。这个过程就是解码的作用

这里只能够代表经过一次编码例子,有些程序中,会将一个汉字或者一个字母用不同的码表连续编码几次,那么第一次编码还是上面所说的作用,第二次编码的话,

就是将电脑能够认识的语言转换为电脑能够认识的语言(转换规则不同),那么该解码过程,就必须要经过两次解码,也就是编码的逆过程,下面这个例子就很好的说明了这个问题:

浏览器使用的是UTF-8码表,通过http协议传输,http协议只支持IS0-8859-1,到了服务器,默认也是使用的是IS0-8859-1的码表,看图:

4ecb14434efb511ba0c5289c42d43a88.png

从上面的图中可以看出,就是三个过程,经历了两次编码,所以就需要进行两次解码:

1)浏览器将"小明"使用UTF-8码表进行编码(因为小明这个是汉字,所以使用能标识中文的码表,这也是我们可以在浏览器上可以手动设置的,如果使用了不能标识中文的码表,那么就将会出现乱码,

因为码表中找不到中文对应的计算机符号,就可能会用??等其他符号表示),编码后得到的为 1234 ,将其通过http协议传输。

2)在http协议传输,只能用ISO-8859-1码表中所代表的符号,所以会将我们原先的1234再次进行一次编码,这次使用的是ISO-8859-1,得到的为 ???? ,然后传输到服务器。

3)服务器获取到该数据是经过了两次编码后得到的数据,所以必须跟原先编码的过程逆过来解码,先是UTF-8编码,然后在ISO-8859-1编码,那么解码的过程,就必须是先ISO-8859-1解码,然后在用UTF-8解码,

这样就能够得到正确的数据。????.getBytes("ISO-8859-1");//第一次解码,转换为电脑能够识别的语言, new String(1234,"UTF-8");//第二次解码,转换为我们认识的语言

3)解决方法

a4353bc13a58a4454c6ea4cea137654f.png

结果:

19d9b4cbba2f003bdbdb87c812e9aadf.png

1.2、post请求

post请求方式的参数是在请求体中,相对于get请求简单很多,没有经过http协议这一步的编码过程,所以只需要在服务器端,设置服务器解码的码表跟浏览器编码的码表是一样的就行了,

在这里浏览器使用的是UTF-8码表编码,那么服务器端就设置解码所用码表也为UTF-8就OK了。

设置服务器端使用UTF-8码表解码:

request.setCharacterEncoding("UTF-8");  //命令Tomcat使用UTF-8码表解码,而不用默认的ISO-8859-1了。

所以在很多时候,在doPost方法的第一句,就是这句代码,防止获取请求参数时乱码。

总结请求参数乱码问题:

get请求和post请求方式的中文乱码问题处理方式不同

get:请求参数在请求行中,涉及了http协议,手动解决乱码问题,知道出现乱码的根本原因,对症下药,其原理就是进行两次编码,两次解码的过程

new String(xxx.getBytes("ISO-8859-1"),"UTF-8");

post:请求参数在请求体中,使用servlet API解决乱码问题,其原理就是一次编码一次解码,命令tomcat使用特定的码表解码。

request.setCharaterEncoding("UTF-8");

二、response响应回浏览器出现中文乱码

首先介绍一下,response对象是如何向浏览器发送数据的。两种方法,一种getOutputStream,一种getWrite:

ServletOutputStream getOutputStream();  //获取输出字节流,提供write() 和 print() 两个输出方法。

PrintWriter getWrite();  //获取输出字符流,提供write() 和 print()两个输出方法。

print()方法底层都是使用write()方法的,相当于print()方法就是将write()方法进行了封装,使开发者更方便快捷的使用,想输出什么,就直接选择合适的print()方法,而不用考虑如何转换字节。

2.1、ServeltOutputStream getOutputStream();

df6e29ad4cd0c20cbbedc1f74d4da875.png

结果:不能直接输出中文,直接输出中文会报异常

7157fa2a5b9a929e03d12350faccedbc.png

报异常的源码分析:

8596c11c024fba6138e483e56aa1e794.png

解决方法:

resp.getoutputStream().write("哈哈哈,我要输出到浏览器".getBytes("UTF-8"));

将要输出的汉字先用UTF-8进行编码,而不用让tomcat来进行编码,这样如果浏览器用的是UTF-8码表进行解码的话,那么就会正确输出,如果浏览器用的不是UTF-8,那么还是会出现乱码,

所以说这个关键要看浏览器用的什么码表,这个就不太好,这里还要注意一点,就是使用的是write(byte)方法,因为print()方法没有输出byte类型的方法。

测试:因为我用的是谷歌浏览器它默认使用的是GB2312所以这里使用的是GB2312

2a0449bbfa9c9dea6323203152a9cd66.png

ad63f40bc3239734cb176fa86ae5b3e6.png

2.2、PrintWriter getWrite();

直接输出中文,不会报异常,但是肯定会报异常,因为用ISO-8859-1的码表不能标识中文,一开始就是错的,怎么解码编码读没用了。

有三种方法来让其正确输出中文:

1)使用Servlet API  response.setCharacterEncoding()

response.setCharacterEncoding("UTF-8");  //让tomcat将我们要响应到浏览器的中文用UTF-8进行编码,而不使用默认的ISO-8859-1了,这个还是要取决于浏览器是不是用的UTF-8的码表,跟上面的一样有缺陷。

测试:因为我用的是谷歌浏览器它默认使用的是GB2312所以这里使用的是GB2312

b376fc4a970f7a9f7b046d65b2726450.png

2)通知tomcat和浏览器都使用同一张码表

response.setHeader("content-type","text/html;charset=uft-8");  //手动设置响应内容,通知tomcat和浏览器使用utf-8来进行编码和解码。

charset=uft-8就相当于response.setCharacterEncoding("UTF-8");//通知tomcat使用utf-8进行编码

response.setHeader("content-type","text/html;charset=uft-8");//合起来,就是既通知tomcat用utf-8编码,又通知浏览器用UTF-8进行解码。

response.setContentType("text/html;charset=uft-8");  //使用Servlet API 来通知tomcat和强制浏览器使用UTF-8来进行编码解码,这个的底层代码就是上一行的代码,进行了简单的封装而己。

efe5e10ef2806dc09dcd56a7bed06c3a.png

3)通知tomcat,在使用html通知浏览器 (html源码),注意:建议浏览器应该使用编码,不能强制要求

412b3907d6aa772a4e2c35568c568c55.png

所以response在响应时,只要通知tomcat和浏览器使用同一张码表,一般使用第二种方法,那么就可以解决响应的乱码问题了

三、总结请求和响应的乱码

3.1、请求乱码

get请求:

经过了两次编码,所以就要两次解码

第一次解码:xxx.getBytes("ISO-8859-1");得到yyy

第二次解码:new String(yyy,"utf-8");

连续写:new String(xxx.getBytes("ISO-8859-1"),"UTF-8");

post请求:

只经过一次编码,所以也就只要一次解码,使用Servlet API request.setCharacterEncoding();

request.setCharacterEncoding("UTF-8");  //不一定解决,取决于浏览器是用什么码表来编码,浏览器用UTF-8,那么这里就写UTF-8。

3.2、响应乱码

getOutputStream();:

使用该字节输出流,不能直接输出中文,会出异常,要想输出中文,解决方法如下

解决:getOutputStream().write(xxx.getBytes("UTF-8"));  //手动将中文用UTF-8码表编码,变成字节传输,变成字节后,就不会报异常,并且tomcat也不会在编码,因为已经编码过了,所以到浏览器后,

如果浏览器使用的是UTF-8码表解码,那么就不会出现中文乱码,反之则出现中文乱码,所以这个方法,不能完全保证中文不乱码

getWrite();:

使用字符输出流,能直接输出中文,不会出异常,但是会出现乱码。能用三种方法解决,一直使用第二种方法

解决:通知tomcat和浏览器使用同一张码表。

response.setContentType("text/html;charset=utf-8");  //通知浏览器使用UTF-8解码

通知tomcat和浏览器使用UTF-8编码和解码。这个方法的底层原理是这句话:response.setHeader("contentType","text/html;charset=utf-8");

注意:getOutputStream()和getWrite() 这两个方法不能够同时使用,一次只能使用一个,否则报异常

四、Servlet中请求和转发的区别

4.1、使用方式

1)在servlet中调用转发、重定向的语句如下:

request.getRequestDispatcher("new.jsp").forward(request, response); //转发到new.jsp

response.sendRedirect("new.jsp"); //重定向到new.jsp

2)在jsp页面中你也会看到通过下面的方式实现转发:

当然也可以在jsp页面中实现重定向:

//重定向到new.jsp

示例:

//获取username信息

String username=request.getParameter("username");//转发与重定向

if(username.equals("admin")){//提示用户已存在,不能注册

request.setAttribute("message","该用户已存在,不能注册");//添加提示信息,需要在userCreate.jsp页面中进行提示信息展示

request.getRequestDispatcher("userCreate.jsp").forward(request, response);//转法

}else{//提示注册成功

request.setAttribute("message","注册成功");

response.sendRedirect("indext.jsp");//重定向

}

4.2、区别:重定向和转发的工作流程

c72658f2275feb1807fd38183aaebc91.png

1)转发的工作流程‘

第一步:客户浏览器发送http请求

第二步:web服务器接受此请求

第三步:调用内部的一个方法在容器内部完成请求处理和转发动作

第四步:将目标资源发送给客户;在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,

也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。

2)重定向的工作流程

86b304ecceea4b33bb1822f09be0f681.png

第一步:客户浏览器发送http请求

第二步:web服务器接受后发送302状态码响应及对应新的location给客户浏览器

第三步:客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址

第四步:服务器根据此请求寻找资源并发送给客户。在这里location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。

在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。

总结:一句话,转发是服务器行为,重定向是客户端行为。

4.3、区别:请求次数

1)重定向

重定向,其实是两次request

第一次,客户端request   A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失。

举例:

response.sendRedirect("loginsuccess.jsp");

2)转发

转发是一次request

请求转发是服务器内部把对一个request/response的处理权,移交给另外一个

对于客户端而言,它只知道自己最早请求的那个A,而不知道中间的B,甚至C、D。传输的信息不会丢失。

RequestDispatcher dis=request.getRequestDispatcher(“loginsuccess.jsp”);

dis.forward(request,response);

4.4、生活中的例子说明区别

d18873ce2401220ef6e675243e29a7ca.png

假设你去办理某个执照

重定向:你先去了A局,A局的人说:“这个事情不归我们管,去B局”,然后,你就从A退了出来,自己乘车去了B局。

转发:你先去了A局,A局看了以后,知道这个事情其实应该B局来管,但是他没有把你退回来,而是让你坐一会儿,自己到后面办公室联系了B的人,让他们办好后,送了过来。

五、总结Servlet中请求和转发的区别

1)重定向的执行过程:Web服务器向浏览器发送一个http响应--》浏览器接受此响应后再发送一个新的http请求到服务器--》服务器根据此请求寻找资源并发送给浏览器。它可以重定向到任意URL,不能共享request范围内的数据。

2)重定向是在客户端发挥作用,通过新的地址实现页面转向。

3)重定向是通过浏览器重新请求地址,在地址栏中可以显示转向后的地址。

4)转发过程:Web服务器调用内部方法在容器内部完成请求和转发动作--》将目标资源发送给浏览器,它只能在同一个Web应用中使用,可以共享request范围内的数据。

5)转发是在服务器端发挥作用,通过forward()方法将提交信息在多个页面间进行传递。

6)转发是在服务器内部控制权的转移,客户端浏览器的地址栏不会显示出转向后的地址。

喜欢就点个“推荐”哦!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【POJ - 3304 】Segments(计算几何,思想转化,直线和线段相交)

题干: Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments on it, all projected segments have at least one point in common. Input Input begins with a…

java调用lingo_使用Lingo增强JMS

虽然activemqjencks的jms轻量级解决方案已经很好地在psa中work了,尤其spring的JmsTemplate使得代码更简单,但是还是存在问题。问题来自暑期做psa的时候,linke突然提出要求,需要MDP返回些处理信息,比如处理结果、异常&a…

jsk Star War (线段树维护区间最小最大值 + 二分)

Description 公元20XX年,人类与外星人之间的大战终于爆发。 现有一个人类军团,由n名士兵组成,第i个士兵的战斗力值对应一个非负整数ai (1 \leq i \leq n1≤i≤n)。 有一天,某个战力爆表的外星人NaN单独向地球人宣战&#xff0c…

java jsp导出pdf文件_JSP页面导出PDF格式文件

JSP页面导出PDF格式文件基本在前端页面可以全部完成添加下载链接的点击事件var downPdf document.getElementById("downLoad");downPdf.onclick function() {downPdf.parentNode.removeChild(downPdf);html2canvas(document.body, {onrendered:function(canvas) {v…

【51Nod - 1094】和为k的连续区间 (前缀和,二分查找)

题干&#xff1a; 一整数数列a1, a2, ... , an&#xff08;有正有负&#xff09;&#xff0c;以及另一个整数k&#xff0c;求一个区间i,ji,j&#xff0c;(1 < i < j < n)&#xff0c;使得aii ... ajj k。 Input 第1行&#xff1a;2个数N,K。N为数列的长度。K为需…

简述java的线程_Java多线程的简述

线程与进程进程&#xff1a;​ 是指一个内存中运行的应用程序&#xff0c;每个进程都有一个独立的内存空间&#xff0c;一个应用程序可以同时运行多个进程&#xff1b;进程也是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff1b;系统运行一个程序即是一个进程…

【POJ - 3253】Fence Repair(贪心,时光倒流)

题干&#xff1a; Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each having some integer length Li (1 ≤ Li ≤ 50,000) units. He t…

java unsafe park_Java中Unsafe类详解

http://www.cnblogs.com/mickole/articles/3757278.htmlJava不能直接访问操作系统底层&#xff0c;而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作&#xff0c;主要提供了以下功能&#xff1a;1、通过Unsafe类可以分配内存&#xff0c;可以释放内存&#xff1b;类中…

【CodeForces - 124D】Squares (旋转坐标系,计算几何,思维)

题干&#xff1a; You are given an infinite checkered field. You should get from a square (x1; y1) to a square (x2; y2). Using the shortest path is not necessary. You can move on the field squares in four directions. That is, when you are positioned in any…

java图形设计_java图形界面设计含答案

十一章 图形用户界面程序设计入门一&#xff0e;选择题&#xff1a;1. 容器Panel和applet缺省使用的布局编辑策略是 BA、BorderLayout B、FlowLayoutC、GridLayout D、CarLayout2. .applet类的直接父类是&#xff1a; BA、Component类 B、Container类C、Frame类 D、Panel类3. .…

【qduoj - 夏季学期创新题】骑士游历(递推dp)

题干&#xff1a; 描述 输入 输入包含多组数据&#xff0c;第一行T表示数据组数接下来每行六个整数n&#xff0c;m&#xff0c;x1&#xff0c;y1&#xff0c;x2&#xff0c;y2(分别表示n&#xff0c;m&#xff0c;起点坐标&#xff0c;终点坐标) 输出 输出T行&#xff0c;表示…

java ee 6 源码_Java EE 6开发手册·高级篇(第4版)

资源名称&#xff1a;Java EE 6开发手册高级篇(第4版)内容简介&#xff1a;《Java EE 6 开发手册?高级篇(第4 版)》是一本面向实战、以示例为驱动、在Java 平台企业版6(Java EE 6)上开发企业级应用的指南。该指南基于The Java EE 6 Tutorial: Basic Concepts&#xff0c;Fourt…

【qduoj - 夏季学期创新题】矩形剖分(递归,dp)

题干&#xff1a; 描述 对一个给定的矩形&#xff0c;将其划分成尽可能少的正方形&#xff0c;输出正方形的最少个数。例如&#xff0c;如下图所示的情况&#xff0c;则输入为3和4&#xff0c;输出为4。 输入 输入两个整数中间用空格分开。 输出 输出最少分割成的正方形的个…

java8 nio_Java8之 NIO的学习

一、什么是NIO&#xff1f;Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API&#xff0c;可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的&#xff0c;但是使用的方式完全不同&#xff0c;NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式…

【牛客 - 125A】灰魔法师(打表,暴力)

题干&#xff1a; 给出长度为n的序列a, 求有多少对数对 (i, j) (1 < i < j < n) 满足 ai aj 为完全平方数。 输入描述: 第一行一个整数 n (1 < n < 105) 第二行 n 个整数 ai (1 < ai < 105) 输出描述: 输出一个整数&#xff0c;表示满足上述条件的数…

学分绩点计算编程java_方便我们计算学分绩点的JavaScript

基于目前我们学校教务处的管理系统, 依靠Javascript的帮忙, 我们可以很方便地计算成绩.测试用HTML:style"width: 100%; border-collapse: collapse;">课程代码课程名称课程性质成绩补考成绩重修成绩学分绩点辅修标记24109505数据库系统实验专业基础课优秀0.54.502…

【POJ - 2663】Tri Tiling (简单dp)

题干&#xff1a; In how many ways can you tile a 3xn rectangle with 2x1 dominoes? Here is a sample tiling of a 3x12 rectangle. Input Input consists of several test cases followed by a line containing -1. Each test case is a line containing an integer …

java 反射 代码_java反射机制学习代码

根据http://www.iteye.com/topic/137944文档进行学习代码如下:package reflectTest;import java.lang.reflect.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.*;class A{}class B extends A{}class C extends B{}class TestClass …

【POJ - 1556】The Doors (计算几何,线段相交)

题干&#xff1a; You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x 0, x 10, y 0, and y 10. The initial and final points of the path are always (0, 5) and (10, 5). Th…

java处理linux中的 m_Linux下处理BOM头和^M的简单方法

Linux在网络服务器、嵌入式设备的市场上占有较大份额&#xff0c;Microsoft Windows在桌面操作系统上占有较大的份额&#xff0c;因此有很多的人喜欢用Windows去控制操作Linux。既然用Windows去控制Linux&#xff0c;难免导致Windows系统上的产生的文件以某种途径传到了Linux系…