當(dāng)前位置:首頁(yè) > 學(xué)習(xí)資源 > 講師博文 > 三層架構(gòu)實(shí)現(xiàn)Java Web案例
三層架構(gòu)一方面是為了解決應(yīng)用程序中代碼之間調(diào)用復(fù)雜,代碼職責(zé)不清的問(wèn)題;通過(guò)各層之間定義接口的形式,并將接口與實(shí)現(xiàn)分離,可以很容易的用不同的實(shí)現(xiàn)來(lái)替換原有的實(shí)現(xiàn),從而有效的降低層與層之間的依賴關(guān)系。這種方式不僅有利于整個(gè)團(tuán)隊(duì)理解整個(gè)應(yīng)用架構(gòu),降低后期維護(hù)成本,同時(shí)也有利于制定整個(gè)應(yīng)用程序架構(gòu)的標(biāo)準(zhǔn)。
另一方面三層架構(gòu)的出現(xiàn)從某種程度上解決了企業(yè)內(nèi)部如果有效的根據(jù)技能調(diào)配技術(shù)人員,提高生產(chǎn)效率的問(wèn)題,在大環(huán)境下,有效的分層能使不同職責(zé)的人各司其職,聚焦于個(gè)人專業(yè)技能的發(fā)展與培養(yǎng)上。
三層架構(gòu)的出現(xiàn)不僅標(biāo)準(zhǔn)化了復(fù)雜系統(tǒng)的邏輯劃分,更幫助企業(yè)解決如果有效的形成技術(shù)人員組織機(jī)構(gòu)的問(wèn)題,因此在很長(zhǎng)的一段時(shí)間內(nèi),它一直是軟件架構(gòu)設(shè)計(jì)的經(jīng)典模式之一。
優(yōu)勢(shì)
層次清晰,每個(gè)層次都提供了接口定義
很容易用新的實(shí)現(xiàn)替換原來(lái)的層次實(shí)現(xiàn)。例如對(duì)sql進(jìn)行性能優(yōu)化,并不會(huì)影響其他層的代碼結(jié)構(gòu)。有利于后期維護(hù)。
有利于實(shí)現(xiàn)切面編程,減輕業(yè)務(wù)的復(fù)雜程度,加快編碼效率。
每個(gè)層次的定位明晰,業(yè)務(wù)處理的內(nèi)容明確。依據(jù)層次,可以劃分不同的分工。開發(fā)人員可以只關(guān)注整個(gè)結(jié)構(gòu)的其中某一層。
接口定義也提供了良好的可擴(kuò)展性。例如數(shù)據(jù)庫(kù)從mysql切換到oracle,只需要通過(guò)配置來(lái)切換。
降低了代碼之間,層與層的依賴關(guān)系
復(fù)用性:利于各層代碼邏輯的復(fù)用
安全性:接口設(shè)計(jì)需要符合對(duì)擴(kuò)展開發(fā),對(duì)修改關(guān)閉的原則,增強(qiáng)了系統(tǒng)的安全性
各層次職責(zé)
表示層:是應(yīng)用的用戶接口部分,擔(dān)負(fù)著用戶與應(yīng)用的對(duì)話,交互功能。
業(yè)務(wù)邏輯層:主要是業(yè)務(wù)邏輯的處理,操作,是系統(tǒng)功能核心。
數(shù)據(jù)訪問(wèn)層:也稱為是數(shù)據(jù)持久層,其功能主要是負(fù)責(zé)數(shù)據(jù)庫(kù)的訪問(wèn)。
遵循的規(guī)格
1. 系統(tǒng)按照三層架構(gòu)劃分:表示層,業(yè)務(wù)層,數(shù)據(jù)訪問(wèn)層。
2. 系統(tǒng)各層次之間接口通信,不能訪問(wèn)實(shí)現(xiàn)類對(duì)象。
3.系統(tǒng)各層次之間單向依賴,不能反向,不能跨層次訪問(wèn),
案例實(shí)現(xiàn)
1.pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hq</groupId>
<artifactId>ssm_base</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- 數(shù)據(jù)庫(kù)驅(qū)動(dòng) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.14.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.14.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<finalName>ssm_base</finalName>
</build>
</project>
2.spring.xml
<?xml version="1.0" encoding="UTF-8"?> <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:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <context:property-placeholder location="classpath:config.properties" /> <!-- 配置DataSource數(shù)據(jù)源 --> <!-- 阿里 druid 數(shù)據(jù)庫(kù)連接池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <!-- 數(shù)據(jù)庫(kù)基本信息配置 --> <property name="url" value="${druid.url}" /> <property name="username" value="${druid.username}" /> <property name="password" value="${druid.password}" /> <property name="driverClassName" value="${druid.driverClassName}" /> <property name="filters" value="${druid.filters}" /> <!-- 最大并發(fā)連接數(shù) --> <property name="maxActive" value="${druid.maxActive}" /> <!-- 初始化連接數(shù)量 --> <property name="initialSize" value="${druid.initialSize}" /> <!-- 配置獲取連接等待超時(shí)的時(shí)間 --> <property name="maxWait" value="${druid.maxWait}" /> <!-- 最小空閑連接數(shù) --> <property name="minIdle" value="${druid.minIdle}" /> <!-- 配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}" /> <!-- 配置一個(gè)連接在池中最小生存的時(shí)間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${druid.validationQuery}" /> <property name="testWhileIdle" value="${druid.testWhileIdle}" /> <property name="testOnBorrow" value="${druid.testOnBorrow}" /> <property name="testOnReturn" value="${druid.testOnReturn}" /> <property name="maxOpenPreparedStatements" value="${druid.maxOpenPreparedStatements}" /> <!-- 打開 removeAbandoned 功能 --> <property name="removeAbandoned" value="${druid.removeAbandoned}" /> <!-- 1800 秒,也就是 30 分鐘 --> <property name="removeAbandonedTimeout" value="${druid.removeAbandonedTimeout}" /> <!-- 關(guān)閉 abanded 連接時(shí)輸出錯(cuò)誤日志 --> <property name="logAbandoned" value="${druid.logAbandoned}" /> </bean> <!-- spring和MyBatis整合--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="typeAliasesPackage" value="com.ssm.entity" /> <property name="configLocation" value="classpath:mybatis-config/mybatis-config.xml" /> <!-- mapper和resultmap配置路徑 --> <property name="mapperLocations" value="classpath:mybatis-config/mapper/*Mapper.xml"></property> </bean> <!-- DAO接口所在包名,Spring會(huì)自動(dòng)查找其下的類 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.ssm.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!-- (事務(wù)管理)transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <context:component-scan base-package="com.ssm"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> </beans> |
2.表示層控制器實(shí)現(xiàn)
//控制器
@Controller
public class UserController {
//依賴注入業(yè)務(wù)層對(duì)象 聲明是業(yè)務(wù)層的接口引用
@Autowired
private BookService bookService;
//處理器 映射http服務(wù)
@RequestMapping("list")
//返回json類型數(shù)據(jù)
@ResponseBody
public List list(@RequestParam(required=false,defaultValue="1")int page,
@RequestParam(required=false,defaultValue="3")int pageSize){
System.out.println("請(qǐng)求list");
return bookService.getBooks(page,pageSize);
}
}
3.業(yè)務(wù)層接口
public interface BookService {
public List getBooks(int page,int pageSize);
}
4.業(yè)務(wù)層實(shí)現(xiàn)
//業(yè)務(wù)層
@Service
public class BookServiceImpl implements BookService {
//依賴數(shù)據(jù)服務(wù)層對(duì)象
@Autowired
private BookMapper bookMapper;
//調(diào)用數(shù)據(jù)訪問(wèn)層對(duì)象方法,獲取所需數(shù)據(jù)
@Transactional
public List
PageHelper.startPage(page, pageSize);
return bookMapper.findBooks();
}
}
5.數(shù)據(jù)訪問(wèn)層接口
public interface BookMapper {
public List
}
6.數(shù)據(jù)訪問(wèn)映射
<mapper namespace="com.ssm.dao.BookMapper">
<select id="findBooks" resultType="book">
select * from books
</select>
</mapper>