遵守javaweb开发的MVC模式。
已知问题:
1.不能注册中文用户(并没有用pattern约束)
2.没有注册输入格式不对的提示,但是可以写入Map集合并且跳转到regist.jsp。点击注册后输入框清空,因为是转发所以地址栏没变正常。
问题已解决。
1.开始时注册用户名为中文的时候认为是账号密码错误无法登陆。原因是问题分析错误:LoginServlet.java类中写的是一个响应跳转,而实际是需要请求转发到login.jsp中的,而非仅仅跳转过去。并不是由于中文用户注册引起的。
2.注册失败时没有提示的总是回抛出一个在com.aloha.domain.UserForm中找不到msg属性的异常。最后发现是由于存放异常信息的Map集合的set/get方法忘记添加了,抛出的异常。
3.BeanUtils的populate方法是可以校验日期是否越界的。如果越界会通过Exception 的对象抛出这个异常,将这个异常同样以一个错误的回显形式请求转发给regist.jsp个面,可以对应提示生日的不合常理问题,如2月30日。
下面是问题代码,修改后的代码在网盘中:
https://pan.baidu.com/s/1UKnt1Ch27rompcONI4NdSQ
UserDao.java
package com.aloha.dao;
import com.aloha.domain.User;
/**
* 这是用户数据库连接的接口
* @author malaganguo
*
*/
public interface UserDao {
/**
* 添加用户信息
* @param user 用户对象
* @throws Exception
*/
void addUser(User user) throws Exception;
/**
* 在数据库中核对用户
* @param user
* @return
* @throws Exception
*/
User findUser(User user) throws Exception;
/**
* 根据用户名查找用户是否存在
* @param name
* @return
*/
boolean findUserByName(String name);
}
UserDaoImpl.java
package com.aloha.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import javax.persistence.PrePersist;
import com.aloha.dao.UserDao;
import com.aloha.domain.User;
import com.aloha.utils.DBUtils;
/**
* 这是数据库接口的实现类
* @author malaganguo
*
*/
public class UserDaoImpl implements UserDao{
public void addUser(User user) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBUtils.getConnection();
pstmt = conn.prepareStatement("INSERT INTO users(username,PASSWORD,email,birthday) VALUES(?,?,?,?)");
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
pstmt.setString(3, user.getEmail());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(user.getBirthday());
pstmt.setString(4, date);
System.out.println(pstmt.executeUpdate());//返回的是几行受影响的值
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("添加失败!");
}finally{
DBUtils.closeAll(null, pstmt, conn);
}
}
public User findUser(User user) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
User u = null;
try {
conn = DBUtils.getConnection();
pstmt = conn.prepareStatement("SELECT * FROM users WHERE username=? AND PASSWORD=?");
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getPassword());
rs = pstmt.executeQuery();
if(rs.next()){//如果返回的结果集中有值
u =new User();
u.setId(rs.getInt(1));
u.setUsername(rs.getString(2));
u.setPassword(rs.getString(3));
u.setEmail(rs.getString(4));
u.setBirthday(rs.getDate(5));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(rs, pstmt, conn);
}
return u;
}
/**
* 如果当前用户名已存在,则返回true,否则返回false
*/
public boolean findUserByName(String name) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBUtils.getConnection();
pstmt = conn.prepareStatement("SELECT * FROM users WHERE username=?");
pstmt.setString(1, name);
rs = pstmt.executeQuery();
if(rs.next()){//如果这个名字存在
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(rs, pstmt, conn);
}
return false;
}
}
User.java
package com.aloha.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable{
private int id;
private String username;
private String password;
private String email;
private Date birthday;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
UserForm.java
package com.aloha.domain;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
public class UserForm {
private int id;
private String username;
private String password;
private String repassword;
private String email;
private String birthday;
Map msg = new HashMap();
/*用户名:必须输入,且3~8位的字母组成
密码:必须输入,3~8位的数组组成
确认密码:和密码保持一致
邮箱:必须输入,且要符合邮箱的格式
生日:必须输入,符合yyyy-MM-dd的格式
*/
/**
* 这是一个规范输入的方法
* @return 符合规范返回true,不符合规范返回false
*/
public boolean validate(){
if("".equals(username)){
msg.put("username", "用户名不能为空!");
}
if("".equals(password)){
msg.put("password", "密码不能为空!");
}
if(!repassword.equals(password)){
msg.put("repassword", "两次密码不一致!");
}
if("".equals(email)){
msg.put("email", "邮箱不能为空!");
}else if(!email.matches("\\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2}|aero|arpa|asia|biz|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|nato|net|org|pro|tel|travel|xxx)$\\b")){
msg.put("email", "邮箱格式不正确!");
}
if("".equals(birthday)){
msg.put("birthday", "生日不能为空!");
}else {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
sdf.parse(birthday);
} catch (ParseException e) {
msg.put("birthday", "生日格式不正确!");
}
}
//所有不符合规范的输入都将输入键入Map集合中。所以当完全符合规范的时候,msg是为null的。
return msg.isEmpty();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRepassword() {
return repassword;
}
public void setRepassword(String repassword) {
this.repassword = repassword;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
UsersException.java
package com.aloha.exception;
public class UsersException extends Exception {
/**
* 此类无参构造访问父类无参构造
*/
public UsersException() {
super();
}
/**
* 以下都是子类有参构造访问父类
* @param message
* @param cause
*/
public UsersException(String message, Throwable cause) {
super(message, cause);
}
public UsersException(String message) {
super(message);
}
public UsersException(Throwable cause) {
super(cause);
}
}
UsersExistException.java
package com.aloha.exception;
/**
* 这是用户退出异常类
* @author malaganguo
*
*/
public class UsersExistException extends Exception {
public UsersExistException() {
super();
}
public UsersExistException(String message, Throwable cause) {
super(message, cause);
}
public UsersExistException(String message) {
super(message);
}
public UsersExistException(Throwable cause) {
super(cause);
}
}
UserService.java
package com.aloha.service;
import com.aloha.domain.User;
import com.aloha.exception.UsersException;
import com.aloha.exception.UsersExistException;
/**
* 这是根据用户需求写的接口
* @author malaganguo
*
*/
public interface UserService {
/**
* 添加用户信息
* @param user
* @throws Exception
*/
void register(User user) throws Exception;
/**
* 根据用户名和密码查找用户信息
* @param user
* @return
* @throws UsersException
*/
User login(User user) throws UsersException;
public boolean findUserByName(String name) throws UsersExistException;
}
UserServiceImpl.java
package com.aloha.service.impl;
import com.aloha.dao.UserDao;
import com.aloha.dao.impl.UserDaoImpl;
import com.aloha.domain.User;
import com.aloha.exception.UsersExistException;
import com.aloha.service.UserService;
public class UserServiceImpl implements UserService {
UserDao ud = new UserDaoImpl();
public void register(User user) throws Exception {
ud.addUser(user);
}
public User login(User user) {
User u = null;
try {
u=ud.findUser(user);
} catch (Exception e) {
e.printStackTrace();
}
return u;
}
public boolean findUserByName(String name) throws UsersExistException {
boolean b = ud.findUserByName(name);
if(b){
throw new UsersExistException("此用户已存在");
}
return b;
}
}
DBUtils.java
package com.aloha.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
public class DBUtils {
private static String driverClass;
private static String url;
private static String username;
private static String password;
/**
* properties文件传值以及反射加载jdbc连接驱动
*/
static{
ResourceBundle rb = ResourceBundle.getBundle("dbinfo");
driverClass = rb.getString("driverClass");
url = rb.getString("url");
username = rb.getString("username");
password = rb.getString("password");
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 这是简化后的创建获取连接的工具
* @return 获取到的连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url, username, password);
}
/**
* 这是关闭资源的工具
* @param rs 这是返回结果集对象
* @param stmt 这是执行SQL语句对象
* @param conn 这是获取连接对象
*/
public static void closeAll(ResultSet rs, Statement stmt, Connection conn){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
LoginOutServlet.java
package com.aloha.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginOutServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.getSession().invalidate();//注销:销毁session
response.sendRedirect(request.getContextPath()+"/index.jsp");
//这样写就不会跳转
// response.getWriter().write("注销成功,2秒后跳转到主页");
// response.setHeader("refresh", "2;url="+request.getContextPath()+"/index.jsp");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
LoginServlet.java
package com.aloha.web.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.aloha.domain.User;
import com.aloha.service.UserService;
import com.aloha.service.impl.UserServiceImpl;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//服务器和客户端共同约定使用UTF-8编码格式
response.setContentType("text/html;charset=UTF-8");
User u = new User();
try {
BeanUtils.populate(u, request.getParameterMap());
UserService us = new UserServiceImpl();
User user = us.login(u); //重新创建对象,如果在数据库中查找不到,那么u就为空了
if(user != null){
request.getSession().setAttribute("user", u);//如果登录成功就把user对象放到session对象中
request.getRequestDispatcher("/index.jsp").forward(request, response);
}else{
response.getWriter().write("用户名或者密码错误,2秒后跳转到主页!");
// response.sendRedirect(request.getContextPath()+"/login.jsp");//如果登录失败跳回到登录页面
response.setHeader("refresh", "2;url="+request.getContextPath()+"/login.jsp");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
RegServlet.java
package com.aloha.web.servlet;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import com.aloha.domain.User;
import com.aloha.domain.UserForm;
import com.aloha.exception.UsersExistException;
import com.aloha.service.UserService;
import com.aloha.service.impl.UserServiceImpl;
public class RegServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//验证操作
UserForm uf = new UserForm();
try {
BeanUtils.populate(uf, request.getParameterMap());
} catch (Exception e1) {
e1.printStackTrace();
}
if(!uf.validate()){//如果map集合不为空,说明格式有误
request.setAttribute("uf", uf);
System.out.println("map集合不为空");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
System.out.println("已完成请求转发");
return; //这个空的return语句可以让格式错误的表单不提交到服务器中,即下面的代码不执行了
}
//获取表单数据
User u = new User();
try {
ConvertUtils.register(new DateLocaleConverter(), Date.class);//这里给提交的Date类型数据提供注册
BeanUtils.populate(u, request.getParameterMap());//使用apache提供的Bean工具类获取表单数据,支持四类八种数据的转换,但是Date不包含在内,所以会报错
//处理业务逻辑
UserService us = new UserServiceImpl();
us.findUserByName(u.getUsername());
us.register(u);
} catch (UsersExistException e) {
request.setAttribute("error", "用户名已存在");
request.getRequestDispatcher("/regist.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
//分发转向
response.getWriter().write("注册成功,1秒后进入主页。");
response.setHeader("refresh", "1;url="+request.getContextPath()+"/index.jsp");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
dbinfo.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbctest
username=root
password=root
web.xml
RegServlet
com.aloha.web.servlet.RegServlet
LoginServlet
com.aloha.web.servlet.LoginServlet
LoginOutServlet
com.aloha.web.servlet.LoginOutServlet
RegServlet
/servlet/regServlet
LoginServlet
/servlet/loginServlet
LoginOutServlet
/servlet/loginOutServlet
index.jsp
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
My JSP 'index.jsp' starting page
登录
注册
欢迎你:${user.username } 注销
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
登录页面
regist.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
<%-- 这里使用了EL表达式来给html标签的value传递真实的值,在输入框后面打印校验信息。因为EL表达式具有很强的容错能力,即找不到值就不打印,所以很方便 --%>