book bookstore project (registration function): three-tier architecture of JavaEE project

The purpose of layering is to decouple. Decoupling is to reduce the coupling of the code. Convenient for later maintenance and upgrades of the project.

web layer

com.ydgk.web/servlet/controller

service layer

com.ydgk.service

Service interface package

com.ydgk.service.impl

Service interface implementation class

dao persistence layer

com.ydgk.dao

Dao interface package

com.ydgk.dao.impl

Dao interface implementation class

Entity bean object

com.ydgk.pojo/entity/domain/bean

JavaBean class

test package

com.ydgk.test/junit

Tools

com.ydgk.utils

Build a bookstore project development environment:

Create the package structure of our project:

1. Create the database and tables required for the bookstore

2. Write the JavaBean object corresponding to the database table

package com.bigdata.bean;

public class User {
    privateInteger 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. Writing tool class JdbcUtils

3.1 , import the required jar Package (required for database and connection pool):

druid-1.1.9.jar

mysql-connector-java-5.1.7-bin.jar

The following are required for testing:

hamcrest-core-1.3.jar

junit-4.12.jar

3.2 Write the jdbc.properties property configuration file in the src source code directory:

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. Write JdbcUtils tool class:

Set up a data source tool class, which is used to get the data source (DruidDataSource) and database connection object (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();
            //Read jdbc.properties property configuration file
            InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //Load data from stream
            properties.load(inputStream);
            //Create database connection pool
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //Add an additional method to obtain the data source
    public static DruidDataSource getDataSource(){
        return dataSource;
    }

    /**
     *Get the connection in the database connection pool
     *@return If null is returned, it means that the connection failed to be obtained<br/>If there is a value, the connection is obtained successfully.
     */
    public static Connection getConnection(){

        Connection conn = null;

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

        return conn;
    }

    /**
     *Close the connection and put it back into the database connection pool
     *@param conn
     */
    public static void close(Connection conn){
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) { e.printStackTrace();
            }
        }
    }
}

3.4JbUtil test class

Mainly to test whether this project is correctly connected to the database

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

}

The result is

,

4. Write BaseDao

Encapsulate some data sources required for database operations, connection drivers, etc.

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;

/**
 * Define a Dao that is inherited to perform basic operations on the database
 * @param <T> Generic -> bean type
 */
public abstract class BaseDao<T>{
    private QueryRunner queryRunner;
    //Define a variable to receive the generic type
    private Class<T> type;

    // Get the Class object of T and get the type of the generic. The generic is determined when it is inherited by a subclass.
    public BaseDao() {
        queryRunner = new QueryRunner(JdbcUtils.getDataSource());
        // Get the type of subclass
        Class clazz = this.getClass();
        // Get the type of parent class
        // getGenericSuperclass() is used to get the type of the parent class of the current class
        // ParameterizedType represents a type with generics
        ParameterizedType parameterizedType =
                (ParameterizedType) clazz.getGenericSuperclass();
        // Get the specific generic type getActualTypeArguments Get the specific generic type
        // This method will return an array of Type
        Type[] types = parameterizedType.getActualTypeArguments();
        // Get the specific generic type·
        this.type = (Class<T>) types[0];
    }


