【Javaweb】JavaEE项目的三层架构 | 快速搭建
逻辑类图
分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。
不同的层有不同的包
web层 com.stguigu.web/servlet/controller
service层 com.atguigu.service Service接口包
com.atguigu.service.impl Service接口实现类
dao持久层 com.atguigu.dao Dao接口包
实体Bean对象 com.atguigu.poio/entity/domain/bean JavaBean类
测试包 com.atguigu.test/junit
工具类 com.atguigu.utils
编码环节
1、先创建项目所需要的数据库和表
DROP DATABASE IF exists javaweb05;
CREATE DATABASE javaweb05;
use javaweb05;
create table t_user(
`id` int primary key auto_increment,
`username` varchar(20) NOT NULL UNIQUE,
`password` varchar(32) not null,
`email` varchar(200)
);
2、编写数据库表对应的JavaBean对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class User { private Integer id; private String username; private String password; private String 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; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + 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; } }
3、编写工具类JdbcUtils
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private static DruidDataSource dataSource; static { try { Properties properties=new Properties(); // 读取jdbc.properties属性配置文件 InputStream inputStream=JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"); // 从源中加载数据 properties.load(inputStream); // 创建 数据库连接 池 dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties); System.out.println(dataSource.getConnection()); } catch (Exception e) { throw new RuntimeException(e); } } public static Connection getConnection(){ Connection connection=null; try { connection=dataSource.getConnection(); }catch (Exception e){ e.printStackTrace(); } return connection; } public static void close(Connection connection){ if(connection!=null){ try { connection.close(); }catch (SQLException e){ e.printStackTrace(); } } }
4、编写BaseDao
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public abstract class BaseDao { // 使用DbUtils操作数据库 private QueryRunner queryRunner=new QueryRunner(); /** * update()方法用来执行,Insert\Update\Delete语句 * @return 如果返回-1,说明执行失败<br>返回其他表示影响的行数 * @author yan * @create 2023/1/30 **/ public int update(String sql,Object ... args){ Connection connection= JdbcUtils.getConnection(); try { return queryRunner.update(connection,sql,args); }catch (SQLException e){ e.printStackTrace(); }finally { JdbcUtils.close(connection); } return -1; } /* * 查询返回一个JavaBean的sql语句 * * @param type 返回的对象类型 * @param sql 执行的sql语句 * @param args sql对应的参数值 * @param <T> 返回的类型的泛型 * @return * @author yan * @create 2023/1/30 **/ public <T>T queryForOne(Class<T>type,String sql,Object ... args){ Connection connection=JdbcUtils.getConnection(); try { queryRunner.query(connection, sql, new BeanHandler<T>(type), args); }catch (SQLException e){ e.printStackTrace(); }finally { JdbcUtils.close(connection); } return null; } /* * 查询返回多个JavaBean的sql语句 * * @param type 返回的对象类型 * @param sql 执行的sql语句 * @param args sql对应的参数值 * @param <T> 返回的类型的泛型 * @return * @author yan * @create 2023/1/30 **/ public <T>List<T> queryForList(Class<T>type,String sql,Object ... args){ Connection connection=JdbcUtils.getConnection(); try { queryRunner.query(connection, sql, new BeanHandler<T>(type), args); }catch (SQLException e){ e.printStackTrace(); }finally { JdbcUtils.close(connection); } return null; } /* * 查询返回多个JavaBean的sql语句 * * @param type 返回的对象类型 * @param sql 执行的sql语句 * @param args sql对应的参数值 * @return * @author yan * @create 2023/1/30 **/ public Object queryForSingleValue(String sql,Object ... args){ Connection connection=JdbcUtils.getConnection(); try { return queryRunner.query(connection, sql, new ScalarHandler<>(), args); }catch (SQLException e){ e.printStackTrace(); }finally { JdbcUtils.close(connection); } return null; } }
5、编写UserDao测试
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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、编写UserService和测试
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private UserDao userDao=new UserDaoImpl(); @Override public void register(User user) { userDao.saveUser(user); } @Override public User login(User user) { return userDao.queryUserByUsernameAndPassword(user.getUsername(),user.getPassword()); } @Override public boolean existsUsername(String username) { if(userDao.queryUserByUsername(username)==null){ // 等于null,说明没查到,没查到表示可用 return false; } return true; }
7、编写web层
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class RegisterServlet extends HttpServlet { private UserService userService = new UserServiceImpl(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、获取请求的参数 String username = req.getParameter("username"); String password = req.getParameter("password"); String email = req.getParameter("email"); String code = req.getParameter("code"); //2、检查验证码是否正确 ---- 正确===写死,要求验证码为123 if ("123".equalsIgnoreCase(code)) { //3、检查用户名是否可用 ----可用 if (userService.existsUsername(username)) { // 不可用 System.out.println("用户名[" + username + "]已存在!"); // 跳回注册页面 req.getRequestDispatcher("/register/register.html").forward(req, resp); } else { // 可用 //4、调用Service保存到数据库 userService.register(new User(null, username, password, email)); //5、跳到注册成功页面 register_success.html req.getRequestDispatcher("/register/registersuccess.html").forward(req, resp); } //6、否则跳回注册页面 } else { System.out.println("验证码[" + code + "]错误"); req.getRequestDispatcher("/register/register.html").forward(req, resp); } } }
7.2IDEA中Debug调试的使用
Debug调试代码,首先需要两个元素:断点+Debug启动器
1、断点,只需要在代码需要停的行的左边上单击,就可以添加和取消
2、Debug启动Tomcat运行代码
调试工具栏:
让代码往下执行一行
可以进入当前方法体内(自己写的代码,非框架源码)
强制进入当前方法体内
跳出当前方法体外
停在光标所在行,相当于是个临时断点
变量窗口
可以查看当前方法范围内所有有效的变量
方法调用栈窗口
1、可以查看当前线程有哪些方法的调用信息
2、下面的调用上面的方法
其他常用调试相关按钮
7.3用户登录功能的实现
利用断点进行测试
信息错误时
信息正确时
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class LoginServlet extends HttpServlet { private UserService userService=new UserServiceImpl(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、获取请求的参数 String username= req.getParameter("username"); String password= req.getParameter("password"); //2、调用userService.login()登录处理业务 User loginUser= userService.login(new User(null,username,password,null)); //3、根据login()方法返回结果判断登录是否成功 // 如果等于null,说明登录 失败! if(loginUser==null){ // 跳回登陆页面 req.getRequestDispatcher("/register/login.html").forward(req,resp); }else { // 登陆成功 // 跳到成功页面login_success.html req.getRequestDispatcher("/register/login_success.html").forward(req,resp); } } }