这里还是一些老掉牙的问题,CSS,验证码,SSL,Struts Validate等。一个一个记录下来再说:
-
css
终于对页面布局有了一点点了解,基本的一个head,一个sidebar,一个mainbody的结构:
/*基本信息*/
body {font:12px Tahoma;margin:0px;text-align:center;background:#FFF;}
a:link,a:visited {font-size:12px;text-decoration:none;}
a:hover{}
/*页面层容器*/
#container {width:700px;margin:10px auto}
/*页面头部*/
#header {background:url(../img/logo.gif) no-repeat;height:59px;}
#menu {}
#menu ul {float:right;list-style:none;margin:0px;width:560px;height:16;background:#EAF3FF}
#menu ul li {float:right;display:block;line-height:30px;margin:0 5px}
#menu ul li a:link,#menu ul li a:visited {font-weight:bold;font-size:11px;color:#00A3FF}
#menu ul li a:hover{}
.menuDiv {width:1px;height:28px;background:#CCCCCC;}
/*页面主体*/
#pagebody {
width:700px; /*设定宽度*/
margin:0px auto; /*居中*/
}
#sidebar {
background:#F5F8FC;
width:320px; /*设定宽度*/
text-align:left; /*文字左对齐*/
float:right; /*浮动居左*/
clear:right; /*不允许左侧存在浮动*/
overflow:hidden; /*超出宽度部分隐藏*/
border:1px solid #78A3D3;
height:400px
}
#sidebar ul {float:right;list-style:none;width:320px;height:16;margin:20px;}
#sidebar ul li {font-size:13px;margin:10px;}
#sidebar ul li a:link,#sidebar ul li a:visited {font-size:11px;color:#78A3D3}
#sidebar ul li a:hover{}
.account,.password,.validate {
border:1px solid #78A3D3;
line-height:100px;
width: 120px;
height: 20px;
}
.loginButton {
BORDER-RIGHT: #7b9ebd 1px solid;
PADDING-RIGHT: 2px;
BORDER-TOP: #7b9ebd 1px solid;
PADDING-LEFT: 2px;
FONT-SIZE: 12px;
FILTER: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#ffffff, EndColorStr=#cecfde);
BORDER-LEFT: #7b9ebd 1px solid;
CURSOR: hand;
COLOR: black;
PADDING-TOP: 2px;
BORDER-BOTTOM: #7b9ebd 1px solid
}
.note {
font-size: 11px;
color: #868686;
}
.error {
margin:1px 20px;
width:120px;
color:ff0000;
font-size:12;
}
#mainbody {
width:380px;
text-align:left;
float:left; /*浮动居右*/
clear:left; /*不允许右侧存在浮动*/
overflow:hidden;
}
#mainbody ul {float:right;list-style:none;width:320px;height:16;margin:20px;}
#mainbody ul li {font-size:12px;margin:5px;}
/*页面底部*/
#footer {width:800px;margin:0 auto;height:50px;background:#00FFFF}
另外找到一个不错的注册的css:
.css
body {
font-family: Arial, Helvetica, sans-serif;
font-size:12px;
color:#666666;
background:#fff;
text-align:center;
}
* {
margin:0;
padding:0;
}
a {
color:#1E7ACE;
text-decoration:none;
}
a:hover {
color:#000;
text-decoration:underline;
}
h3 {
font-size:14px;
font-weight:bold;
}
pre,p {
color:#1E7ACE;
margin:4px;
}
input, select,textarea {
padding:1px;
margin:2px;
font-size:11px;
}
.buttom{
padding:1px 10px;
font-size:12px;
border:1px #1E7ACE solid;
background:#D0F0FF;
}
#formwrapper {
width:510px;
margin:15px auto;
padding:20px;
text-align:left;
border:1px #1E7ACE solid;
}
fieldset {
padding:10px;
margin-top:5px;
border:1px solid #1E7ACE;
background:#fff;
}
fieldset legend {
color:#1E7ACE;
font-weight:bold;
padding:3px 20px 3px 20px;
border:1px solid #1E7ACE;
background:#fff;
}
fieldset label {
float:left;
width:120px;
text-align:right;
padding:4px;
margin:1px;
}
.error {
margin:1px 125px;
width:120px;
color:ff0000;
}
fieldset div {
clear:left;
margin-bottom:2px;
}
.enter{ text-align:center;}
.clear {
clear:both;
}
.jsp
<fieldset>
<legend>请选择您的用户名</legend>
<div>
<label for="username">用户名</label>
<input type="text" name="username" id="username" size="20" maxlength="30" οnblur="getBackInfo();"/> @ymail.com*<input type="text" id="disCheckResult" size="50" readonly style="border:0;margin:0 80px;font-size=12;color=red"/><br />
<p class="error"><html:errors property="username"/></p>
</div>
</fieldset>
<br />
<fieldset>
<legend>请填写相关安全信息</legend>
<p><strong>以下信息对保护您的帐户安全十分重要,请谨慎填写并牢记.</strong> 在您注册之前请先认真阅读服务条款.</p>
<div>
<label for="password">密码</label>
<input type="password" name="password" size="18"/>
*(至少8个字符)<br /><p class="error"><html:errors property="password"/></p>
</div>
<div>
<label for="password1">重复密码</label>
<input type="password" name="password1" size="18"/>
*<br /><p class="error"><html:errors property="password1"/></p>
</div>
<div>
<label for="question">密码保护问题</label>
<select name="question" class="text" title="密码保护问题">
<option value="" selected="selected">请选择一个问题</option>
<option value="我就读的第一所学校的名称?">我就读的第一所学校的名称?</option>
<option value="我最喜欢的休闲运动是什么?">我最喜欢的休闲运动是什么?</option>
<option value="我最喜欢的运动员是谁?">我最喜欢的运动员是谁?</option>
<option value="我最喜欢的物品的名称?">我最喜欢的物品的名称?</option>
<option value="我最喜欢的歌曲?">我最喜欢的歌曲?</option>
<option value="我最喜欢的食物?">我最喜欢的食物?</option>
<option value="我最爱的人的名字?">我最爱的人的名字?</option>
<option value="我最爱的电影?">我最爱的电影?</option>
<option value="我妈妈的生日?">我妈妈的生日?</option>
<option value="我的初恋日期?">我的初恋日期?</option>
</select>
*<br /><p class="error"><html:errors property="question"/></p>
</div>
<div>
<label for="answer">您的答案</label>
<input type="text" name="answer" size="18"/>
*<br /><p class="error"><html:errors property="answer"/></p>
</div>
<div>
<label for="nickName">昵称</label>
<input type="text" name="nickName" size="18"/>
*<br/><p class="error"><html:errors property="nickName"/></p>
</div>
<div>
<label for="sEmail">备用邮箱</label>
<input type="text" name="sEmail" value="" size="20" maxlength="150" />
可以通过备用邮箱来修改您的密码<p class="error"><html:errors property="sEmail"/></p>
</div>
<div>
<label for="agreeToTerms">同意服务条款</label>
<input type="checkbox" name="agreeToTerms" value="1" />
<a href="#" title="您是否同意服务条款">先看看条款?</a> * <br/>
<p class="error"><html:errors property="agreeToTerms"/></p></div>
<div class="enter">
<input name="create791" type="submit" class="buttom" value="提交" />
<input name="Submit" type="reset" class="buttom" value="重置" />
</div>
<p><strong>* 在提交您的注册信息时, 我们认为您已经同意了我们的服务条款.<br />
* 这些条款可能在未经您同意的时候进行修改.</strong></p>
</fieldset>
-
关于validation
可以用js和struts validate,这里两种都用了-_-!!!
先说用框架的:
1.配置文件:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>
2.写验证规则
<form name="registerForm"> <field property="username" depends="required"> <msg name="required" key="error.required"/> <arg0 key="error.username"/> </field> <field property="password" depends="required,minlength"> <msg name="required" key="error.required"/> <arg0 key="error.password"/> <msg name="minlength" key="error.minlength"/> <arg0 key="error.password"/> <arg1 key="${var:minlength}" name="minlength" resource="false"/> <var> <var-name>minlength</var-name> <var-value>8</var-value> </var> </field> <field property="password1" depends="validwhen"> <var> <var-name>test</var-name> <var-value>(password==*this*)</var-value> </var> <msg name="validwhen" key="error.password1"/> </field> <field property="question" depends="required"> <msg name="required" key="error.required"/> <arg0 key="error.question"/> </field> .... </form>
3.写properties文件
4. 别忘了页面上添加<html:errors property="username"/>
本来可以自己写个验证规则来判断用户名是否存在,但是Ajax的无刷新验证看来更具诱惑力,于是对Ajax一窍不通的我做了第一次尝试..貌似也蛮好理解的,即写一个servlet,并用js调用并在页面显示结果。
servlet:
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ymail.dbimpl.UsersImpl;
public class UsernameValidator extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = -9038308848332609445L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
// System.out.print("asdfdsaf");
try{
UsersImpl usersImpl = new UsersImpl();
boolean flag = usersImpl.usernameValidate(username);
String msg = null;
//System.out.print(flag);
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter();
if (flag) {
msg = "用户名"+username+"已经存在";
}
else {
msg = "恭喜你,"+username+"可以使用";
}
out.println(msg);
//System.out.print(msg);
}catch(Exception ex){
ex.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(request, response);
}
}
js:
<script language="javascript" > var request; /** 下面这个函数可以返回一个适合任何浏览器的httpRequest,步子如下: 1.试着创建一个XMLHttpRequest()示例,该示例可适合于除了微软以外的所有浏览器 2.增加错误判断,如果当前浏览器是微软的,那么就创建适用于微软的浏览器 3.但微软的浏览器又有两个版本之分,不过据说微软已经在7.0中增加对XMLHttpRequest()的支持 4.但这样也需要对原来的浏览器支持,否则你写出来的程序那些用老版本浏览器的用户就是看不 到效果的。 */ function createRequest() { try{ request=new XMLHttpRequest(); }catch(trymicrosoft) { try{ request=new ActiveXObject("Msxml2.XMLHTTP"); }catch(othermicrosoft) { try{ request=new ActiveXObject("Microsoft.XMLHTTP"); } catch(failed) { request=false; } } } if(!request) { alert("err Happend!"); return null; } return request; } /** 这个函数就是用户的动作所有触发的函数,如下面的onblur()时,就会调用该函数 经过的步骤如下: 1.从HTML页面得到你需要的数据,可以采有document.getElementById("")方法。 2.建立需要的URL,该URL就和在FORM里面的method为get时并采用submit提交在地址栏 里面到的一样 3.打开与服务器的连接,这里面有三个必要的参数,虽然文档规定只有两个,但是我个 人觉得最好用三个, 第一个可以是GET,POST或者是POST,但常用的就是前面的两个,并且最好都用大写,因 为有些浏览器如FireFox可能会报错, 第二个就是打报的URL,这肯定你是必须的。 第三个就是下面的看到的true,这里可以是false。true表示同步处理,你提交后可以做 其它的事情,这就是AJAX里面的A,即asynchronous;如是false,那就得等到服务器的返 回才能够做其它的事情。 4.等到服务器完成,并且确定返回执行了正确执行的提示,我们就可以做下面我们想做的 事情。这些后面的事情就必须通过Javascript去完成了,因为XMLHttpRequest的唯一用途 就是发送请求及接收服务器的响应结果。 5.上面都完成了后,就可以采用send()方法向服务器发送你需要发送的信息了,它的参数 可以是任何类型,发送的数据格式必须为这样的格式: name=value&anothername=othervalue&so=on,如果你想传送数据,你必须更改MIME类型: httpRequest.setRequestHeader('Content-type','application/x-www-form-urnlencoded'); 否则服务器将会丢弃发送的数据。 */ function getBackInfo() { request = createRequest(); var username=document.getElementById("username").value; var url='/ymail/usernameValidate?username='+username; // var xmlHttp = new ActiveXObject("MSXML2.XMLHTTP"); //alert("请输入用户名!"); request.open("GET",url,"true"); //下面相当于是一个隐性的循环,在函数中规定只有都接收完毕数据后才做处理 //onreadystatechange有5个值: // 0:未初始化 // 1:初始化 // 2:发送数据 // 3:接收数据中 // 4:数据接收完毕 //另外还要注意就是在注册回调函数onreadystatechange时,后面的函数不能够带参数 //如下disResult是一个函数,不能够带参。 request.onreadystatechange=disResult;//隐性的循环 request.send(null); } function disResult() { /** 1.一定要确定readystate==4的完成状态才做下面的事,否则会在建立连接即readystate==1的 时候就开始,然后会在readystate==2,readystate==3,readystate==4的时候都会执行,不信 你可以alert("")一个提示信息试试。 2.服务器通知完成了,并且还要保证是正确完成的,得到的是我们需要的结果才能够继续,这里 常用响应码有: 200:成功执行 401:未授权 403:禁止 404:没有找到文件 */ if(request.readystate==4) { if(request.status==200) { //一切都OK了,那就该用Javascript去执行你想要的动作了。 document.getElementById("disCheckResult").value=request.responseText; //alert(request.responseText); } else { alert('Something Wrong has Happend!'); } } } </script>
记得在页面中添加错误信息显示的位置:
<input type="text" id="disCheckResult" size="50" readonly style="border:0;margin:0 80px;font-size=12;color=red"/>
-
验证码
怎么也弄不出qq邮箱那个效果,谁能告诉我怎么用java2d画随机曲线的?自己做的比较难看:
package servlet;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* 生成随机验证码
* @author bitiliu
*
*/
public class ValidateCodeServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
//验证码图片的宽度。
private int width=30;
//验证码图片的高度。
private int height=15;
//验证码字符个数
private int codeCount=3;
private int x=0;
//字体高度
private int fontHeight;
private int codeY;
char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
/**
* 初始化验证图片属性
*/
public void init() throws ServletException
{
//从web.xml中获取初始信息
//宽度
String strWidth=this.getInitParameter("width");
//高度
String strHeight=this.getInitParameter("height");
//字符个数
String strCodeCount=this.getInitParameter("codeCount");
//将配置的信息转换成数值
try
{
if(strWidth!=null && strWidth.length()!=0)
{
width=Integer.parseInt(strWidth);
}
if(strHeight!=null && strHeight.length()!=0)
{
height=Integer.parseInt(strHeight);
}
if(strCodeCount!=null && strCodeCount.length()!=0)
{
codeCount=Integer.parseInt(strCodeCount);
}
}
catch(NumberFormatException e)
{}
x=width/(codeCount+1);
fontHeight=height;
codeY=height-2;
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException {
//定义图像buffer
BufferedImage buffImg = new BufferedImage(
width, height,BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();
//创建一个随机数生成器类
Random random = new Random();
//将图像填充为白色
g.setColor(new Color(230, 243, 255));
g.fillRect(0, 0, width, height);
//创建字体,字体的大小应该根据图片的高度来定。
Font font = new Font("Arial", Font.ITALIC, 35);
//设置字体。
g.setFont(font);
//画边框。
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
//随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。
g.setColor(Color.BLACK);
int red = 0, green = 0, blue = 0;
for(int i = 0; i < 20; i++)
{
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(30);
int yl = random.nextInt(30);
red = random.nextInt(255);
green = random.nextInt(255);
blue = random.nextInt(255);
//用随机产生的颜色将验证码绘制到图像中。
g.setColor(new Color(red, green, blue));
g.setStroke(new BasicStroke(3.0f));
g.drawArc(x, y, xl, yl,random.nextInt(180),random.nextInt(180));
}
//randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer randomCode = new StringBuffer();
//随机产生codeCount数字的验证码。
for (int i = 0; i < codeCount; i++) {
//得到随机产生的验证码数字。
String strRand = String.valueOf(codeSequence[random.nextInt(36)]);
g.setColor(new Color(red, green, blue));
g.drawString(strRand, (i + 1) * x, codeY);
//将产生的四个随机数组合在一起。
randomCode.append(strRand);
}
// 将四位数字的验证码保存到Session中。
HttpSession session = req.getSession();
session.setAttribute("validateCode", randomCode.toString());
// 禁止图像缓存。
resp.setHeader("Pragma", "no-cache");
resp.setHeader("Cache-Control", "no-cache");
resp.setDateHeader("Expires", 0);
resp.setContentType("image/jpeg");
//将图像输出到Servlet输出流中。
ServletOutputStream sos = resp.getOutputStream();
ImageIO.write(buffImg, "jpeg", sos);
sos.close();
}
}
然后再页面插入该servlet:
<img src="/ymail/validateCodeServlet" οnclick="refresh(this);"/>
<script>
function refresh(e){
e.src="validateCodeServlet";
}
</script>
-
SSL
提到这个,单向双向是老掉牙的问题,这里不用双向,所以只添加了服务器端的验证:
一、生成 KeyStore
这一步比较简单,利用 JDK 自带的 keytool 即可完成。命令如下:
wakan@wakan:~/tomcat2/bin> keytool -genkey -alias tomcat -keyalg RSA
输入keystore密码: ************
您的名字与姓氏是什么?
[Unknown]: Wakan.Jiang
您的组织单位名称是什么?
[Unknown]: ZZNode
您的组织名称是什么?
[Unknown]: ZZNode
您所在的城市或区域名称是什么?
[Unknown]: BeiJing
您所在的州或省份名称是什么?
[Unknown]: BeiJing
该单位的两字母国家代码是什么
[Unknown]: CN
CN=Wakan.Jiang, OU=ZZNode, O=ZZNode, L=BeiJing, ST=BeiJing, C=CN 正确吗?
[否]: 是
输入<tomcat>的主密码
(如果和 keystore 密码相同,按回车):
特别说明:上边输入的“<tomcat>的主密码”,与keystore密码一定要相同,否则TOMCAT起不来。至少我试了几次都不行。报错如下:
2007-3-26 17:07:01 org.apache.coyote.http11.Http11BaseProtocol init
严重: Error initializing endpoint
java.io.IOException: Cannot recover key
at org.apache.tomcat.util.net.jsse.JSSE14SocketFactory.init(JSSE14Socket Factory.java:125)
二、修改 server.xml
在 TOMCAT/conf/server.xml 中,修改与 SSL 相关的那一段,我改成下面这样:
这里要指定keystorePass,如果写错了,会出现下边的错误:
严重: Error initializing endpoint
java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:768)
三、启动 Tomcat
这一步比较简单,就不多说了。启动完成后,在浏览器中输入:https://localhost:8443,即可看到TOMCAT的主页面。
<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
<Connector port="8443" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true" keystorePass="******"
clientAuth="false" sslProtocol="TLS" />