jQuery 拥有可操作 HTML 元素和属性的强大方法。
jQuery DOM 操作
jQuery 中非常重要的部分,就是操作 DOM 的能力。
jQuery 提供一系列与 DOM 相关的方法,这使访问和操作元素和属性变得很容易。
提示:DOM = Document Object Model(文档对象模型)
DOM 定义访问 HTML 和 XML 文档的标准:
“W3C 文档对象模型独立于平台和语言的界面,允许程序和脚本动态访问和更新文档的内容、结构以及样式。”
获得内容 - text()、html() 以及 val()
三个简单实用的用于 DOM 操作的 jQuery 方法:
text() - 设置或返回所选元素的文本内容
html() - 设置或返回所选元素的内容(包括 HTML 标记)
val() - 设置或返回表单字段的值
下面的例子演示如何通过 jQuery text() 和 html() 方法来获得内容:
<!DOCTYPE html>
<html>
<head>
<script src="/jquery/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$("#btn1").click(function(){
alert("Text: " + $("#test").text());
});
$("#btn2").click(function(){
alert("HTML: " + $("#test").html());
});
});
</script>
</head>
<body>
<p id="test">这是段落中的<b>粗体</b>文本。</p>
<button id="btn1">显示文本</button>
<button id="btn2">显示 HTML</button>
</body>
</html>
val()方法例子:
<!DOCTYPE html>
<html>
<head>
<script src="/jquery/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
alert("Value:"+$("#test").val());
});
});
</script>
</head>
<body>
<p>姓名:<input type="text" id="test" value="米老鼠"></p>
<button>显示值</button>
</body>
</html>
获取属性 - attr()
jQuery attr() 方法用于获取属性值。
<!DOCTYPE html>
<html>
<head>
<script src="/jquery/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
alert($("#w3s").attr("url"));
});
});
</script>
</head>
<body>
<p><a url="img/001.jpg" id="w3s">W3School.com.cn</a></p>
<button>显示 href 值</button>
</body>
</html>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
局部变量
局部变量:在函数内部声明的变量,只在函数内部起作用。函数的参数也是局部性的,只在函数内部起作用,对于其他的函数或脚本代码是不可用的。
函数可以访问函数内部定义的变量,如:
<p>函数可以访问函数内部定义的变量:</p>
<button type="button" onclick="myFunction()">点我</button>
<p id="demo"></p>
<script>
function myFunction() {
var a = 4;
document.getElementById("demo").innerHTML = a a;
}
</script>
全局变量
在web页面中全局变量属于 window 对象,全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。
函数也可以访问函数外部定义的变量,如:
<p>函数可以访问定义在函数外的变量:</p>
<button type="button" onclick="myFunction()">点我</button>
<p id="demo"></p>
<script>
var a = 4;
function myFunction() {
document.getElementById("demo").innerHTML = a a;
}
</script>
全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
问题描述:
做抽屉式菜单时候,在 ie 7 下发现 li 元素之间会留白,如下图:
原以为是样式的问题,后来看到有博文写到“行框的排列会受到中间空白(回车\空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔”。
解决办法:
li 标签之间的空白,可以通过设置 li 标签的 font-size 为 0,可以解决:
li{
padding:0;
margin:0;
height: 30px;
line-height: 30px;
font-size: 0; / 设置 font-size 为 0 即可 /
}
修改后的效果如图:
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
引起这种空白间隔的原因:
浏览器的默认行为是把inline元素间的空白字符(空格换行tab)渲染成一个空格,也就是我们上面的代码
换行后会产生换行字符,而它会变成一个空格,当然空格就占用一个字符的宽度。
解决方案:
方法一: 既然是因为< li>换行导致的,那就可以将< li>代码全部写在一排,如下
<div class="wrap">
<h3>li标签空白测试</h3>
<ul>
<li class="part1"></li><li class="part2"></li><li class="part3"></li><li class="part4"></li>
</ul>
</div>
1
2
3
4
5
6
7
再刷新页面看就没有空白了,就是这么神奇~
方法二: 我们为了代码美观以及方便修改,很多时候我们不可能将< li>全部写在一排,那怎么办?既然是空格占一个字符的宽度,那我们索性就将
内的字符尺寸直接设为0,将下面样式放入样式表,问题解决。
.wrap ul{font-size:0px;}
1
但随着而来的就是
中的其他文字就不见了,因为其尺寸被设为0px了,我们只好将他们重新设定字符尺寸。
方法三: 本来以为方法二能够完全解决问题,但经测试,将li父级标签字符设置为0在Safari浏览器依然出现间隔空白;既然设置字符大小为0不行,那咱就将间隔消除了,将下面代码替换方法二的代码,目前测试完美解决。同样随来而来的问题是li内的字符间隔也被设置了,我们需要将li内的字符间隔设为默认。
.wrap ul{letter-spacing: -5px;}
1
之后记得设置li内字符间隔
.wrap ul li{letter-spacing: normal;}
1
2
详细看这篇文章 li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
后台返回json数据给前台和前台解析json数据(总结)
一般来说web开发中,前台采用json数据提交给后台,后台处理数据以后返回json数据给前台,前台解析json,显示数据。
总而言之,前后台直接交换的数据格式最常用的非json数据无疑了。
这里就总结一些json数据的前后台处理方式。
1.JSON数据
JSON(JavaScript Object Notation, JS 对象简谱)
是一种轻量级的数据交换格式,比xml更轻巧(由于 JSON 所使用的字符要比 XML 少得多,可以大大得节约传输数据所占用的带宽)。
json是javascript原生格式,就是说在javascript中处理json数据,需要引用其他API或工具包。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
只需要记住!
Json是一种文本字符串!被存储在responseText属性中,而读取json数据可以使用javascript的eval函数来解析json。
2.json规则:
在 JS 语言中,一切都是对象,对象是一个无序的 “键/值” 对集合。
因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型:
• 对象表示为键值对.
• 数据由逗号分隔.
• 花括号{}保存对象.
• 方括号[]保存数组.
键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:
{"firstName": "Json"}
1
这很容易理解,等价于这条 JavaScript 语句:
{firstName : "Json"}
1
对象在 JS 中是使用花括号包裹 {} 起来的内容,数据结构为 {key1:value1, key2:value2, …} 的键值对结构。
在面向对象的语言中,key 为对象的属性,value 为对应的值。
键名可以使用整数和字符串来表示,值的类型可以是任意类型。
数组在 JS 中是方括号 [] 包裹起来的内容,数据结构为 [“java”, “javascript”, “vb”, …] 的索引结构。
在 JS 中,数组是一种比较特殊的数据类型,它也可以像对象那样使用键值对,但还是索引使用得多。同样,键名可以使用整数和字符串来表示,值的类型可以是任意类型。
3.JSON 与 JS 对象的关系:
很多人搞不清楚 JSON 和 Js 对象的关系,甚至连谁是谁都不清楚。其实,可以这么理解:
JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
如:
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
1
2
4.后台返回json数据
一般来说,使用JsonObject来将Java类型数据转换成Json类型,首先要下载该库相关的jar包,下载地址如下:
json-jar包下载
JsonObject的使用:
后台controller部分代码:
JSONObject object = new JSONObject(); //创建Json对象
object.put("username", "张三"); //设置Json对象的属性
object.put("password", "123456");
System.out.println(object.toString()); //调用toString方法将json对象转换成json字符串
//把json数据返回给浏览器:
PrintWriter out = cu.getWriterOut(response);
out.print(object.toString());
//或者
response.getWriter().write(jsonObject.toString());
1
2
3
4
5
6
7
8
9
10
11
5.在JavaScript代码中接收Json数据:
假设result为浏览器得到的json数据,可以使用以下js代码可以将json对象转换为字符串。
比如:
通过$.get从后台获取了一段json串{“id”:“1”,“name”:“ww”},然后要拿到这里面的id和name值:
注意!注意!注意!
如果你直接这么写!
$.get(url,
function(data) {
alert("ID:" + data.id + "\nName:" + data.name);
});
1
2
3
4
直接这样写的话,界面会alert提示undefined,因为没能正确解析返回的字符串。
图示:
解决方案:
1、 需要用eval()函数
将返回的串转化成可用的strig串,eval(data),但是因为原串里面是以{}开始和结束的,会被认为是可执行方法,因此需要加上()包围起来,最终形成:
var jsonobj= eval('(' + data + ')'); // 把JSON字符串解析为javascript对象
1
然后再
alert("ID:" + jsonobj.id + "\nName:" + jsonobj.name);
1
各种正常的按key取值,就能正常显示了。
2、获取的时候就直接表示返回的是json格式,用.getJSON代替 .getJSON代替.getJSON代替.get,其他代码不变,也能正常获取。
也可以直接获取json对象的属性,如下:console.log(result.username);
前端js代码:
$.ajax({
url: url,
type: "POST",
data: parameters,
dataType:"json",
async: false,
success: function(result){
var newData = JSON.stringify(result); //将json对象转换为字符串
newData = eval("("+newData+")"); /解析json
var annualDays = newData.annualDays;
var entryDate = newData.entryDate;
$("input[name='extendDataFormInfo.value(fd_shengyu_nianjia)']").val(annualDays);
$("input[name='extendDataFormInfo.value(fd_ruzhi_date)']").val(entryDate);
}});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ps: 注意注释中的代码,如果少了这一句,那么直接alert(result);得到的结果会是
所以在这里stringfy()的作用是用于从一个对象解析出字符串
加上了var newData = JSON.stringify(result);这句,然后你再alert(newData);
得到的就会是你想要的结果,如下:
另外:
如果返回的json数据格式不是很规范的解决办法:
判断后台返回的数据格式是否字符串,是则转,不是则不转?
var $obj = (typeof data.content == 'string') ? JSON.parse(data.content):data.content
1
总结:
前台发送请求,并且设置数据为json格式‘
$.ajax({
url:"selectByid.",
datatype:'json',
data:{id:id}, // 发送数据
1
2
3
4
数据回调函数
success:function(data){
alert(data);
var json = eval("("+data+")");//将json类型字符串转换为json对象
alert("hjf"+json.name);
1
2
3
4
给对应的input赋值:
$("#id").val(json.id),
$("#name").val(json.name),
$("#age").val(json.age);
1
2
3
后台代码:返回json数据
response.getWriter().print(str); //将数据返回前台ajax
1
6.前端ajax接不到json解决?
在前台:
async:false, //加上这个属性就好了
1
7.返回的json字符串中有转义符解决?
比如:
"result":"{\"id\":\"60\",\"qid\":\"1\",\"bazi\":\"baiz\",\"shenxiao\":\"\",\"xingzuo\":\"\",\"wuge\":\"\",\"jianyi\":\"\",}"
1
这样我们我们使用JSON.parse(result) ,直接转化为json的话是会报错的。
解决方法:
我们先把转义符用正则表达式去掉,
var string = result.replace("/\","");
var getDataArray = JSON.parse(string)
1
2
这样就OK了,不过要注意有时候也是需要指定返回数据类型的
dataType:“json”
8.使用其他的json依赖包方式:
引入阿里巴巴的json依赖包:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.9</version>
</dependency>
1
2
3
4
5
模拟后台:
String params="{\"channelCode\":\"bbb\",\"accountNo\":\"121300000932\",\"message\":\"字符信息解密成功\",\"status\":\"1\"}";
JSONObject pa=JSONObject.parseObject(params);
System.out.println(pa.getString("message"));
1
2
3
结果:
或者:
引入net.sf.json-lib依赖包:
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
1
2
3
4
5
6
后台:
String params="{\"channelCode\":\"ccy\",\"accountNo\":\"121300000932\",\"message\":\"字符信息解密成功\",\"status\":\"1\"}";
JSONObject pa=JSONObject.fromObject(params);
String accountNo=pa.getString("accountNo");
System.out.println(accountNo);
1
2
3
4
结果:
9.后台对象转换json数据返回给前台
List集合转换成json代码:
List list = new ArrayList();
list.add( "first" );
list.add( "second" );
JSONArray jsonArray2 = JSONArray.fromObject( list );
1
2
3
4
Map集合转换成json代码:
Map map = new HashMap();
map.put("name", "json");
map.put("bool", Boolean.TRUE);
map.put("int", new Integer(1));
map.put("arr", new String[] { "a", "b" });
map.put("func", "function(i){ return this.arr[i]; }");
JSONObject json = JSONObject.fromObject(map);
1
2
3
4
5
6
7
或者在项目中加入引入JSON-lib包,JSON-lib包同时依赖于以下的JAR包:
下载地址。
1.commons-lang.jar
2.commons-beanutils.jar
3.commons-collections.jar
4.commons-logging.jar
5.ezmorph.jar
6.json-lib-2.2.2-jdk15.jar
1
2
3
4
5
6
用法同上
JSONObject jsonObject = JSONObject.fromObject(message);
getResponse().getWriter().write(jsonObject.toString());
1
2
当把数据转为json后,用如上的方法发送到客户端。前端就可以取得json数据了。(可以参考最下面的实例)
10.后台返回数据给前台,json中文乱码解决方法
在实际运用场景中,当前台发起请求后,我们需要从后台返回数据给前台,这时,如果返回的数据中包含中文,则经常会出现在后台查询出来都是好好,但是传输回去就莫名的乱码了,而且即使在 web.xml 中进行编码过滤了,但还是乱码。
解决办法:
只需要在 spring-mvc.xml 配置文件中配置一次就好,省去了我们重复写的麻烦,配置内容如下:
<!--自定义消息转换器的编码,解决后台传输json回前台时,中文乱码问题-->
<mvc:annotation-driven >
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter" >
<property name = "supportedMediaTypes">
<list>
<value>application/json;charset=utf-8</value>
<value>text/html;charset=utf-8</value>
<!-- application 可以在任意 form 表单里面 enctype 属性默认找到 -->
<value>application/x-www-form-urlencoded</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" ></bean>
</mvc:message-converters>
</mvc:annotation-driven>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
加上这段配置,保存重新运行,再次访问,会发现,原先的中文乱码都已经正常显示了。
方法二:在后台的方法映射添加:
@RequestMapping(value="/getphone",produces = “text/plain;charset=utf-8”)
11.Spring MVC返回json数据的方式
原型:函数中的属性prototype,她的名字就叫原型。可以通过也只能通过prototype添加可继承的属性和方法
原型对象:函数中prototype中的proto 和对象中的proto
先记住原型(prototype)和原型对象(proto)
下面用代码解释原型、原型对象、 原型链
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>对象</title>
</head>
<body>
<script type="text/javascript">
//创建一个对象和一个函数
var obj = {}
console.log(obj.proto)//obj有原型对象
function objFun (){}
console.log(objFun.prototype) //objFun 原型
console.log(objFun.prototype.proto) //原型中有原型对象
console.log('*华丽的分割线***')
// 以objFun为构造函数 (为了把构造函数和普通函数做区分,通常把构造函数名首字母大写)
// 添加属性和方法
objFun.prototype.name='saozhu'
objFun.prototype.say = function(){
console.log(this.name+'-骚猪')
}
// 创建实例对象1
var obj1=new objFun()
console.log(obj1)//打印对象 空对象
console.log(obj1.name) //骚猪 证明obj1继承了objFun函数的属性
console.log('*华丽的分割线***')
// 此时此刻 可以理解原型链了:
console.log(obj1.proto=== objFun.prototype)
//true
// 原型链是有实例对象的proto(原型对象)指向构造函数函数的原型(prototype)
console.log(objFun.prototype.proto==window.Object.prototype)
// true
// 然后构造函数的原型的原型对象(prototype.proto)指向window.Object.protype(对象的原型)
console.log(window.Object.prototype.proto===null)
// 这样的指向关系形成的链式关系就是原型链
//链式查询,查询对象中的属性和方法,会根据这样的原型链查找,直到找到响应的属性和方法.找到window.Object.prototype.proto还没有值,就返回undeifne
</script>
</body>
</html>
开篇
之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你没有真正的理解。最近正在读《Javascript高级程序设计》,书中对原型对象和原型链的描述让我受益匪浅,下面仅用一个对比性的例子来说明。
我们经常会这么写
function Person () {
this.name = 'John';
}
var person = new Person();
Person.prototype.say = function() {
console.log('Hello,' + this.name);
};
person.say();//Hello,John
1
2
3
4
5
6
7
8
上述代码非常简单,Person原型对象定义了公共的say方法,虽然此举在构造实例之后出现,但因为原型方法在调用之前已经声明,因此之后的每个实例将都拥有该方法。从这个简单的例子里,我们可以得出:
原型对象的用途是为每个实例对象存储共享的方法和属性,它仅仅是一个普通对象而已。并且所有的实例是共享同一个原型对象,因此有别于实例方法或属性,原型对象仅有一份。
所以就会有如下等式成立:
person.say == new Person().say
1
可能我们也会这么写
function Person () {
this.name = 'John';
}
var person = new Person();
Person.prototype = {
say: function() {
console.log('Hello,' + this.name);
}
};
person.say();//person.say is not a function
1
2
3
4
5
6
7
8
9
10
很不幸,person.say方法没有找到,所以报错了。其实这样写的初衷是好的:因为如果想在原型对象上添加更多的属性和方法,我们不得不每次都要写一行Person.prototype,还不如提炼成一个Object来的直接。但是此例子巧就巧在构造实例对象操作是在添加原型方法之前,这样就会造成一个问题:
当var person = new Person()时,Person.prototype为:Person {} (当然了,内部还有constructor属性),即Person.prototype指向一个空的对象{}。而对于实例person而言,其内部有一个原型链指针proto,该指针指向了Person.prototype指向的对象,即{}。接下来重置了Person的原型对象,使其指向了另外一个对象,即
Object {say: function}
1
这时person.proto的指向还是没有变,它指向的{}对象里面是没有say方法的,因为此报错。
从这个现象我们可以得出:
在js中,对象在调用一个方法时会首先在自身里寻找是否有该方法,若没有,则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的proto属性。
若想让上述例子成功运行,最简单有效的方法就是交换构造对象和重置原型对象的顺序,即:
function Person () {
this.name = 'John';
}
Person.prototype = {
say: function() {
console.log('Hello,' + this.name);
}
};
var person = new Person();
person.say();//person.say is not a function
1
2
3
4
5
6
7
8
9
10
一张图让你秒懂原型链
其实,只需要明白原型对象的结构即可:
Function.prototype = {
constructor : Function,
proto : parent prototype,
some prototype properties: ...
};
1
2
3
4
5
总结:
函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针proto,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用proto一直指向Object的原型对象上,而Object的原型对象用Object.prototype.proto = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。
Blog同步
JavaScript 队列
题目:
在计算机科学中 队列(queue)是一个抽象的数据结构,队列中的数据条目都是有秩序的。新的条目会被加到 队列 的末尾,旧的条目会从 队列 的头部被移出。
写一个函数 queue ,用一个数组arr和一个数字item作为参数。数字item添加到数组的结尾,然后移出数组的第一个元素,最后队列函数应该返回被删除的元素。
queue([], 1) 应该返回 1
queue([2], 1) 应该返回 2
queue([5,6,7,8,9], 1) 应该返回 5
在 queue(testArr, 10) 之后, testArr[4] 的值应该是 10
通关答案:
function queue(arr, item) {
/下面这两句是关键/
arr.push(item);
return arr.shift();// Change this line
}
console.log(queue([], 1));
console.log(queue([2], 1));
console.log(queue([5,6,7,8,9], 1));
// Test Setup
var testArr = [1,2,3,4,5];
// Display Code
console.log("Before: " + JSON.stringify(testArr));
console.log(queue(testArr, 10)); // Modify this line to test
console.log("After: " + JSON.stringify(testArr));
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
转发和重定向区别详解
作为一名程序员,特别是java web开发的程序员,在使用servlet/jsp的时候,我们必须要知道实现页面跳转的两种方式的区别和联系:即转发和重定向的区别。
1、RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。、
2、调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
3、HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。
4、RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用RequestDispatcher.forward方法。不同WEB应用程序之间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该使用HttpServletResponse.sendRedirect方法。
5、无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中。
以上五点的论述来源于:点击查看原文论述
转发和重定向的图解
两种跳转获得对象的方式
//获得转发对象getRequestDispatcher()
HttpServletRequest(httpServletRequest).getRequestDispatcher
ServletContext.getRequestDispatcher();
//获得重定向对象sendRedirect()
HttpServletResponse(httpServletResponse).sendRedirect();
转发和跳转的小结
1、转发使用的是getRequestDispatcher()方法;重定向使用的是sendRedirect();
2、转发:浏览器URL的地址栏不变。重定向:浏览器URL的地址栏改变;
3、转发是服务器行为,重定向是客户端行为;
4、转发是浏览器只做了一次访问请求。重定向是浏览器做了至少两次的访问请求;
5、转发2次跳转之间传输的信息不会丢失,重定向2次跳转之间传输的信息会丢失(request范围)。
转发和重定向的选择
1、重定向的速度比转发慢,因为浏览器还得发出一个新的请求,如果在使用转发和重定向都无所谓的时候建议使用转发。
2、因为转发只能访问当前WEB的应用程序,所以不同WEB应用程序之间的访问,特别是要访问到另外一个WEB站点上的资源的情况,这个时候就只能使用重定向了。
转发和重定向的应用场景
在上面我已经提到了,转发是要比重定向快,因为重定向需要经过客户端,而转发没有。有时候,采用重定向会更好,若需要重定向到另外一个外部网站,则无法使用转发。另外,重定向还有一个应用场景:避免在用户重新加载页面时两次调用相同的动作。
例如,当提交产品表单的时候,执行保存的方法将会被调用,并执行相应的动作;这在一个真实的应用程序中,很有可能将表单中的所有产品信息加入到数据库中。但是如果在提交表单后,重新加载页面,执行保存的方法就很有可能再次被调用。同样的产品信息就将可能再次被添加,为了避免这种情况,提交表单后,你可以将用户重定向到一个不同的页面,这样的话,这个网页任意重新加载都没有副作用;
但是,使用重定向不太方便的地方是,使用它无法将值轻松地传递给目标页面。而采用转发,则可以简单地将属性添加到Model,使得目标视图可以轻松访问。由于重定向经过客户端,所以Model中的一切都会在重定向时丢失。但幸运的是,在Spring3.1版本以后,我们可以通过Flash属性,解决重定向时传值丢失的问题。
要使用Flash属性,必须在Spring MVC的配置文件中添加一个<annotation-driven/>。然后,还必须再方法上添加一个新的参数类型:org.springframework.web.servlet.mvc.support.RedirectAttributes。
如下所示:
@RequestMapping(value="saveProduct",method=RequestMethod.POST)
public String saveProduct(ProductForm productForm,RedirectAttributes redirectAttributes){
//执行产品保存的业务逻辑等
//传递参数
redirectAttributes.addFlashAttribute("message","The product is saved successfully");
//执行重定向
return "redirect:/……";
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
Struts2中转发和重定向的区别以及实现方法
最近遇到一个问题,就是在设置struts2的拦截器以后,想要访问必须登录,想要的效果是转到登录页面,也就是转到xxx.jsp,但是发现没有转到,而是action结尾的,后来发现是因为在struts.xml里面配置的时候,没有在result中配置type属性,struts默认的是重定向,就是网址不变,解决办法就是在result中加type=”redirect”,就可以了
转发和重定向的区别:
重定向是不共享request的东西,重定向后的页面中无法接收request里的东西,另外dispatcher结果类型的default属性为TRUE,故<result- type/>缺省为dispatcher 所以如果没有设置type属性的话,那么默认的是请求转发,就是说你要是什么都不写的话,默认就是这样的
1
<result name="list" type="dispatcher">/admin/jsp/userAction/list.jsp</result>
1
重定向的两个属性:
redirect是在处理完当前Action之后,重定向到另外一个实际的物理资源,以.jsp结尾这样的
redirectAction也是重定向,但它重定向到的是另外一个Action,就是以action结尾这样的
只要是重定向,那么之前凡是保存在request里面的东西就全都消失了
因为重定向实际是发送第二个请求,故请求中的东西也就不会出现在第二个请求里面了
也就是说重定向是不共享request的东西,重定向后的页面中无法接收request里的东西,
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
蓝蓝 http://www.lanlanwork.com