servlet中文乱码
问题描述
在servlet中可能经常会出现中文乱码的情况,大致分为以下三种 * 表单处理(get/post) * 超链接() * sendRedirect()乱码(response.sendRedirect(“test.servlet?username=测试”))
原因解释及解决方案
表单处理
首先,浏览器默认一般都是UTF-8的方式编码的,而服务端默认以ISO-8859-1编码,也是以此方式来将字节流转化成字符串。
假如说页面中设置了<meta charset=utf-8>
,那么发送请求时,url是以UTF-8发送字节流,而服务端使用request.getparameter直接得到的字符串,也就是用ISO-8859-1将字节流转化成字符串,因此出现乱码。
简而言之,一个字符串,以什么编码方式转化成字节流,就要用什么编码方式还原
- post提交:
解决方法:在接收方的request.setCharacterEncoding(‘utf-8’);
- get提交:
如果你使用以上的方法的话,结果还是乱码,原因在于,get方法中数据是在请求行中的,不是封装在请求体,而setCharacterEncoding针对的是请求体中的内容, 解决方法:
String request=new String(request.getParameter("key").getBytes("ISO-8859-1"),"UTF-8")
这样写看起来很麻烦,我们可以把他写成一个工具类,
public class MyTools{
public static String getNewString(String str){
String newstr=new String(str.getBytes("iso-8859-1"),"utf-8");
return newstr;
}
}
超链接
从超链接的格式上可以看到,他本质上使用的get方式提交,那我们可以使用get提交的解决方案来解决此问题
sendRedirect()
在使用sendRedirect发送数据之前,如果数据中有中文字段,需要先转化一下编码方式,用以下这种办法,也可以解决IE6中乱码的问题
String message = "测试";
message = URLEncoder.encode(message,"GBK");
response.sendRedirect(url+"?message ="+message);
事件代理委托机制
问题模型
假设现在有一个页面,存了1000个button,点击button显示这是第几个button,怎么实现这个功能呢
以前我们通常是给一个元素绑定一个事件,但是监听器可能会导致内存泄露或者性能降低,并且监听器越多这种可能性越大,为此,我们有了另一种办法,将监听放在其父元素或者更高的元素上,减少监听器的数量。
背景知识
先来看看JavaScript中设置事件监听的几种办法:
- element.[‘on’+type]=function(){} //所有浏览器
- element.attachEvent(‘on’+type,listener); //IE6-10支持,IE11不支持
- element.addEventListener(type,listener,[usecapture]); //IE6-8不支持
区别:
-
element['on' + type]
不支持对一个元素的一个事件注册多个监听,并且不能使用事件捕获 -
attachEvent
是IE为了实现绑定多个监听而引入的,不过这也也还是不能使用事件捕获,而且IE11也已经抛弃这种方法了。 -
addEventListener
是W3C工作组在DOM Level 2开始引入的一个注册事件监听器的方法,存在3个事件阶段,捕获-目标-冒泡,传播路径如下图:
- 捕获阶段: 在事件对象到达目标元素之前,事件对象从window开始经过祖先节点传到目标节点
- 目标阶段: 事件对象到达其目标节点,假如一个事件对象被标志为不能冒泡,则在目标阶段处理完之后不会进入冒泡阶段
- 事件冒泡: 看名称应该能看出一些端倪,事件对象沿着目标节点往上传递,与捕获阶段相反,到达window结束
可以将usecapture设置为true(false)来控制监听生效的阶段,true表示在捕获阶段生效,false表示在冒泡阶段生效。如果要跳过冒泡阶段的话,可以将event.bubbles
设置为false
问题解决
现在让我们来解决一下之前的那个问题,我们可以在document上设置一个监听,判断点击事件到底是在第几个button发生的,那么我们可以这么做
document.addEventListener('click',function(e) {
if (e.target.nodeName.toUpperCase()==='BUTTON') {
var buttonList=document.getElementsByTagName('button');
for (var i = 0; i < buttonList.length; i++) {
if (e.target===buttonList[i]) {
console.log("button:"+(i+1));
};
};
};
},false);
补充
除了代理监听还有什么办法呢,有吗?有的,我们还有闭包嘛,我们可以使用闭包那些i值缓存起来,咱们来简单实现一下:
var buttonList=document.getElementsByTagName('button');
for (var i = 0; i < buttonList.length; i++) {
(function(j) {
buttonList[j].onclick=function() {
console.log("button:"+(j+1));
}
})(i);
};
在线demo
CSS优先级
背景
今天碰到css的一个小问题,于是重温一下css选择器的优先级的问题
计算优先级
优先级是根据由每种选择器类型构成的级联字串计算而成的。他是一个对应匹配表达式的权重。 如果优先级相同,靠后的 CSS 会应用到元素上。
注意:元素在DOM树的位置不影响优先级
优先级顺序
优先级逐级增加的选择器列表:
- 通用选择器(*)
- 元素(类型)选择器
- 类选择器
- 属性选择器
- 伪类
- ID选择器
- 内联样式
基于类型的优先级
优先级是根据选择器类型进行计算的,下面有个例子可以说明一下这个选择优先级,虽然属性选择器里使用的ID,但是优先级还是没有ID选择器高,因此应用到元素上的样式为第一种
* #foo {
color: green;
}
*[id="foo"] {
color: purple;
}
将其用到下面的HTML中
<p id="foo">I am a sample text.</p>
演示例子: <iframe width="100%" height="300" src="https://jsfiddle.net/donqi/vmo5m3re/embedded/result,css,html,js/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
选择器优先级一致
优先级相同的情况下,后面定义的会覆盖前面定义的样式,classList里的顺序并不影响结果 举例:
<div class="box padding border"></div>
<div class="box border padding"></div>
<div class="padding box border"></div>
CSS:
div{
height:100px;
width:100px;
padding:20px;
margin:20px;
border:10px solid hsla(0,0%,0%,0.5);
background-color:#ccc;
background-image:url("/favicon.png");
background-repeat:space;
background-origin:content-box;
}
div.box{
background-clip:content-box;
}
div.border{
background-clip:border-box;
}
div.padding{
background-clip:padding-box;
}
演示例子:
最后说两句
这里说的是css选择器的优先级,对于到底表现哪种样式,还有一点特别重要,css解析器是从右到左的顺序解析的。比如上面的例子中,会先寻找id为”foo”的元素
* #foo {
color: green;
}
为什么要这么做呢,下回再说
屏蔽chrome(webkit)中的input.textarea的默认点击/聚焦高亮的样式
Webkit作为一个开源的浏览器引擎,而且apple和google都大力推广,其重要性不言而喻 chrome和Safari浏览器中添加了一些小功能
1.input标签/textarea标签聚焦高亮 屏蔽方法:
input, textarea{outline: none;}
2.textarea标签缩放 去掉缩放:
/**css2.0*/
textarea {width: 400px; max-width: 400px; height: 400px; max-height: 400px; }
/**css3.0*/
textarea{resize: none;}
注意:如果考虑兼容webkit核心的浏览器,要注意输入框(文本框)要尽量保持原来的样式。 当你隐藏了点击前的样式,又忘记去掉聚焦之后的默认样式,webkit引擎浏览器就会出现问题。
JS控制鼠标悬浮时放大元素,不影响其他元素布局
问题描述
第一部分: 用CSS控制3个<div>标签实现下面这个布局
第二部分:用javascript优化布局
由于我们的用户群喜欢放大看页面,于是我们给上一题的布局做一次优化。当鼠标略过某个区块的时候,该区块会放大25%,并且其他的区块仍然固定不动。
实现思路
第一部分,可以用float,也可以absoulte,看大家喜欢了,这里我使用的是absolute定位,将右边的主要内容放在前面,这样能够先加载主要内容,代码如下
div{
background-color:grey;
position:absolute;
}
#main{
margin-left: 210px;
height: 500px;
width: 300px;
}
#left1{
width: 200px;
height: 245px;
}
#left2{
width:200px;
height:245px;
top:255px;
margin-top:10px;
}
第二部分:
鼠标滑过时,将zIndex设为100,不影响其他元素布局,离开时恢复 使用事件代理,直接通过document监听鼠标 鼠标滑过时,宽高变为120%,将margin-top和margin-left减小20px; 如果图片大小都差不多大话,可以将边距减少10%,效果还比较好 在这里要注意以下几点:
- IE8及以下添加监听使用的是attchEvent,并且响应函数里this的值是window对象而不是触发事件的元素
- 获取元素之前的宽高时,用先获取到元素的宽高,这里就可以用我们之前讨论过的方法,IE用element.currentStyle,其他用
window.getComputedStyle(element,[, pseudoElt])
,不清楚的看这里->获取样式表 - 利用parseInt转化类型时,如果在字符串开始处无法获得任何数字,会返回NaN,IE中用currentStyle获取样式表的话,如果margin未定义的话,值是auto
- 想要获取元素的最终样式,如果你这么写:
var style=window.getComputedStyle(e)||e.currentStyle;
IE8及以前就会报错,说不支持getComputedStyle属性或方法,IE中,如果碰到未定义的变量就会开始报错,不管是不是在if判断句还是或运算符前,不知道这不是一个bug啊,按理说第一句为假的时候应该要判断后面一句的啊,现在我们只能调换顺序了
js代码如下:
/**attachEvent响应函数中this的值会变成window对象而不是触发事件的元素*/
function returnEvent(e) {
if (e.target) {
return e.target;
} else if(e.srcElement){
return e.srcElement;
};
};
/**针对IE中currentStyle获取到的属性值可能是auto,导致转化成int时出现NaN的情况**/
function improInt (attr) {
if (parseInt(attr)) {
return parseInt(attr);
} else{
return 0;
};
}
/**div变大***/
function bigger(e) {
var node=returnEvent(e);
if (!!node&&node.nodeName.toUpperCase()=="DIV") {
node.style.zIndex=100;
var style=(node.currentStyle||window.getComputedStyle(node));//非IE和IE
node.style.width=1.2*improInt(style.width)+"px";//宽度放大1.2倍
node.style.height=1.2*improInt(style.height)+"px";//高度放大1.2倍
node.style.marginTop=(improInt(style.marginTop)-20)+"px";
node.style.marginLeft=(improInt(style.marginLeft)-20)+"px";
node.style.backgroundColor="red";
};
}
/**鼠标离开时,图片恢复原样**/
function smaller(e) {
var node=returnEvent(e);
console.log("returnEvent(e)"+returnEvent(e));
if (!!node&&node.nodeName.toUpperCase()=="DIV") {
node.style.zIndex=0;
var style=node.currentStyle||window.getComputedStyle(node);//非IE和IE
node.style.width=improInt(style.width)/1.2+"px";
node.style.height=improInt(style.height)/1.2+"px";//高度缩减1.2倍
node.style.marginTop=(improInt(style.marginTop)+20)+"px";
node.style.marginLeft=(improInt(style.marginLeft)+20)+"px";
node.style.backgroundColor="grey";
};
}
//在document上监听鼠标事件
if (document.addEventListener) {//其他浏览器和IE8以上都支持
document.addEventListener('mouseover',bigger,false);
document.addEventListener('mouseout', smaller, false);
} else if(document.attachEvent){//IE8及以下下事件监听使用的是attachEvent
document.attachEvent('onmouseover',bigger);
document.attachEvent('onmouseout',smaller);
};
具体实现:
具体实现:DEMO例子