目录
一:概述
二:设计框架
三:实现步骤
第一阶段:表单验证
第二阶段:注册和登陆功能的实现
1、先创建书城需要的数据库和表(使用sqlyog)
2、编写数据库表中对应的javaBean对象——User类
3、编写工具类JDBCUtils并测试
4、编写 BaseDao和与负责数据库交互的Dao
5、编写Service层
6、编写web层(servlet)
第三阶段:编写jsp页面
一:概述
这是尚硅谷javaweb的开源实战项目
主界面:
登录界面:
注册界面:
购物车界面:
二:设计框架
该项目采用MVC三层架构,示意图如下:
① 视图展现层:接收用户请求,负责调用业务层。
②业务层:处理具体的事务逻辑,以及调用持久层的操作。
③持久层:负责与数据库交互,实现数据的增删改查操作。
代码布局如下:
javaweb工程的创建和tomcat服务器的部署详见我的另一篇博客
三:实现步骤
第一阶段:表单验证
验证用户名是否合法:5-12位,由数字,字母或下划线组成
验证密码是否合法:5-12位,由数字,字母或下划线组成
验证确认密码和密码是否相同
验证电子邮件是否合法:
验证验证码是否非空:该阶段暂不用实现验证码的正确性判断
//给注册按钮绑定单击事件
$("#sub_btn").click(function (){
//1.获取输入框用户名
var usernameText=$("#username").val()
var patt=/^\w{5,12}$/
if (!patt.test(usernameText)){
$("span.errorMsg").text("用户名不合法!")
return false
}
//2.获取输入框密码
var passwordText=$("#password").val()
var passwordReText=$("#repwd").val()
if (!patt.test(passwordText)){
$("span.errorMsg").text("密码不合法!")
return false
}
if(passwordReText!==passwordText){
$("span.errorMsg").text("密码不一致!")
return false
}
//3.确认邮箱
var emailpatt=/^\w+@\w+.com$/
var email=$("#email").val()
if(!emailpatt.test(email)){
$("span.errorMsg").text("邮箱不合法!")
return false
}
//4.验证码
var codetext=$("#code").val()
if (codetext==null||codetext==""){
$("span.errorMsg").text("验证码不能为空!")
return false
}
//去除错误信息
$("span.errorMsg").text()
})
第二阶段:注册和登陆功能的实现
1、先创建书城需要的数据库和表(使用sqlyog)
2、编写数据库表中对应的javaBean对象——User类
package com.atguigu.pojo;
public class User {
private Integer id;
private String username;
private String password;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer 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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
'}';
}
public User() {
}
public User(Integer id, String username, String password, String email) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
}
}
3、编写工具类JDBCUtils并测试
package com.atguigu.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class JdbcUtils {
private static DruidDataSource dataSource;
private static ThreadLocal<Connection> conns=new ThreadLocal<>();
static {
try {
Properties properties=new Properties();
//读取jdbc.properties属性配置文件
InputStream resourceAsStream = JdbcUtils.class.getClassLoader().
getResourceAsStream("jdbc.properties");
//从流中加载数据
properties.load(resourceAsStream);
//创建数据库连接池
dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/*
获取数据库连接池中的连接
返回null说明获取失败
*/
public static Connection getConnection(){
Connection conn=conns.get();
if(conn==null){
try {
conn= dataSource.getConnection();
conns.set(conn);//保存到threadLocal对象中,供后面JDBC操作使用
conn.setAutoCommit(false);//手动提交
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return conn;
}
// Connection conn=null;
// try {
// conn=dataSource.getConnection();
// } catch (SQLException throwables) {
// throwables.printStackTrace();
// }
// return conn;
// }
/*
关闭数据库连接,放回数据库连接池
*/
// public static void close(Connection conn){
// if(conn!=null){
// try {
// conn.close();
// } catch (SQLException throwables) {
// throwables.printStackTrace();
// }
// }
// }
/*
提交事务并关闭
*/
public static void commmitAndClose(){
Connection conn=conns.get();
if(conn!=null){
try {
conn.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//一定要执行remove操作,否则就会出错,因为tomcat服务器底层用了线程池技术
conns.remove();
}
/*
回滚事务并关闭
*/
public static void rollbackAndClose(){
Connection conn=conns.get();
if(conn!=null){
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
//一定要执行remove操作,否则就会出错,因为tomcat服务器底层用了线程池技术
conns.remove();
}
}
4、编写 BaseDao和与负责数据库交互的Dao
BaseDao类
package com.atguigu.dao.impl;
import com.atguigu.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
public abstract class BaseDao {
//使用DbUtils操作数据库
private QueryRunner queryRunner=new QueryRunner();
/*
update()用来执行Insert/update/delete语句
返回-1说明执行失败
返回其他表示影响的行数
*/
public int update(String sql,Object ...args){
Connection conn= JdbcUtils.getConnection();
try {
return queryRunner.update(conn,sql,args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/*
查询返回一个javabean的sql语句
*/
public <T> T queryForOne(Class<T> type,String sql,Object ...args){
Connection conn=JdbcUtils.getConnection();
try {
return queryRunner.query(conn,sql,new BeanHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/*
查询返回多个javabean的sql语句
*/
public <T>List<T> queryForList(Class<T> type,String sql,Object ...args){
Connection conn=JdbcUtils.getConnection();
try {
//只有此处不同
return queryRunner.query(conn,sql,new BeanListHandler<T>(type),args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/*
单个查询
*/
public Object queryForSingleValue(String sql,Object...args){
Connection conn=JdbcUtils.getConnection();
try {
return queryRunner.query(conn,sql,new ScalarHandler(),args);
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
UserDaoImpl类,继承了BaseDao实现了UserDao类
package com.atguigu.dao.impl;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;
public class UserDaoImpl extends BaseDao implements UserDao {
@Override
public User queryUserByUsername(String username) {
String sql="select `id`,`username`,`password`,`email` from t_user where username=?";
return queryForOne(User.class,sql,username);
}
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql="select `id`,`username`,`password`,`email` from t_user where username=? and password=?";
return queryForOne(User.class,sql,username,password);
}
@Override
public int saveUser(User user) {
String sql="insert into t_user(`username`,`password`,`email`) values(?,?,?)";
return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
}
}
5、编写Service层
package com.atguigu.service;
import com.atguigu.pojo.User;
public interface UserService {
/*
注册用户
*/
public void registUser(User user);
/*
用户登陆
*/
public User login(User user);
/*
检查用户名是否可用
返回false--用户名不存在说明可用
true--用户名存在说明该用户名不可用
*/
public boolean existsUsername(String username);
}
具体实现类UserServiceImpl
package com.atguigu.dao.impl;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;
public class UserDaoImpl extends BaseDao implements UserDao {
@Override
public User queryUserByUsername(String username) {
String sql="select `id`,`username`,`password`,`email` from t_user where username=?";
return queryForOne(User.class,sql,username);
}
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql="select `id`,`username`,`password`,`email` from t_user where username=? and password=?";
return queryForOne(User.class,sql,username,password);
}
@Override
public int saveUser(User user) {
String sql="insert into t_user(`username`,`password`,`email`) values(?,?,?)";
return update(sql,user.getUsername(),user.getPassword(),user.getEmail());
}
}
6、编写web层(servlet)
package com.atguigu.web;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
public abstract class BaseServlet extends HttpServlet {
private UserService userService=new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决相应的中文问题
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
String action = req.getParameter("action");
try {
Method method = this.getClass().getDeclaredMethod(action,
HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();//吧异常抛给Filter过滤器
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
}
UserServet类:用于实现用户登录,用户注册等功能
package com.atguigu.web;
import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import com.atguigu.utils.WebUtils;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;
public class UserServlet extends BaseServlet {
private UserService userService=new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
try {
Method method = this.getClass().getDeclaredMethod(action,
HttpServletRequest.class,HttpServletResponse.class);
method.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username=req.getParameter("username");
String password=req.getParameter("password");
User login = userService.login(new User(null, username, password, null));
if(login!=null){
//System.out.println("登陆成功!");
req.getSession().setAttribute("user",login);
req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req,resp);
}else{
//System.out.println("用户名或密码错误!");
//把错误信息,和回显的表单项信息,保存到Request域中
req.setAttribute("msg","用户名或密码错误!");
req.setAttribute("username",username);
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
}
}
protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Session中的验证码
String token =(String)req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
//删除Session中的验证码
req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
//1.获取请求的参数。比如用户名密码邮箱验证码等
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
User user= WebUtils.copyParamToBean(req.getParameterMap(),new User());
//2.检查验证码是否正确
if(token!=null&&token.equalsIgnoreCase(code)){
// 正确 3检查用户名是否可用
if(userService.existsUsername(username)){
//不可用 跳转到注册页面
//System.out.println("用户名"+username+"已存在!");
req.setAttribute("msg","用户名已存在");
req.setAttribute("username",username);
req.setAttribute("email",email);
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);
}else{
//可用 调用Service保存到数据库,跳转到登陆成功页面
userService.registUser(user);
req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req,resp);
}
}else{
// 不正确 跳回注册页面
req.setAttribute("msg","验证码错误!");
req.setAttribute("username",username);
req.setAttribute("email",email);
//System.out.println("验证码["+code+"]错误");
req.getRequestDispatcher("/pages/user/regist.jsp").forward(req,resp);
}
}
/*
注销用户
*/
protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.销毁Session中的用户登陆信息
//2.重定向到首页
req.getSession().invalidate();
resp.sendRedirect(req.getContextPath());
}
/*
*/
protected void ajaxExistsUsername(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的参数username
String username = req.getParameter("username");
//调用userservice.existsUsername();
boolean existsUsername = userService.existsUsername(username);
//把返回的结果封装成map对象
Map<String,Object> resultMap=new HashMap<>();
resultMap.put("existsUsername",existsUsername);
Gson gson = new Gson();
String json = gson.toJson(resultMap);
resp.getWriter().write(json);
}
}
第三阶段:编写jsp页面
1.将网页中公共的部分,如页脚,log,css等公共部分进行提取为head.jsp。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String basepath=request.getScheme()+"://"+
request.getServerName()+":"+
request.getServerPort()+
request.getContextPath()+"/";
pageContext.setAttribute("basepath",basepath);
%>
<!--写base标签固定跳转路径-->
<base href="<%=basepath%>">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>
2.将每个.jsp都静态包含head.jsp
<%--静态包含base标签,css样式,jquery文件--%>
<%@include file="/pages/common/head.jsp"%>
3.将项目中所有的html改写为jsp文件