分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。
web层 com.achang.web/servlet/controller
service层 com.achang.service service接口包
com.achang.service.impl service接口实现类
dao持久层 com.achang.dao Dao接口包
com.achang.Dao.impl Dao接口实现类
实体bean对象 com.achang.pojo/entity/domain/bean JavaBean类
测试包 com.achang.test/junit
工具类 com.achang.utils
.
CREATE DATABASE book;
USE book;
CREATE TABLE t_user(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(20) NOT NULL UNIQUE,
`password` VARCHAR(32) NOT NULL,
`email` VARCHAR(200)
);
INSERT INTO t_user(`username`,`password`,`email`)VALUES('admin','admin','[email protected]');
SELECT * FROM t_user;
public class User {
private Integer id;
private String username;
private String password;
private String email;
//省略get()、set()、有参无参构造器、toString();
4.1 、导入需要的 jar 包(数据库和连接池需要)
druid-1.1.9.jar
mysql-connector-java-5.1.7-bin.jar以下是测试需要:
hamcrest-core-1.3.jar
junit-4.12.jar
4.2 、在 src 源码目录下编写 jdbc.properties 属性配置文件:
username=root
password=00000
url=jdbc:mysql://localhost:3306/book?useUnicode=true&characterEncoding=utf8
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
4.3 、编写 JdbcUtils 工具类(使用德鲁伊数据库池)
获取数据库连接池中的连接
//为了避免每次调用都创建一个数据库池,拉出来跟着类加载一同创建一次即可
private static DataSource source;
static{
try {
Properties pros = new Properties();
FileInputStream is = new FileInputStream(new File("D:\\JavaStudy\\JavaWeb\\book\\src\\main\\java\\jdbc.properties"));
pros.load(is);
source = DruidDataSourceFactory.createDataSource(pros);
System.out.println(source);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接池中的连接
public static Connection getConnection() throws SQLException {
Connection conn = source.getConnection();
return conn;
}
//关闭连接,放回数据库连接池
public static void closeConnection(Connection conn){
if (conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
4.4 、JdbcUtils 测试
public class JDBCUtilsTest {
@Test
public void testGetConnection() throws SQLException {
for (int i=0;i<100;i++){
Connection conn = JDBCUtils.getConnection();
System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@9f70c54
JDBCUtils.closeConnection(conn);
}
}
public class BaseDao {
//使用DBUtils操作数据库
//创建dbutils的QueryRunner实例对象
private QueryRunner runner = new QueryRunner();
//增删改语句
//返回-1,说明执行失败,返回其他值为影响的行数
public int update(String sql,Object...param){
Connection conn = JDBCUtils.getConnection();
try {
return runner.update(conn,sql,param);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.closeConnection(conn);
}
return -1;
}
//查询语句,返回一个对象
public <T>Object queryForOne(Class<T> type,String sql,Object...args){
Connection conn = JDBCUtils.getConnection();
try {
return runner.query(conn,sql,new BeanHandler<T>(type),args);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.closeConnection(conn);
}
return null;
}
//查询语句,返回多个对象
public <T> List<T> queryForList(Class<T> type, String sql, Object...args){
Connection conn = JDBCUtils.getConnection();
try {
return runner.query(conn,sql,new BeanListHandler<T>(type),args);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.closeConnection(conn);
}
return null;
}
//查询语句,返回单个一行一列的值
public Object queryForSingleVaule(String sql,Object...args){
Connection conn = JDBCUtils.getConnection();
try {
Object query = runner.query(conn,sql,new ScalarHandler(),args);
return query;
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBCUtils.closeConnection(conn);
}
return null;
}
}
UserDao 接口:
public interface UserDao {
//根据用户名查询用户信息
public Object queryUserByUsername(String username);
//保存用户信息到数据库
public int saveUser(User user);
//根据用户名和密码,查询数据库是否匹配
public User queryUserByUsernameAndPassword(String username,String password);
}
UserDaoImpl 实现类:
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 (User) queryForOne(User.class,sql,username);
}
@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());
}
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql = "select id,username,password,email from t_user where username = ? And password = ?";
return (User) queryForOne(User.class,sql,username,password);
}
}
UserDao 测试:
public class UserDaoTest {
UserDaoImpl userDao = new UserDaoImpl();
@Test
public void queryUserByUsername() {
if (userDao.queryUserByUsername("admin")==null){
System.out.println("用户名可用");
}else {
System.out.println("用户名已存在");
}
}
@Test
public void saveUser() {
System.out.println(userDao.saveUser(new User(1,"achang999","915456","[email protected]")));
}
@Test
public void queryUserByUsernameAndPassword() {
if (userDao.queryUserByUsernameAndPassword("admin","admin")==null){
System.out.println("用户名或密码错误,登入失败");
}else {
System.out.println("登入成功");
}
}
}
UserService接口:
public interface UserService {
//注册用户
public void registUser(User user);
/**
* 登录
* @param user
* @return 返回null登录失败,返回有值则登录成功
*/
public User login(User user);
/**
* 检查用户名是否可用
* @param username
* @return 返回true表示用户名已存在,返回false表示用户名可用
*/
public boolean existsUsername(String username);
}
UserServiceImpl 实现类:
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void registUser(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){
return false;//表示用户名可用
}else{
return true;//表示用户名已存在
}
}
}
UserService 测试:
public class UserServiceTest {
UserService userService = new UserServiceImpl();
@Test
public void registUser() {
userService.registUser(new User(0,"achang001","achang00000","[email protected]"));
userService.registUser(new User(0,"achang002","achang0000","[email protected]"));
}
@Test
public void login() {
System.out.println(userService.login(new User(4,"achang999","915456",null)));//User{id=4, username='achang999', password='915456', email='[email protected]'}
System.out.println(userService.login(new User(0,"asd","123",null)));//null
}
@Test
public void existsUsername() {
if (userService.existsUsername("achang02201")){
System.out.println("用户名已存在");
}else {
System.out.println("用户名可用");
}
}
}
8.1.1 图解用户注册的流程:
8.1.2 修改 regist.html 和 regist_success.html 页面:
<base href="http://localhost:8080/book/">
根据base标签更改地址信息
以下是几个修改的示例:
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js">script>
8.1.3 、编写 RegistServlet 程序
public class RegistServlet 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.检查验证码是否正确,先写死,要求,验证码为:abcde
if ("abcde".equalsIgnoreCase(code)){
//检查用户名是否可用
if (userService.existsUsername(username)){
System.out.println("用户名[ " + username + "] 已存在");
//跳转到注册页面
req.getRequestDispatcher("pages/user/regist.html").forward(req,resp);
}else {
//调用Service保存到数据库
userService.registUser(new User(0,username,password,email));
//跳转到注册成功页面
req.getRequestDispatcher("pages/user/regist_success.html").forward(req,resp);
}
}else {
//跳转到注册页面
System.out.println("验证码 ["+code+"] 错误");
req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
}
}
}
8.2.1 、Debug 点 调试代码,首先需要两个元素:断点 + Debug 启动服务器
8.2.2 、测试工具栏:
8.2.3 、变量窗口
变量窗口:它可以查看当前方法范围内所有有效的变量。
8.2.4 、方法调用栈窗口
1、方法调用栈可以查看当前线程有哪些方法调用信息
2、下面的调用上一行的方法
其他常用调试相关按钮:
8.3.1 、图解用户登录
8.3.2 、修改 login.html 页面和 login_success.html 页面
<base href="http://localhost:8080/book/">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js">script>
8.3.3 、LoginServlet 程序
public class LoginServlet extends HttpServlet {
private UserServiceImpl 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(0, username, password, null));
//3.根据login()方法返回结果判断登录是否成功
if (loginUser ==null){
//4.如果等于null,登入失败
System.out.println("登录失败,用户名不存在,或密码错误");
//5.转跳login登入页面
req.getRequestDispatcher("/pages/user/login.html").forward(req,resp);
}else {
System.out.println("登录成功");
//6.不为null,登入成功,跳转login_success页面
req.getRequestDispatcher("/pages/user/login_success.html").forward(req,resp);
}
}
}
2. 项目阶段二:用户注册和登陆的实现。
需求 1 :用户注册
需求如下:
1)访问注册页面
2)填写注册信息,提交给服务器
3)服务器应该保存用户
4)当用户已经存在----提示用户注册 失败,用户名已存在
5)当用户不存在-----注册成功
需求 2 :用户登陆
需求如下:
1)访问登陆页面
2)填写用户名密码后提交
3)服务器判断用户是否存在
4)如果登陆失败 --->>>> 返回用户名或者密码错误信息
5)如果登录成功 --->>>> 返回登陆成功 信息
感谢尚硅谷