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