本文主要是介绍尚硅谷书城项目总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
尚硅谷书城项目
跟着课程讲的思路来做项目,一步一步梳理的都很清晰,小黄记性不太好,决定边做边总结,本片文章持续更新
先附上尚硅谷的JavaWeb视频链接,对我帮助极大,有兴趣的小伙伴也可以跟着一起学习,一起进步
https://www.bilibili.com/video/BV1Y7411K7zz
第一阶段:表单验证
大部分网站都会有登录注册功能,而在这些用户可以进行操作的板块中,我们需要通过JS将用户填写的内容进行一个判断,在前端先检查,避免将无用的数据传到服务器对服务器造成负担
操作流程(我们拿注册来举例说明)
- 给注册按钮绑定单击事件
- 获取用户输入在输入框中的内容
- 按照规则进行判断(可能用到正则表达式)
- 输入不合法返回提示信息
先来看一下表单(为了全篇文章的可读性,我只会贴一小部分实例代码)
<%--span.errorMsg用于显示返回的错误信息--%>
<span class="errorMsg"></span>
<form><input type="hidden" name="function" value="regist"><label>用户名称:</label><input class="itxt" type="text" placeholder="请输入用户名"autocomplete="off" tabindex="1" name="username" id="username"/><br /><input type="submit" value="注册" id="sub_btn" />
</form>
我们的要求是用户名必须由字母、数字、下划线组成,并且长度在5-12之间,这个需求我们需要使用正则表达式
$(function () {// 给注册绑定单击事件$("#sub_btn").click(function () {// 验证用户名:必须由字母,数字下划线组成,并且长度为5到12位//1 获取用户名输入框里的内容var usernameText = $("#username").val();//2 创建正则表达式对象var usernamePatt = /^\w{5,12}$/;//3 使用test方法验证if (!usernamePatt.test(usernameText)) {//4 提示用户结果$("span.errorMsg").text("用户名不合法!");//返回false代表验证不通过时,不会跳转页面return false;}});
});
第二阶段:搭建书城项目环境
第二阶段我们开始着手搭建书城项目的环境,并且实现用户登录、注册的功能
先来看一下JavaEE的三层架构
一般我们的项目都会有以下几个包,先来介绍一下这些包的用处
- dao:dao层是专门用来与数据库打交道的,这里存放到dao接口包
- daoImpl:dao接口的实现类
- pojo:Javabean对象
- service:service接口包
- serviceImpl:service接口实现类
- servlet:servlet类
- test:测试类
- utils:工具类
实际开发中,我们应该从数据库一层一层的往外写
-
编写JdbcUtils类,用于连接数据库(采用德鲁伊数据库连接池)
public class JdbcUtils {private static DataSource dataSource = null;static{try {Properties prop = new Properties();InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");prop.load(is);dataSource = DruidDataSourceFactory.createDataSource(prop);} catch (Exception e) {e.printStackTrace();}}/*** 从数据库连接池中拿出一条链接* @return*/public static Connection getConnection(){Connection conn = null;try {conn = dataSource.getConnection();} catch (SQLException throwables) {throwables.printStackTrace();}return conn;}/*** 关闭一条连接* @param conn*/public static void close(Connection conn){if(conn != null){try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}} }
每一个小demo编写完成,都需要进行测试,测试代码放在test目录下,我就不贴出来了
-
编写BaseDao类,用于与数据库的交互,执行CRUD操作
public class BaseDAO {private QueryRunner queryRunner = new QueryRunner();/*** update():用于执行insert、update、delete语句* @param conn* @param sql 执行的sql语句* @param args 填充sql的占位符* @return 返回值为影响的行数,返回-1代表失败*/public int update(Connection conn,String sql,Object... args){int rows = -1;try {rows = queryRunner.update(conn, sql, args);} catch (SQLException throwables) {throwables.printStackTrace();}return rows;}/*** queryByOne():用于查询一行数据* @param type 返回值类型* @param conn* @param sql 执行的sql* @param args 填充占位符* @param <T> 返回值类型的泛型* @return*/public <T> T queryByOne(Class<T> type,Connection conn,String sql,Object... args){T t = null;try {t = queryRunner.query(conn, sql, new BeanHandler<>(type), args);} catch (SQLException throwables) {throwables.printStackTrace();}return t;}/*** queryByList():用于返回多条数据* @param type 返回值类型* @param conn* @param sql 执行的sql* @param args 填充占位符* @param <T> 返回值类型的泛型* @return*/public <T>List<T> queryByList(Class<T> type,Connection conn,String sql,Object... args){List<T> list = null;try {list = queryRunner.query(conn, sql, new BeanListHandler<>(type), args);} catch (SQLException throwables) {throwables.printStackTrace();}return list;}/*** queryForSingleValue():用于查询函数语句* @param conn* @param sql* @param args* @return*/public Object queryForSingleValue(Connection conn,String sql,Object... args){Object result = null;try {result = queryRunner.query(conn, sql, new ScalarHandler(), args);} catch (SQLException throwables) {throwables.printStackTrace();}return result;} }
-
编写UserDao接口
这里我们要结合业务来看,登录注册需要的操作有:
- 判断用户名是否重复(注册):根据用户名查询数据库中的数据
- 判断用户名密码是否存在(登录):根据用户名密码查询数据库中的数据
- 保存用户信息(注册):将用户输入的数据保存到数据库
public interface UserDAO {//根据用户名查询数据库中的数据User queryUserByUsername(String username);//根据用户名密码查询数据库中的数据User queryUserByUsernameAndPassword(String username,String password);//将用户输入的数据保存到数据库void saveUser(User user); }
-
编写UserDaoImpl类实现UserDao接口
public class UserDAOImpl extends BaseDAO implements UserDAO {@Overridepublic User queryUserByUsername(String username) {Connection conn = JdbcUtils.getConnection();String sql = "select id,username,password,email from t_user where username = ?";User user = queryByOne(User.class, conn, sql, username);JdbcUtils.close(conn);return user;}@Overridepublic User queryUserByUsernameAndPassword(String username, String password) {Connection conn = JdbcUtils.getConnection();String sql = "select id,username,password,email from t_user where username = ? and password = ?";User user = queryByOne(User.class, conn, sql, username,password);JdbcUtils.close(conn);return user;}@Overridepublic void saveUser(User user) {Connection conn = JdbcUtils.getConnection();String sql = "insert into t_user(username,password,email) values (?,?,?)";update(conn, sql, user.getUsername(), user.getPassword(), user.getEmail());} }
以上dao层的操作我们算是做完了,需要做一个小测试,接下来我们看一下service如何处理
-
编写UserService接口
service接口我们就需要更具体的去调用dao中的方法
public interface UserService {User login(String username,String password);void regist(User user);/*** 判断用户名是否存在* @param username* @return 返回true代表用户名存在,不可用,反之亦然*/boolean existUsername(String username); }
-
编写UserServiceImpl类实现UserService接口
public class UserServiceImpl implements UserService {UserDAO userDAO = new UserDAOImpl();@Overridepublic User login(String username, String password) {User user = userDAO.queryUserByUsernameAndPassword(username, password);return user;}@Overridepublic void regist(User user) {userDAO.saveUser(user);}@Overridepublic boolean existUsername(String username) {User user = userDAO.queryUserByUsername(username);if(user == null){return false;}return true;} }
以上完成之后,我们开始编写servlet程序,来实现需求
-
编写登录的servlet程序
public class UserLoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");UserService userService = new UserServiceImpl();if(userService.login(username, password) != null){//使用请求重定向,成功之后跳转页面req.getRequestDispatcher("pages/user/login_success.jsp").forward(req,resp);}else {//登录失败req.setAttribute("msg","用户名或密码错误");req.setAttribute("username",username);req.getRequestDispatcher("pages/user/login.jsp").forward(req,resp);}} }
-
编写注册的servlet程序
public class UserRegistServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");String email = req.getParameter("email");String code = req.getParameter("code");//判断用户名是否存在UserService userService = new UserServiceImpl();if(!userService.existUsername(username)){//用户名可用if("abcde".equals(code)){//验证码正确userService.regist(new User(null,username,password,email));req.getRequestDispatcher("pages/user/regist_success.jsp").forward(req,resp);}else {//回到注册页面req.setAttribute("msg","验证码错误");req.setAttribute("username",username);req.setAttribute("email",email);req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}}else {//回到注册页面req.setAttribute("msg","用户名已存在");req.setAttribute("username",username);req.setAttribute("email",email);req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}} }
第三阶段:对以上代码进行优化
一般来说,我们一个功能只会有一个servlet程序,比如书城项目,操作用户的是一个userServlet,操作书的是一个BookServlet,我们需要对以上的servlet进行优化,将他整合到一个servlet程序中
思路:运用input:hidden 隐藏表单,将客户端功能传输给服务器,在服务器判断应该执行哪条程序
-
编写UserServlet
public class UserServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {if("login".equals(req.getParameter("function"))){login(req,resp);}else if ("regist".equals(req.getParameter("function"){regist(req,resp);}}private void login(HttpServletRequest req,HttpServletResponse resp) throws Exception{String username = req.getParameter("username");String password = req.getParameter("password");UserService userService = new UserServiceImpl();if(userService.login(username, password) != null){req.getRequestDispatcher("pages/user/login_success.jsp").forward(req,resp);}else {//登录失败req.setAttribute("msg","用户名或密码错误");req.setAttribute("username",username);req.getRequestDispatcher("pages/user/login.jsp").forward(req,resp);}}private void regist(HttpServletRequest req,HttpServletResponse resp) throws Exception{String code = req.getParameter("code");User user = ServletUtils.getParamToBean(req.getParameterMap(),new User());//判断用户名是否存在UserService userService = new UserServiceImpl();if(!userService.existUsername(user.getUsername())){//用户名可用if("abcde".equals(code)){//验证码正确userService.regist(user);req.getRequestDispatcher("pages/user/regist_success.jsp").forward(req,resp);}else {//回到注册页面req.setAttribute("msg","验证码错误");req.setAttribute("username",user.getUsername());req.setAttribute("email",user.getEmail());req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}}else {//回到注册页面req.setAttribute("msg","用户名已存在");req.setAttribute("username",user.getUsername());req.setAttribute("email",user.getEmail());req.getRequestDispatcher("pages/user/regist.jsp").forward(req,resp);}} }
-
利用反射,去除繁琐的if else
在实际开发过程中,我们可能不只是登录、注册,可能还有修改信息等等功能,如果我们使用if else,会让代码看上去非常的冗余。我们发现从前端得到的字符串,与我们的方法名相同,这时候我们可以使用反射技术,动态的调用相对于的方法
public class UserServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String function = req.getParameter("function");//利用反射,动态调用操作用户的方法,避免大量的if elsetry {Method method = this.getClass().getDeclaredMethod(function,HttpServletRequest.class,HttpServletResponse.class);method.setAccessible(true);method.invoke(this,req,resp);} catch (Exception e) {e.printStackTrace();}}//重复的login和regist方法就 }
-
编写BaseServlet
除了操作用户,操作书籍等功能都需要使用到反射技术,所以我们这些代码提取出来,UserServlet只需继承BaseServlet即可
public abstract class BaseServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String function = req.getParameter("function");//利用反射,动态调用操作用户的方法,避免大量的if elsetry {Method method = this.getClass().getDeclaredMethod(function,HttpServletRequest.class,HttpServletResponse.class);method.setAccessible(true);method.invoke(this,req,resp);} catch (Exception e) {e.printStackTrace();}} }
这篇关于尚硅谷书城项目总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!