– Three-tier architecture

  • MVC design pattern vs. three-tier architecture

    • In fact, the three-tier architecture doesn’t have much to do with MVC, just the same goal: decoupling and improving code reuse

    • MVC is a design pattern or a design idea, while three-tier architecture is a software architecture

  • What is three-tier architecture: Three-tier architecture is a kind of classical software architecture, and there are other architectures, such as four-tier architecture and so on

  • Why a three-tier architecture

    • Developers can focus on just one layer of the entire structure
    • It is easy to replace the existing level of implementation with a new one
    • Layer to layer dependencies can be reduced
    • Good for standardization
    • It facilitates the reuse of logic of each layer
    • High security. The client can only access the data layer through the logical layer, reducing entry points and shielding many dangerous system functions
    • The project structure is clearer and the division of labor clearer, which facilitates later maintenance and upgrade
  • What are the three tiers of architecture

    • Data access layer [data layer] / Persistence layer /DAL: Mainly CRUD operations on the database without writing any logical code

    • Business processing layer [business layer] /Service layer /BLL: Mainly deals with business logic and is responsible for data transfer and logical processing between the presentation layer and the data layer (persistence layer)

    • Presentation layer/interface layer /UI: The interface that presents or provides data, or the interface that the user sees, such as HTML, JSP, Swing, etc. Controller Controller and View both belong to the presentation layer. Data transfer in the interface depends on Controller, and the format of data transfer is model data

  • Data layer framework

    • Hibernate, SpringJdbc, Mybatis [iBatis], etc., encapsulate native JDBC code
  • Presentation layer framework

    • Struts2, SpringMvc, etc., encapsulate native Servlet code
  • Three-tier architecture specification

    • Presentation/Controller layer design

      • Without interface, all the classes under the controllers package, class called: XxxController/UserController
    • Business layer/Service layer design

      • You need an interface and implementation class, both of which are under the Service package

      • The interface name is IXxxService/IUserService

      • Implementation class as follows: in the service package created under impl package, implementation class under the impl package, XxxServiceImpl/UserServiceImpl

    • Persistence layer design, two ways

      • Persistence layer design method 1: DAO layer

        IXxxDao/IUserDao - Create impL package under service package, implement class under IMPl, XxxDaoImpl/UserDaoImplCopy the code
      • Persistent layer design method 2: Mapper layer, Mybatis official recommended use (recommended use)

        - All interfaces are in the mapper package and are named XxxMapper/UserMapperCopy the code

Note: Domain is not considered a layer of software architecture, our entity classes are uniformly placed in the domain, and each layer uses the entity classes in the domain

– integration of SSM

  • SSM integration is the integration of three frameworks: Spring + SpringMVC + Mybatis

  • Steps for integrating the SSM framework

1. Import JAR packages: 7 types of JAR packages are needed today

2. Import database table/create database table: Today take employee table as an example

3. Write a domain

package cn.itsource.domain;

import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;

import com.fasterxml.jackson.annotation.JsonFormat;

public class Emp {
	  
	  / / the primary key id
	  private Integer eid;
	  / / number
	  private String eno;
	  / / name
	  private String ename;
	  / / age
	  private Integer age;
	  / / gender
	  private char sex;
	  / / phone
	  private String tel;
	  / / address
	  private String address;
	  / / salary
	  private double sal;
	  
	  // Create time
	  @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	  private Date createdTime;
	  
