book书城项目(注册功能):JavaEE项目的三层架构

分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。

web 层

com.ydgk.web/servlet/controller

service 层

com.ydgk.service

Service 接口包

com.ydgk.service.impl

Service 接口实现类

dao 持久层

com.ydgk.dao

Dao 接口包

com.ydgk.dao.impl

Dao 接口实现类

实体bean 对象

com.ydgk.pojo/entity/domain/bean

JavaBean 类

测试包

com.ydgk.test/junit

工具类

com.ydgk.utils

搭建书城项目开发环境:

创建我们项目的包结构:

1、创建书城需要的数据库和表

2、编写数据库表对应的JavaBean对象

package com.bigdata.bean;

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;
    }

    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 + '\'' +
                '}';
    }
}

3、编写工具类JdbcUtils

3.1 、导入需要的jar 包(数据库和连接池需要):

druid-1.1.9.jar

mysql-connector-java-5.1.7-bin.jar

以下是测试需要:

hamcrest-core-1.3.jar

junit-4.12.jar

3.2 在src 源码目录下编写jdbc.properties 属性配置文件:

username=root
password=021211
url=jdbc:mysql://localhost:3306/book?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
driverClassName=com.mysql.jdbc.Driver

initialSize=5
maxActive=10

3.3、编写JdbcUtils 工具类:

设置一个数据源的工具类,此类用于得到数据源(DruidDataSource)和数据库连接对象(Connection)

package com.bigdata.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;

    static {
        try {
            Properties properties = new Properties();
            // 读取 jdbc.properties 属性配置文件
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            // 从流中加载数据
            properties.load(inputStream);
            // 创建 数据库连接池
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //额外加一个获取数据源方法
    public static DruidDataSource getDataSource(){
        return dataSource;
    }

    /**
     *获取数据库连接池中的连接
     *@return 如果返回null,说明获取连接失败<br/>有值就是获取连接成功
     */
    public static Connection getConnection(){

        Connection conn = null;

        try {
            conn = dataSource.getConnection();
        } catch (Exception e) { e.printStackTrace();
        }

        return conn;
    }

    /**
     *关闭连接,放回数据库连接池
     *@param conn
     */
    public static void close(Connection conn){
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) { e.printStackTrace();
            }
        }
    }
}

3.4JbUtil测试类

主要为了测试本项目与数据库是否正确连接

package com.bigdata.test;

import com.bigdata.utils.JdbcUtils;
import org.junit.Test;
import java.sql.Connection;
public class JdbcUtilsTest {

@Test
public void testJdbcUtils(){
for (int i = 0; i < 100; i++){
    Connection connection = JdbcUtils.getConnection();
    System.out.println(connection);
    JdbcUtils.close(connection);
}
}

}

结果为

4、编写BaseDao

封装一些数据库操作需要的数据源,连接驱动等方法

package com.bigdata.utils;

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.math.BigInteger;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * 定义一个用来被继承的对数据库进行基本操作的Dao
 * @param <T> 泛型 -> bean类型
 */
public abstract class BaseDao<T>{
    private QueryRunner queryRunner ;
    // 定义一个变量来接收泛型的类型
    private Class<T> type;

    // 获取T的Class对象,获取泛型的类型,泛型是在被子类继承时才确定
    public BaseDao() {
        queryRunner = new QueryRunner(JdbcUtils.getDataSource());
        // 获取子类的类型
        Class clazz = this.getClass();
        // 获取父类的类型
        // getGenericSuperclass()用来获取当前类的父类的类型
        // ParameterizedType表示的是带泛型的类型
        ParameterizedType parameterizedType =
                (ParameterizedType) clazz.getGenericSuperclass();
        // 获取具体的泛型类型 getActualTypeArguments获取具体的泛型的类型
        // 这个方法会返回一个Type的数组
        Type[] types = parameterizedType.getActualTypeArguments();
        // 获取具体的泛型的类型·
        this.type = (Class<T>) types[0];
    }


