----------------------------------------------------写在前面-------------------------------------------------------
作为一名小小程序猿,已经工作一年多了,由于平时不用功学习,导致技术上积累太单薄。2015年即将结束,突然发现自己这一年来进不如此至少,心里有点发慌。于是想改头换面,从新学习。
Java Web知识点多,想要系统的学习需要多做一些实战项目。于是我决定通过写一个个我们常用的模块来系统的学习Java web相关技术。首先决定从登陆注册模块开始,因为这是我们平时最常用的一个模块。
时间有限,我就不一一讲解项目从头到尾是如何创建的,这篇文章也是给有一定基础的Java开发人员看的。由于技术有限,难免会有很多疏忽,如果大家发现有什么不对的地方,欢迎指正!谢谢!
------------------------------------------------------------正文---------------------------------------------------
一. MYSQL数据库创建
(我是用MySQL workbench创建的表,没用SQL语句。表的数据结构如下图)
主要有留个字段: username用户名,password密码,email邮箱,status激活状态,validateCode激活码,signupTime注册时间。
2. RegisterAction注册
(这里我就只贴出execute方法里面的代码,全部代码请见github,github地址我会在博文最后贴出)
private String signupUsername;
private String signupPassword;
private String signupEmail;
private int status;
private String validateCode;
private Date signupTime;
private UserService userService;
@Override
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
signupUsername = (String) stack.findValue("signupUsername");
signupPassword = (String) stack.findValue("signupPassword");
signupPassword = MD5Util.encode2hex(signupPassword);
signupEmail = (String) stack.findValue("signupEmail");
User existingUser = this.userService.find(signupEmail);
if (existingUser != null) {
return ERROR;
} else {
signupTime = new Date();
status=0;
validateCode = MD5Util.encode2hex(signupEmail);
User user = new User(signupUsername,signupPassword,signupEmail,status,validateCode,signupTime);
userService.save(user);
StringBuffer sb=new StringBuffer("Please active your account within 48 hours!");
sb.append("<br/>");
sb.append("<a href = \"http://localhost:8080/RegistrationAndLoginExample/activeAccount?signupEmail=");
sb.append(signupEmail);
sb.append("&validateCode=");
sb.append(user.getValidateCode());
sb.append("\">Click here to activate your account!</a>");
SendEmail.send(signupEmail, sb.toString());
return SUCCESS;
}
}
3. 发邮件
public class SendEmail {
public static final String HOST = "smtp.163.com";
public static final String PROTOCOL = "smtp";
public static final int PORT = 25;
public static final String FROM = "请填写你的邮箱";
public static final String PWD = "请填写你邮箱密码";
private static Session getSession() {
Properties props = new Properties();
props.put("mail.smtp.host", HOST);
props.put("mail.store.protocol" , PROTOCOL);
props.put("mail.smtp.port", PORT);
props.put("mail.smtp.auth" , true);
Authenticator authenticator = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(FROM, PWD);
}
};
Session session = Session.getInstance(props , authenticator);
return session;
}
public static void send(String toEmail , String content) {
Session session = getSession();
try {
System.out.println("--send--"+content);
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(FROM));
InternetAddress[] address = {new InternetAddress(toEmail)};
msg.setRecipients(Message.RecipientType.TO, address);
msg.setSubject("Account Activation");
msg.setSentDate(new Date());
msg.setContent(content , "text/html;charset=utf-8");
Transport.send(msg);
}
catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
4. MD5加密
public class MD5Util {
public static byte[] encode2bytes(String source) {
byte[] result = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(source.getBytes("UTF-8"));
result = md.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
public static String encode2hex(String source) {
byte[] data = encode2bytes(source);
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < data.length; i++) {
String hex = Integer.toHexString(0xff & data[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
public static boolean validate(String unknown , String okHex) {
return okHex.equals(encode2hex(unknown));
}
}
5. ActiveAccountAction激活账户
private static final long serialVersionUID = 1L;
private String signupEmail;
private String validateCode;
private UserService userService;
@Override
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
String signupEmail = (String) stack.findValue("signupEmail");
String validateCode = (String) stack.findValue("validateCode");
User user = this.userService.find(signupEmail);
if(user!=null) {
if(user.getStatus()==0) {
Date currentTime = new Date();
currentTime.before(user.getSignupTime());
if(currentTime.before(user.getLastActivateTime())) {
if(validateCode.equals(user.getValidateCode())) {
//update status to 1
user.setStatus(1);
this.userService.modify(user);
} else {
throw new ServiceException("validate code is not correct!");
}
} else { throw new ServiceException("validate code has been expired!");
}
} else {
throw new ServiceException("email has been activated!");
}
} else {
throw new ServiceException("this email has not been registered!");
}
return SUCCESS;
}
6. LoginAction登录
private String email;
private String password;
private UserService userService;
@Override
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
String email = (String) stack.findValue("email");
String password = (String) stack.findValue("password");
password = MD5Util.encode2hex(password);
if (email != null && email.length() > 0) {
if (password != null && password.length() > 0) {
if (this.userService == null) {
return ERROR;
}
User user = this.userService.find(email);
if (user != null) {
if(user.getStatus()==0){
return ERROR;
}else if (user.getPassword().equals(password)) {
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
session.setAttribute("user", user);
return SUCCESS;
}
}
}
}
return ERROR;
}
7. index.jsp 登录,注册等页面
<!DOCTYPE html>
<html>
<head>
<title>Login Example</title>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.13.0/jquery.validate.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="js/main.js"></script>
<script src="js/alert.js"></script>
</head>
<body>
<div class="container">
<div id="loginbox" style="margin-top:50px;" class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="panel panel-info" >
<div class="panel-heading">
<div class="panel-title">Sign In</div>
<div style="float:right; font-size: 80%; position: relative; top:-10px">
<a href="#" onclick="$('#signupbox').hide(); $('#forgetpasswordbox').show();$('#loginbox').hide()">Forgot password?</a>
</div>
</div>
<div style="padding-top:30px" class="panel-body" >
<div style="display:none" id="login-alert" class="alert alert-danger col-sm-12"></div>
<form action="login" method="post" id="loginform" class="form-horizontal" role="form">
<div class="form-group">
<label class="col-md-3 control-label" for="email">Email</label>
<div class="col-md-6">
<div class="input-group"> <span class="input-group-addon"><i class="fa fa-envelope-o fa-fw"></i></span>
<input id="email" name="email" type="text" placeholder="Enter Your Email" class="form-control input-md">
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label" for="Password">Password</label>
<div class="col-md-6">
<div class="input-group"> <span class="input-group-addon"><i class="fa fa-key fa-fw"></i></span>
<input id="password" name="password" type="password" placeholder="Enter Your Password" class="form-control input-md">
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label" for="Submit"></label>
<div class="checkbox col-md-4">
<label><input id="login-remember" type="checkbox" name="remember" value="1" > Remember me</label>
</div>
<div class="col-md-4">
<input id="Submit" class="btn btn-success" type="submit" value="Login">
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div style="border-top: 1px solid#888; padding-top:15px; font-size:85%" >
Don't have an account?
<a href="#" onClick="$('#loginbox').hide();$('#forgetpasswordbox').hide(); $('#signupbox').show()">Sign Up Here</a>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="signupbox" style="display:none; margin-top:50px" class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Sign Up</div>
<div style="float:right; font-size: 85%; position: relative; top:-10px">
<a id="signinlink" onclick="$('#signupbox').hide(); $('#forgetpasswordbox').hide();$('#loginbox').show()">Sign In</a></div>
</div>
<div class="panel-body" >
<form action="register" method="post" id="signupform" class="form-horizontal" role="form" onSubmit="return checkForm('signUpEmail')">
<div class="form-group">
<label for="signUpEmail" class="col-md-3 control-label">Email</label>
<div class="col-md-9">
<input type="text" class="form-control" id = "signupEmail" name="signupEmail" placeholder="Email Address" onblur="checkEmail(signupEmail)">
</div>
</div>
<div class="form-group">
<label for="username" class="col-md-3 control-label">User Name</label>
<div class="col-md-9">
<input type="text" class="form-control" name="signupUsername" placeholder="User Name">
</div>
</div>
<div class="form-group">
<label for="signupPassword" class="col-md-3 control-label">Password</label>
<div class="col-md-9">
<input type="password" id="signupPassword" class="form-control" name="signupPassword" placeholder="Password">
</div>
</div>
<div class="form-group">
<label for="confirmPassword" class="col-md-3 control-label">Confirm Password</label>
<div class="col-md-9">
<input type="password" class="form-control" name="confirm" id="confirm" placeholder="Confirm Password">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-3 col-md-9">
<input id="btn-signup" type="submit" class="btn btn-info" value="Sign Up"/>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="forgetpasswordbox" style="display:none; margin-top:50px" class="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Forgot Password</div>
<div style="float:right; font-size: 85%; position: relative; top:-10px"><a id="signinlink" href="#" onclick="$('#signupbox').hide();$('#forgetpasswordbox').hide();$('#loginbox').show()">Sign In</a></div>
</div>
<div class="panel-body" >
<form action="forgotPassword" method="post" id="forgotPasswordForm" class="form-horizontal" role="form" onSubmit="return checkForm('forgotPasswordEmail')">
<div class="form-group">
<label class="col-md-3 control-label" for="email">Email</label>
<div class="col-md-6">
<div class="input-group"> <span class="input-group-addon"><i class="fa fa-envelope-o fa-fw"></i></span>
<input id="forgotPasswordEmail" name="forgotPasswordEmail" type="text" placeholder="Enter Your Email" class="form-control input-md" onblur="checkForm('forgotPasswordEmail')">
</div>
</div>
<div class="col-md-3">
<input id="btn-sendEmail" type="submit" class="btn btn-success" value="Send Email"/>
</div>
</div>
<div class="form-group">
<div class="col-md-12 control">
<div style="border-top: 1px solid#888; padding-top:15px; font-size:85%" >
Don't have an account?
<a href="#" onClick="$('#loginbox').hide(); $('#forgetpasswordbox').hide();$('#signupbox').show()">Sign Up Here</a>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
这里引用了bootstrap, 和JQury, 同时用到了Ajax去实时查询用户所填写的邮箱是否已经注册过。
8. ForgotPasswordAction 忘记密码
private String forgotPasswordEmail;
private UserService userService;
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
forgotPasswordEmail = (String) stack.findValue("forgotPasswordEmail");
User existingUser = this.userService.find(forgotPasswordEmail);
if (existingUser == null) {
return ERROR;
} else {
Long validateCode = System.currentTimeMillis()+30*60*1000;
StringBuffer sb=new StringBuffer("Please reset your password within 30 mins!");
sb.append("<br/>");
sb.append("<a href = \"http://localhost:8080/RegistrationAndLoginExample/resetPassword?email=");
sb.append(forgotPasswordEmail);
sb.append("&validateCode=");
sb.append(validateCode);
sb.append("\">Click here to reset your password!</a>");
SendEmail.send(forgotPasswordEmail, sb.toString());
return SUCCESS;
}
}
当用户请求忘记密码时,发一封邮件到用户邮箱, 要求用户30分钟内完成修改密码。否则此次请求过期。
9. ResetPasswordAction重置密码
private String email;
private String validateCode;
private UserService userService;
@Override
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
String email = (String) stack.findValue("email");
String validateCode = (String) stack.findValue("validateCode");
User user = this.userService.find(email);
if(user!=null) {
if(user.getStatus()!=0) {
Long currentTime = System.currentTimeMillis();
if(currentTime<Long.parseLong(validateCode)) {
return SUCCESS;
} else {
return ERROR;
}
} else {
throw new ServiceException("email has not been activated!");
}
} else {
throw new ServiceException("this email has not been registered!");
}
}
10. UpdatePasswordAction更新密码
private String email;
private String oldPassword;
private String newPassword;
private UserService userService;
@Override
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
String email = (String) stack.findValue("email");
String oldPassword = (String) stack.findValue("oldPassword");
String newPassword = (String) stack.findValue("newPassword");
User user = this.userService.find(email);
if(user!=null) {
if(user.getStatus()==1) {
if(user.getPassword().equals(MD5Util.encode2hex(oldPassword))){
user.setPassword(MD5Util.encode2hex(newPassword));
this.userService.modify(user);
} else {
throw new ServiceException("Old password is not correct!");
}
} else {
throw new ServiceException("email has not been activated!");
}
} else {
throw new ServiceException("this email has not been registered!");
}
return SUCCESS;
}
11. struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<constant name="struts.objectFactory" value="spring" />
<package name="user" extends="struts-default">
<global-results>
<result name="serviceException">/exception.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="ServiceException" result="serviceException" />
</global-exception-mappings>
<action name="login" class="LoginAction">
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
</action>
<action name="register" class="RegisterAction">
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
</action>
<action name="userCheck" class="UserCheckAction">
</action>
<action name="activeAccount" class="ActiveAccountAction">
<result name="success">success.jsp</result>
</action>
<action name="forgotPassword" class="ForgotPasswordAction">
<result name="error">error.jsp</result>
<result name="success">success.jsp</result>
</action>
<action name="resetPassword" class="ResetPasswordAction">
<result name="success">resetPassword.jsp</result>
<result name="error">error.jsp</result>
</action>
<action name="updatePassword" class="UpdatePasswordAction">
<result name="success">success.jsp</result>
<result name="error">error.jsp</result>
</action>
</package>
<package name="ajax_json" extends="json-default">
<action name="userCheck" class="UserCheckAction">
<result name="success" type="json"/>
</action>
</package>
</struts>
12.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver">
</property>
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test">
</property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/model/User.hbm.xml</value>
</list>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="userDao" class="com.dao.UserDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
<bean id="userService" class="com.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="LoginAction" class="com.action.LoginAction">
<property name="userService" ref="userService"></property>
</bean>
<bean id="RegisterAction" class="com.action.RegisterAction">
<property name="userService" ref="userService"></property>
</bean>
<bean id="ActiveAccountAction" class="com.action.ActiveAccountAction">
<property name="userService" ref="userService"></property>
</bean>
<bean id="UserCheckAction" class="com.action.UserCheckAction">
<property name="userService" ref="userService"></property>
</bean>
<bean id="ForgotPasswordAction" class="com.action.ForgotPasswordAction">
<property name="userService" ref="userService"></property>
</bean>
<bean id="ResetPasswordAction" class="com.action.ResetPasswordAction">
<property name="userService" ref="userService"></property>
</bean>
<bean id="UpdatePasswordAction" class="com.action.UpdatePasswordAction">
<property name="userService" ref="userService"></property>
</bean>
</beans>
项目全部代码我已经上传到我个人的github上,欢迎大家fork,把这个模块做的越来越完善。
https://github.com/aoxinxing/RegistrationAndLoginExample