	public Integer getEid(a) {
		return eid;
	}
	public void setEid(Integer eid) {
		this.eid = eid;
	}
	public String getEno(a) {
		return eno;
	}
	public void setEno(String eno) {
		this.eno = eno;
	}
	public String getEname(a) {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public Integer getAge(a) {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public char getSex(a) {
		return sex;
	}
	public void setSex(char sex) {
		this.sex = sex;
	}
	public String getTel(a) {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getAddress(a) {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public double getSal(a) {
		return sal;
	}
	public void setSal(double sal) {
		this.sal = sal;
	}
	
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
	public Date getCreatedTime(a) {
		return createdTime;
	}
	public void setCreatedTime(Date createdTime) {
		this.createdTime = createdTime;
	}
	@Override
	public String toString(a) {
		return "Emp [eid=" + eid + ", eno=" + eno + ", ename=" + ename + ", age=" + age + ", sex=" + sex + ", tel="
				+ tel + ", address=" + address + ", sal=" + sal + ", createdTime=" + createdTime + "]"; }}Copy the code

4. Write mapper interfaces

package cn.itsource.mapper;

import java.util.List;

import cn.itsource.domain.Emp;
import cn.itsource.query.EmpQuery;

public interface EmpMapper {
	
	// Query all
	List<Emp> findAllEmp(a);
	
	// Query by primary key ID
	Emp findById(Integer eid);
	
	// Based on the primary key ID
	void updateById(Integer eid);
	
	// Delete by primary key ID
	void deleteById(Integer eid);
	
	/ / new
	void addEmp(Emp emp);
	
	// Query by condition
	List<Emp> findByQuery(EmpQuery empQuery);

}

Copy the code

5. Write the mapper. XML


      
<! DOCTYPEmapper
  PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
  <mapper namespace="cn.itsource.mapper.EmpMapper">
  		
  		<select id="findAllEmp" resultType="Emp">
  			select * from emp
  		</select>
  		
  		<select id="findByQuery" resultType="Emp">
  			select * from emp
  			
  			<! -- will automatically concatenate a WHERE keyword for us, and help us remove unnecessary and keyword -->
  			<where>
  				<! -- The condition may be empty, so we need to use the if tag to help us determine -->
  				<if test="ename != null and ename != '' ">
  					and ename like CONCAT('%',#{ename},'%')
  				</if>
  				
  				<if test="address != null and address != '' ">
  					and address like CONCAT('%',#{address},'%')
  				</if>
  				
  				<if test="sal == 1 ">and <! [CDATA[sal < 3000]]></if>
  				
  				<if test="sal == 2 ">and <! [CDATA[sal >= 3000 and sal <= 5000]]></if>
  				
  				<if test="sal == 3 ">and <! [CDATA[sal > 5000 and sal <= 8000]]></if>
  				
  				<if test="sal == 4 ">and <! [CDATA[sal > 8000]]></if>
  			</where>
  			
  		</select>
  		
  		<delete id="deleteById">
  			delete from emp where eid = #{eid}
  		</delete>
  		
  </mapper>
Copy the code

6. Write the service

  • interface
package cn.itsource.service;

import java.util.List;

import cn.itsource.domain.Emp;
import cn.itsource.query.EmpQuery;

public interface IEmpService {
	
		// Query all
		List<Emp> findAllEmp(a);
		
		// Query by primary key ID
		Emp findById(Integer eid);
		
		// Based on the primary key ID
		void updateById(Integer eid);
		
		// Delete by primary key ID
		void deleteById(Integer eid);
		
		/ / new
		void addEmp(Emp emp);
		
		// Query by condition
		List<Emp> findByQuery(EmpQuery empQuery);	

}

Copy the code
  • The implementation class
package cn.itsource.service.impl;

import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.itsource.domain.Emp;
import cn.itsource.mapper.EmpMapper;
import cn.itsource.query.EmpQuery;
import cn.itsource.service.IEmpService;

@Service // Pass the current class to Spring to manage the object creation
public class EmpServiceImpl implements IEmpService{
	
	@Autowired
	private EmpMapper empMapper;

	// Query all
	@Override
	public List<Emp> findAllEmp(a) {
		return empMapper.findAllEmp();
	}

	// Query by ID
	@Override
	public Emp findById(Integer eid) {
		// TODO Auto-generated method stub
		return null;
	}

	// Change according to ID
	@Override
	public void updateById(Integer eid) {
		// TODO Auto-generated method stub
		
	}

	// Delete by ID
	@Override
	public void deleteById(Integer eid) {
		empMapper.deleteById(eid);
	}

	/ / new
	@Override
	public void addEmp(Emp emp) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public List<Emp> findByQuery(EmpQuery empQuery) {
		returnempMapper.findByQuery(empQuery); }}Copy the code

7. Write the Spring core configuration file applicationContext.xml

  • 1. Configure the connection pool object BasicDataSource

    • 1.1. The JDBC. Properties
  • 2. Configure the myBatis core object: SqlSessionFactoryBean

    • 1.1. Scan alias packets

    • 1.2. Scanning mapper XML

    • 1.3. Rely on database connection pools

  • 3. Scan the Service layer

  • 4. Scan mapper interfaces


      
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
>
	<! Jdbc.properties -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<! Configure the scan package, service layer -->
	<context:component-scan base-package="cn.itsource.service"/>

	<! -- Configure database connection pool object -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
	</bean>
	
	<! Configure mybatis core object -->
	<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<! DataSource -->
		<property name="dataSource" ref="dataSource"/>
		<! -- Scan public package -->
		<property name="typeAliasesPackage" value="cn.itsource.domain"/>
		<! Mapper.xml -->
		<property name="mapperLocations" value="classpath:cn/itsource/mapper/*Mapper.xml"/>
	</bean>
	
	<! MapperFactoryBean is designed to manage all of the mapper interfaces. Once you configure this, Spring knows that your Mapper interface needs it to help create implementation classes.
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="cn.itsource.mapper"></property>
	</bean>
	
</beans>
Copy the code
  • jdbc.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/ssm

jdbc.username=root

jdbc.password=root
Copy the code

7. Test

package cn.itsource.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.itsource.service.IEmpService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class EmpMapperTest {
	
	@Autowired
	private IEmpService iEmpService;
	
	@Test
	public void test(a) { iEmpService.findAllEmp().forEach(System.out::println); }}Copy the code

8. Add the log.properties core configuration file

# console output + custom layout log4j. RootLogger = DEBUG,. My # specified output device log4j appenders. My = org.. Apache log4j. ConsoleAppender # specify layout editor (custom layout) . # specify layout for custom layout log4j appenders. My. Layout = org.. Apache log4j. PatternLayout # specified in a custom layout format, % d, says the current system time, % t - threads execute the business name, %p -- the level of the diarist, -5 -- 5 for the number of output characters, and the symbol for right-aligned #%c -- for the fully qualified name (package name) of the class in which the business is specified. Class name), %m -- output additional information, % n - newline log4j. Appender. My. Layout. The ConversionPattern = [t] % % % d - 5 p [c] % % m % n # set package (can be customized bag) can also be the API output level log4j.logger.org.springframework=info log4j.logger.cn.itsource=debugCopy the code

9. Write the Controller layer

package cn.itsource.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.itsource.domain.Emp;
import cn.itsource.query.EmpQuery;
import cn.itsource.service.IEmpService;

@Controller
@RequestMapping("/emp")
public class EmpController {
	
	@Autowired
	private IEmpService iEmpService;
	
	
	/** * query all *@param model
	 * @return* /
	@RequestMapping("/findAllEmp")
	public String findAllEmp(Model model) {
	
		// Call the persistence layer method
		List<Emp> findAllEmp = iEmpService.findAllEmp();
		model.addAttribute("emps", findAllEmp);
		
		return "show";

	}
	
	/** * Query employee list by condition *@param model
	 * @param empQuery
	 * @return* /
	@RequestMapping("/findByQuery")
	public String findByQuery(Model model, EmpQuery empQuery) {
		// Call the service layer method
		List<Emp> findByQuery = iEmpService.findByQuery(empQuery);
		model.addAttribute("emps", findByQuery);
		model.addAttribute("query", empQuery);
		return "show";
	}
	
	/** * delete by ID and redirect to the findByQuery interface for the latest data *@param eid
	 * @return* /
	@RequestMapping("/deleteById")
	public String deleteById(Integer eid) {
		iEmpService.deleteById(eid);
		return "redirect:/emp/findByQuery"; }}Copy the code

10. Write the springMVC core configuration file applicationContext-vcv.xml

1. The package

2. Static resource release

3. Enable springMVC annotation support

4. Configure the view resolver

5. Configure an upload parser. (Configure the upload parser based on the service.)

6. Configure interceptors (based on services, if login is required)


      
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>

	<! -- Scan package, controller -->
	<context:component-scan base-package="cn.itsource.controller"/>
	
	<! Enable static resource release -->
	<mvc:default-servlet-handler/>
	
	<! -- Enable springMVC annotation support -->
	<mvc:annotation-driven/>
	
	<! -- Configure the view parser -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<! -- prefix -- -- >
		<property name="Prefix" value="/WEB-INF/views/"/>
		<! - the suffix - >
		<property name="Suffix" value=".jsp"></property>
	</bean>
	
</beans>
Copy the code

11. Write web. XML

1. Configure the springMVC core object

2. Resolve the problem of garbled characters in POST submissions

3. Start the Spring container


      

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="false">
  
  	<! Load the core configuration file of the specified path -->
  	<context-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:applicationContext.xml</param-value>
  	</context-param>

	<! -- Open the Spring container -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<! -- Configure springMVC core object -->
	<servlet>
		<servlet-name>dispatcherServlet</servlet-name>	
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:applicationContext-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<! -- Resolve post submission error -->
	<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<! -- Specify character encoding set -->
	<init-param>
	<param-name>encoding</param-name>
	<param-value>UTF-8</param-value>
	</init-param>
	<! -- Enforces a character encoding, even if request or Response has a character encoding, the current setting will be enforces, in any case enforces this encoding -->
	<init-param>
	<param-name>forceEncoding</param-name>
	<param-value>true</param-value>
	</init-param>
	</filter>
	<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
	<url-pattern>/ *</url-pattern>
	</filter-mapping>
</web-app>

Copy the code

12. Write the JSP

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"% > <! DOCTYPE html> <html> <head> <title>model</title> <style type="text/css">
	body{
		background-color: silver;
	}
	table{
		border-collapse: collapse; 
		width: 100%;
		text-align: center;
		margin: 20px auto;
		font-family: Microsoft Yahei;
	}
	td{
		border: 1px solid green;
		height: 30px;
	}
	caption {
		margin: 5px;
		font-size: 30px;
		font-weight: bold;
	}

</style>
</head>
<body>
	<form action="/emp/findByQuery"> <div> <h1> List of employees shows </h1> name: <input type="text" name="ename" value="${query.ename }"/> &emsp; Address: <input type="text" name="address" value="${query.address }"/> &emsp; Salary: <select name="sal" id="sal">
				<option value=""> Please select salary: </option> <option value="1" <c:if test="${query.sal == 1}">selected=selected</c:if>>3000The following </option> <option value="2" <c:if test="${query.sal == 2}">selected=selected</c:if> > [3000-5000)</option>
				<option value="3" <c:if test="${query.sal == 3}">selected=selected</c:if> > [5000-8000)</option>
				<option value="4" <c:if test="${query.sal == 4}">selected=selected</c:if>>8000</option> </select> <input type="submit" value="Search"/>
		</div>
		<script type="text/javascript">
			document.getElementById("deptno").value="${emp.deptno}";
			document.getElementById("sal").value="${emp.sal}"; < / script > < / form > < table > < thead > < tr > < td > ID < / td > < td > ID < / td > < td > name < / td > < / td > < td > age sex < / td > < td > < / td > < td > address Salary < / td > < td > < td > create time < / td > < td > action < / td > < / tr > < thead > < tbody id ="tbody">
			<c:forEach  items="${emps}" var="e"> <tr> <td>${e.eid}</td> <td>${e.eno}</td> <td>${e.ename}</td> <td>${e.age}</td> <td>${e.sex}</td> <td>${e.address}</td>  <td>${e.sal}</td> <td> <fmt:formatDate value="${e.createdTime}" pattern="yyyy-MM-dd HH:mm:ss"/>
					</td>
					<td>
						<a href="#"> Edit </a> <a href="/emp/deleteById? eid=${e.eid}"> delete < / a > < / td > < / tr > < / c: forEach > < / tbody > < / table > < / body > < / HTML >Copy the code

13. Start Tomcat, visit the page, and test the function

  • Project directory

The SSM three framework integration is complete