    /**
     * 获取所有对象
     *
     * @param sql
     * @param params
     * @return
     */
    public List<T> getBeanList(Connection conn, String sql, Object... params) {
        List<T> list = null;
        try {
            list = queryRunner.query(conn, sql, new BeanListHandler<T>(type), params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 获取一个对象
     *
     * @param sql
     * @param params
     * @return
     */
    public T getBean(Connection conn,String sql, Object... params) {
        T t = null;
        try {                                              //type == String.class
            t = queryRunner.query(conn, sql, new BeanHandler<T>(type), params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 通用的增删改操作(事务有关)
     *
     * @param sql
     * @param params
     * @return
     */
    public int update(Connection conn, String sql, Object... params) {
        int count = 0;
        try {
            count = queryRunner.update(conn, sql, params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 通用的增删改操作(没有办法使用事务)
     *
     * @param sql
     * @param params
     * @return
     */
    public int update(String sql, Object... params) {
        int count = 0;
        try {
            count = queryRunner.update(sql, params);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 添加数据后返回主键id(事务有关)
     * @param sql
     * @param params
     * @return
     */
    public int insert(Connection conn ,String sql, Object... params){
        try {
            return queryRunner.insert(conn,sql , new ScalarHandler<BigInteger>() , params).intValue();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 添加数据后返回主键id(没有办法使用事务)
     * @param sql
     * @param params
     * @return
     */
    public int insert(String sql, Object... params){
        try {
            return queryRunner.insert(sql , new ScalarHandler<Long>() , params).intValue();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取单行单列值得方法,专门用来执行像 select count(*)...这样的sql语句
     *
     * @param sql
     * @param params
     * @return
     */
    public int getValue(Connection conn,String sql, Object... params) {
        int count = 0;
        try {
            // 调用queryRunner的query方法获取一个单一的值
            count = queryRunner.query(conn, sql, new ScalarHandler<Long>(), params).intValue();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

}

5、编写UserDao 和测试

UserDao接口:

package com.bigdata.dao;

import com.bigdata.bean.User;

public interface UserDao {

/**
*根据用户名查询用户信息
*@param username 用户名
*@return 如果返回null,说明没有这个用户。反之亦然
*/
public User queryUserByUsername(String username);

/**
*根据 用户名和密码查询用户信息
*@param username
*@param password
*@return 如果返回null,说明用户名或密码错误,反之亦然
*/
public User queryUserByUsernameAndPassword(String username,String password);

/**
*保存用户信息
*@param user
*@return 返回-1 表示操作失败,其他是sql 语句影响的行数
*/
public int saveUser(User user);

}

UserDaoImpl实现类:

该类实现对数据库的一些操作(增删改查)

package com.bigdata.dao.impl;

import com.bigdata.bean.User;
import com.bigdata.dao.UserDao;
import com.bigdata.utils.BaseDao;

public class UserDaoImpl extends BaseDao<User> implements UserDao {

    @Override
    public User queryUserByUsername(String username) {
        return getBean("select * from t_user where username = ?",username);
    }

    @Override
    public User queryUserByUsernameAndPassword(String username, String password) {
        return getBean("select * from t_user where username = ? and password = ?",username,password);
    }

    @Override
    public int saveUser(User user) {
        return insert("insert into t_user values(null,?,?,?)",
                user.getUsername(),user.getPassword(),user.getEmail());
    }
}

测试UserDao中的方法是否可以正常运行

6、编写UserService接口 与 UserServiceImpl实现类

UserService接口定义三个方法,分别是注册、登录、判断用户是否存在。

package com.bigdata.service;

import com.bigdata.bean.User;

public interface UserService {
/**
*注册用户
*@param user
*/
    public void registUser(User user);

    /**
     *登录
     *@param user
     *@return 如果返回null,说明登录失败,返回有值,是登录成功
     */
    public User login(User user);

    /**
     *检查 用户名是否可用
     *@param username
     *@return 返回true 表示用户名已存在,返回false 表示用户名可用
     */
    public boolean existsUsername(String username);
}

该类实现接口,首先实例化UserDaoImpl,方法中调用UserDaoImpl类中的一些方法,也就是对数据库进行操作的方法。

package com.bigdata.service.impl;

import com.bigdata.bean.User;
import com.bigdata.dao.UserDao;
import com.bigdata.dao.impl.UserDaoImpl;
import com.bigdata.service.UserService;

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) {
        return userDao.queryUserByUsername(username) != null;
    }
}

service层

service层就是业务层,在我们开发项目中,有很多复杂的业务功能,并不是单纯的crud,所以我们会创建一个业务层实现项目中复杂的业务功能,并且在此层中完成事务的操作。事务:要么成功都成功,要么失败都失败

dao层就是用来完成对数据库的crud,但是一个项目并不是只有crud所以我们需要业务层来完成复杂的功能。

比如:

转账

购物车

下订单

...

就不是我们在dao层使用crud能完成的

具体的业务层使用我们后期会在项目中来体现

7、编写web层

首先实现的是注册功能

1、添加base标签

<base href="http://localhost:8080/book/">

web前端页面的注册登录中一定会有提交表单

表单提交中的action就得是Servlet包下的类名,因为我们需要servlet技术将客户端的数据回显到后端,利用HttpServletRequest类中的getParameter()方法获取参数。得到用户名密码邮箱等,判断该用户名是否在数据库中存在,如果不存在就执行添加语句。添加成功使用

getRequestDispatcher()方法 获取请求转发对象,跳转到注册成功页面。

在Servlet包下面创建RegistServlet类,该类处理客户端发来的请求(也就是注册的信息)。

首先记得加上注解,并且该类要继承HttpServlet类。详情见前面发布的文章Servlet技术篇。

对HttpServlet类中的service方法进行重写。

package com.bigdata.servlet;

import com.bigdata.bean.User;
import com.bigdata.service.UserService;
import com.bigdata.service.impl.UserServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/RegistServlet")
public class RegistServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到我们提交上来的用户名,邮箱,密码等。
        //1、post会有乱码问题,先解决一下乱码
        req.setCharacterEncoding("utf-8");
        //2、获取表单提交上来的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
        String code = req.getParameter("code");

        //创建一个用户业务层对象 userService
        UserService userService = new UserServiceImpl();

        //3、判断一下验证是不是正确的
        if("1234".equals(code)){
            //返回true,表示用户已存在,返回false
            if (userService.existsUsername(username)){
                req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);
            }else {
                User user = new User();
                user.setUsername(username);
                user.setPassword(password);
                user.setEmail(email);
                //因为eregistUser方法需要传入的参数是一个user对象,所以我们创建一个user对象并将表单提交上来的参数都保存到User对象中
                //这里调用userServiceImpl中的registUser方法,即注册方法,然后该类中的此方法是调用了UserDao类中的saveUser方法,sql语句添加到数据库中
                userService.registUser(user);
                //如果注册成功,就跳转到成功网页
                req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
            }
        }else{
            //通过服务器转发的方式跳回到regist.html网页,因为验证不正确
            req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);

        }
    }
}

本book商城项目还未涉及到验证码功能。只是简单的三层架构,帮助大家更好的理解JavaEE项目。且重点在于后端,web代码不完全。可以简单点,html代码中只要有form表单提交,action不要写错验证数据库是否正确添加就行。

至此,完整的项目结构如下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值