    /**
     * Get all objects
     *
     * @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;
    }

    /**
     * Get an object
     *
     * @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;
    }

    /**
     * General addition, deletion and modification operations (transaction related)
     *
     * @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;
    }

    /**
     * General addition, deletion and modification operations (there is no way to use transactions)
     *
     * @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;
    }

    /**
     * Return the primary key id after adding data (transaction related)
     * @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;
    }

    /**
     * Return the primary key id after adding data (there is no way to use transactions)
     * @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;
    }

    /**
     * Get the value of a single row and column, specifically used to execute SQL statements like select count(*)...
     *
     * @param sql
     * @param params
     * @return
     */
    public int getValue(Connection conn,String sql, Object... params) {
        int count = 0;
        try {
            // Call the query method of queryRunner to get a single value
            count = queryRunner.query(conn, sql, new ScalarHandler<Long>(), params).intValue();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

}

5. Write UserDao and test

UserDao interface:

package com.bigdata.dao;

import com.bigdata.bean.User;

public interface UserDao {

/**
*Query user information based on user name
*@param username username
*@return If null is returned, it means there is no such user. vice versa
*/
public User queryUserByUsername(String username);

/**
*Query user information based on username and password
*@param username
*@param password
*@return If null is returned, the username or password is incorrect, and vice versa
*/
public User queryUserByUsernameAndPassword(String username,String password);

/**
*Save user information
*@param user
*@return Return -1 indicates that the operation failed, and the others are the number of rows affected by the sql statement
*/
public int saveUser(User user);

}

UserDaoImpl implementation class:

This class implements some operations on the database (add, delete, modify, check)

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

Test whether the methods in UserDao can run normally

6. Write the UserService interface and UserServiceImpl implementation class

The UserService interface defines three methods, namely registration, login, and determining whether the user exists.

package com.bigdata.service;

import com.bigdata.bean.User;

public interface UserService {
/**
*registered user
*@param user
*/
    public void registerUser(User user);

    /**
     *Log in
     *@param user
     *@return If null is returned, the login failed, if a value is returned, the login is successful.
     */
    public User login(User user);

    /**
     *Check if username is available
     *@param username
     *@return Returns true to indicate that the username already exists, returns false to indicate that the username is available
     */
    public boolean existsUsername(String username);
}

This class implements the interface, first instantiates UserDaoImpl, and calls some methods in the UserDaoImpl class, which are methods for operating the database.

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 registerUser(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 layer

The service layer is the business layer. In our development project, there are many complex business functions, not just CRUD, so we will create a business layer to implement the complex business functions in the project, and complete transaction operations in this layer. Transaction: Either everything succeeds, or everything fails.

The dao layer is used to complete CRUD on the database, but a project is not only CRUD, so we need the business layer to complete complex functions.

for example:

transfer

shopping cart

place an order

It’s not something we can accomplish using crud at the dao layer.

The specific use of the business layer will be reflected in the project later.

7. Write web layer

The first thing to implement is the registration function

1. Add base tag

<base href=”http://localhost:8080/book/”

There must be a submission form in the registration login on the web front-end page

The action in the form submission must be the class name under the Servlet package, because we need servlet technology to echo the client’s data to the backend, and use the getParameter() method in the HttpServletRequest class to obtain the parameters. Get the username, password, email address, etc. to determine whether the username exists in the database. If it does not exist, execute the add statement. Added successfully

The getRequestDispatcher() method obtains the request forwarding object and jumps to the registration success page.

Create the RegisterServlet class under the Servlet package, which handles requests from the client (that is, registered information).

First remember to add annotations, and the class must inherit the HttpServlet class. For details, see the previously published article Servlet Technology.

Rewrite the service method in the HttpServlet class.

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 {
        //Get the username, email, password, etc. we submitted.
        //1. The post will have garbled characters. Please solve the garbled characters first.
        req.setCharacterEncoding("utf-8");
        //2. Get the parameters submitted by the form
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
        String code = req.getParameter("code");

        //Create a user business layer object userService
        UserService userService = new UserServiceImpl();

        //3. Determine whether the verification is correct.
        if("1234".equals(code)){
            //Return true, indicating that the user already exists, return 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);
                //Because the eregistUser method needs to pass in a user object as a parameter, we create a user object and save all the parameters submitted by the form into the User object.
                //The registerUser method in userServiceImpl is called here, that is, the registration method. Then this method in this class calls the saveUser method in the UserDao class, and the sql statement is added to the database.
                userService.registUser(user);
                //If the registration is successful, jump to the success page
                req.getRequestDispatcher("/pages/user/regist_success.html").forward(req,resp);
            }
        }else{
            //Jump back to the register.html web page through server forwarding because the verification is incorrect.
            req.getRequestDispatcher("/pages/user/regist.html").forward(req,resp);

        }
    }
}

This book mall project has not yet involved the verification code function. It’s just a simple three-tier architecture to help everyone better understand JavaEE projects. And the focus is on the backend, the web code is incomplete. It can be simpler. As long as there is a form submission in the html code, do not write the wrong action and verify whether the database is added correctly.

At this point, the complete project structure is as follows