1、表单验证的实现
现将文件拷贝进新的模块
然后完成以下需求
字母、数字、下划线组成,且长度是5-12, 由正则表达式表示为
var patt = /^\w{5,12}$/;
if(patt.test(usernameText)){
alert("用户名合法!");
}else {
alert("用户名不合法!");
}
邮箱部分也需要由正则表达式表示,可查看jQuery文档的 “其他” 里面
代码
<head>
<meta charset="UTF-8">
<title>尚硅谷会员注册页面</title>
<link type="text/css" rel="stylesheet" href="../../static/css/style.css" >
<style type="text/css">
.login_form{
height:420px;
margin-top: 25px;
}
</style>
<script type="text/javascript" src="../../static/script/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
$("#sub_btn").click(function () {
var patt = /^\w{5,12}$/;
var usernameText = $("#username").val();
if(!patt.test(usernameText)) {
$("span.errorMsg").text("用户名不合法")
return false
}
var passwordText = $("#password").val();
if(!patt.test(passwordText)) {
$("span.errorMsg").text("密码不合法")
return false
}
var repwdText = $("#repwd").val();
if(!(repwdText == passwordText)){
$("span.errorMsg").text("密码不一致")
return false
}
var emailText = $("#email").val();
var emailpatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
if(!emailpatt.test(emailText)) {
$("span.errorMsg").text("邮箱不合法")
return false
}
var codeText = $("#code").val();
var trim = $.trim(codeText);
if(trim == null || trim == "") {
$("span.errorMsg").text("验证码为空")
return false
}
$("span.errorMsg").text("")
})
})
</script>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="../../static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎注册</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>注册尚硅谷会员</h1>
<span class="errorMsg"></span>
</div>
<div class="form">
<form action="regist_success.html">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名" autocomplete="off" tabindex="1" name="username" id="username" />
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码" autocomplete="off" tabindex="1" name="password" id="password" />
<br />
<br />
<label>确认密码:</label>
<input class="itxt" type="password" placeholder="确认密码" autocomplete="off" tabindex="1" name="repwd" id="repwd" />
<br />
<br />
<label>电子邮件:</label>
<input class="itxt" type="text" placeholder="请输入邮箱地址" autocomplete="off" tabindex="1" name="email" id="email" />
<br />
<br />
<label>验证码:</label>
<input class="itxt" type="text" style="width: 150px;" id="code"/>
<img alt="" src="../../static/img/code.bmp" style="float: right; margin-right: 40px">
<br />
<br />
<input type="submit" value="注册" id="sub_btn" />
</form>
</div>
</div>
</div>
</div>
</div>
<div id="bottom">
<span>
尚硅谷书城.Copyright ©2015
</span>
</div>
</body>
2、用户注册和登陆
注意点:
- 在数据库连接操作的时候,导入properties配置文件的时候,不可以使用系统类加载器ClassLoader.getSystemResourceAsStream
- 在注册和登录的 html 页面中,表单提交的链接部分,链接填写的是提供的 Servlet 程序的链接,可以写相对路径和绝对路径
- 绝对路径:后续若使用请求中转会无法使用样式等文件(参考Servlet文章)
- 相对路径:需要写 base 标签,该页面内所有的相对路径都是相对于base标签中的路径,则页面的css样式以及 jquery的配置文件的路径全部要进行更改。
跳转页面的时候可使用请求中转
需求 1:用户注册 1)访问注册页面 2)填写注册信息,提交给服务器 3)服务器应该保存用户 4)当用户已经存在----提示用户注册失败,用户名已存在 5)当用户不存在-----注册成功
需求 2:用户登陆 1)访问登陆页面 2)填写用户名密码后提交 3)服务器判断用户是否存在 4)如果登陆失败 —>>>> 返回用户名或者密码错误信息 5)如果登录成功 —>>>> 返回登陆成功信息
JavaEE 项目的三层架构
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级
2.1、数据库层
第三方 jar 包放在 web 目录的 WEB-INF 文件夹下
2.1.1、创建数据库
数据库存放用户注册的数据
2.1.2、定义 JavaBean 类
编写数据库表对应的 JavaBean 对象
public class User {
private int id;
private String username;
private String password;
private String email;
}
2.1.3、编写工具类 JdbcUtils
使用 Druid 数据库连接池,导入 jar 包
在 src 源码目录下编写 jdbc.properties 属性配置文件 工具类 JdbcUtils 中封装数据库链接和关闭操作
注意,在连接操作中,如果使用ClassLoader.getSystemResourceAsStream(“文件名”),在后面项目运行的时候会报空指针异常
要使用jdbcUtils.class.getClassLoader().getResourceAsStream(“druid.properties”)
package com.atguigu.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.pool.DruidPooledConnection;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class jdbcUtils {
private static DruidDataSource dataSource;
static {
try {
Properties pro = new Properties();
pro.load(jdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getconn(){
DruidPooledConnection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
public static void close(Connection conn){
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
如果获取了数据库连接池的连接没有及时释放,就只能获取最大连接数的连接
但是如果及时的释放了连接,那获取几个连接都没有问题
2.2、DAO 层
2.2.1、编写 BaseDAO父类
package com.atguigu.DAO;
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.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
public class BaseDAO<T> {
private Class<T> clazz = null;
{
ParameterizedType parameterized = (ParameterizedType) this.getClass().getGenericSuperclass();
Type[] type = parameterized.getActualTypeArguments();
clazz = (Class<T>) type[0];
}
private QueryRunner qr = new QueryRunner();
public void update(Connection conn,String sql,Object...args){
try {
int i = qr.update(conn, sql, args);
System.out.println("影响了" + i + "条数据");
} catch (SQLException e) {
e.printStackTrace();
}
}
public T queryForOne(Connection conn,String sql,Object...args){
T t = null;
try {
t = qr.query(conn,sql,new BeanHandler<T>(clazz),args);
return t;
} catch (SQLException e) {
e.printStackTrace();
}
return t;
}
public List<T> queryForList(Connection conn,String sql,Object...args){
List<T> list = null;
try {
list = qr.query(conn, sql, new BeanListHandler<T>(clazz), args);
return list;
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
public Object queryForSingleValue(Connection conn,String sql,Object...args){
Object o = null;
try {
o = qr.query(conn, sql, new ScalarHandler(), args);
} catch (SQLException e) {
e.printStackTrace();
}
return o;
}
}
2.2.2、编写 UserDAO接口
package com.atguigu.DAO;
import com.atguigu.bean.User;
import java.sql.Connection;
public interface UserDAO {
User queryUserByUsername(Connection connection, String username);
User queryUserByUsernameAndPassword(Connection connection,String username,String password);
void saveUser(Connection connection,User user);
}
2.2.3、编写 UserDAOImpl
package com.atguigu.DAO.impl;
import com.atguigu.DAO.BaseDAO;
import com.atguigu.DAO.UserDAO;
import com.atguigu.bean.User;
import java.sql.Connection;
public class UserDAOImpl extends BaseDAO<User> implements UserDAO {
@Override
public User queryUserByUsername(Connection connection, String username) {
String sql = "select * from `t_user` where username = ?";
User user = queryForOne(connection, sql, username);
return user;
}
@Override
public User queryUserByUsernameAndPassword(Connection connection, String username, String password) {
String sql = "select * from `t_user` where username = ? and password = ?";
User user = queryForOne(connection, sql, username, password);
return user;
}
@Override
public void saveUser(Connection connection, User user) {
String sql = "insert into `t_user`(`id`,`username`,`password`,`email`) values(?,?,?,?)";
update(connection,sql,user.getId(),user.getUsername(),user.getPassword(),user.getEmail());
}
}
2.3、Service 层
该层编写的是具体的业务
比如,登录、注册、验证用户名是否重复
2.3.1、编写 UserService接口
package com.atguigu.service;
import com.atguigu.bean.User;
public interface UserService {
void registerUser(User user);
User login(User user);
boolean existsUsername(String username);
}
2.3.2、编写 UesrServiceImpl
package com.atguigu.service.impm;
import com.atguigu.DAO.UserDAO;
import com.atguigu.DAO.impl.UserDAOImpl;
import com.atguigu.bean.User;
import com.atguigu.service.UserService;
import com.atguigu.utils.jdbcUtils;
import java.sql.Connection;
public class UesrServiceImpl implements UserService {
private UserDAO userDAO = new UserDAOImpl();
@Override
public void registerUser(User user) {
Connection conn = jdbcUtils.getconn();
userDAO.saveUser(conn,user);
jdbcUtils.close(conn);
}
@Override
public User login(User user) {
Connection conn = jdbcUtils.getconn();
User user1 = userDAO.queryUserByUsernameAndPassword(conn, user.getUsername(), user.getPassword());
jdbcUtils.close(conn);
return user1;
}
@Override
public boolean existsUsername(String username) {
Connection conn = jdbcUtils.getconn();
User user = userDAO.queryUserByUsername(conn, username);
jdbcUtils.close(conn);
return user != null;
}
}
2.4、Web 层
web.xml 文件中的配置
<servlet>
<servlet-name>RegistServlet</servlet-name>
<servlet-class>com.atguigu.web.RegistServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.atguigu.web.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegistServlet</servlet-name>
<url-pattern>/registServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
2.4.1、注册servlet
选择 POST 请求方式,是因为在转入网址之后,不会显现密码的内容
注册成功或者注册失败的时候,跳转页面使用的是 响应的请求重定向
package com.atguigu.web;
import com.atguigu.bean.User;
import com.atguigu.service.impm.UesrServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RegistServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
String code = request.getParameter("code");
if("abc".equalsIgnoreCase(code)){
UesrServiceImpl uesrService = new UesrServiceImpl();
if(uesrService.existsUsername(username)){
System.out.println("用户名已存在");
response.sendRedirect("http://localhost:8080/book02/pages/user/regist.html");
}else {
User user = new User(username, password, email);
uesrService.registerUser(user);
response.sendRedirect("http://localhost:8080/book02/pages/user/regist_success.html");
}
}else {
System.out.println("验证码不正确");
response.sendRedirect("http://localhost:8080/book02/pages/user/regist.html");
}
}
}
2.4.2、登录servlet
登录成功或者登录失败的时候,跳转页面使用的是 响应的请求重定向
package com.atguigu.web;
import com.atguigu.bean.User;
import com.atguigu.service.impm.UesrServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
UesrServiceImpl uesrService = new UesrServiceImpl();
if(uesrService.login(new User(username,password,null)) != null){
response.sendRedirect("http://localhost:8080/book02/pages/user/login_success.html");
}else {
System.out.println("登录失败");
response.sendRedirect("http://localhost:8080/book02/pages/user/login.html");
}
}
}
2.5、html文件
登录页面的 html 文件中表单的提交链接
<form action="http://localhost:8080/book02/loginServlet" method="post">
注册页面的 html 文件中表单的提交链接
<form action="http://localhost:8080/book02/registServlet" method="post">
2.6、如果使用相对路径
- 添加 base 标签
<base href="http://localhost:8080/book/">
- 修改 base 标签对页面中所有相对路径的影响(浏览器 F12,哪个报红,改哪个)
以下是几个修改的示例:
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js">
</script>
- 修改 login.html 表单的提交地址和请求方式
|