經過學習spring的基礎知識,瞭解了Spring爲了下降Java開發的複雜性,採起了如下4種關鍵策略:html
下面將作一個spring的練習demo,進一步熟悉spring的ioc和aop的使用方法,以及使用spring模板的優勢。java
將構建一個用戶更刪改查的項目,其中對項目進行分層,經過spring的ioc的特性進行依賴注入。並使用aop特性增長日誌操做。數據庫操做使用了spring的jdbcTemplate簡化數據庫操做。mysql
建立一個maven項目,並構建以下文件夾git
--springdemo --src --main --java --aop --conf --dao --service --entity --resources --test --java --service pom.xml
使用到的依賴有spring,slf4j,log4j,mysql-connector等。github
pom.xml以下:web
<?xml version="1.0" encoding="UTF-8"?> <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.tong</groupId> <artifactId>spring-demo</artifactId> <version>1.0-SNAPSHOT</version> <name>spring-demo</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.version>4.3.2.RELEASE</spring.version> <slf4j.version>1.7.24</slf4j.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring 核心 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <!-- spring aop --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.8</version> </dependency> <!-- spring junit --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- spring jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- mysql 驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.22</version> </dependency> <!-- slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> </dependencies> <build> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --> <plugin> <artifactId>maven-site-plugin</artifactId> <version>3.7.1</version> </plugin> <plugin> <artifactId>maven-project-info-reports-plugin</artifactId> <version>3.0.0</version> </plugin> </plugins> </pluginManagement> </build> </project>
entity層即包含User.jave實體類,是一個POJO類,僅包含屬性,構造器和setter,getter方法。spring
以下:sql
package com.tong.entity; /** * User實體類 * * @author tongl * @version 1.0 11/11/2019 */ public class User { Integer id; String name; String sex; Integer age; public User() { } public User(Integer id, String name, String sex, Integer age) { this.id = id; this.name = name; this.sex = sex; this.age = age; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + this.id + ", name='" + this.name + '\'' + ", sex='" + this.sex + '\'' + ", age=" + this.age + '}'; } }
DAO層主要是作數據持久層的工做,負責與數據庫進行聯絡的一些任務都封裝在此,DAO層的設計首先是設計DAO的接口,而後在Spring的配置文件中定義此接口的實現類,而後就可在模塊中調用此接口來進行數據業務的處理,而不用關心此接口的具體實現類是哪一個類,顯得結構很是清晰,DAO層的數據源配置,以及有關數據庫鏈接的參數都在Spring的配置文件中進行配置。數據庫
包括接口和實現。express
UserDao.java
package com.tong.dao; import com.tong.entity.User; /** * 持久化數據層接口 * * @author tongl */ public interface UserDao { /** * 新增用戶 * * @param user 用戶 */ void addUser(User user); /** * 根據id刪除用戶 * * @param id id */ void deleteUser(int id); /** * 根據id查找用戶 * * @param id 用戶id */ User getUser(int id); /** * 更新用戶信息 * * @param user 用戶 */ void updateUser(User user); }
UserDaoImpl.java
package com.tong.dao.impl; import com.tong.dao.UserDao; import com.tong.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import java.util.List; /** * 持久化數據層實現 * * @author tongl */ @Repository public class UserDaoImpl implements UserDao { @Autowired private JdbcTemplate jdbcTemplate; /** * 新增用戶 * * @param user 用戶 */ @Override public void addUser(User user) { jdbcTemplate.update("insert into t_user values(?,?,?,?)", user.getId(), user.getName(), user.getSex(), user.getAge()); } /** * 根據id刪除用戶 * * @param id id */ @Override public void deleteUser(int id) { jdbcTemplate.update("delete from t_user where id = ?", id); } /** * 根據id查找用戶 * * @param id 用戶id * @return user */ @Override public User getUser(int id) { List<User> users = jdbcTemplate.query("select * from t_user where id = ?", new BeanPropertyRowMapper<User>(User.class), id); if (users != null && users.size() > 0) { return users.get(0); } return null; } /** * 更新用戶 * * @param user 用戶 */ @Override public void updateUser(User user) { jdbcTemplate.update("update t_user set name = ?, age = ?, sex = ? where id = ?", user.getName(), user.getAge(), user.getSex(), user.getId()); } }
Service層主要負責業務模塊的邏輯應用設計。一樣是首先設計接口,再設計其實現的類,接着再Spring的配置文件中配置其實現的關聯。這樣咱們就能夠在應用中調用Service接口來進行業務處理。Service層的業務實現,具體要調用到已定義的DAO層的接口,封裝Service層的業務邏輯有利於通用的業務邏輯的獨立性和重複利用性,程序顯得很是簡潔。
UserService.java
package com.tong.service; import com.tong.entity.User; /** * 服務層接口 * * @author tongl * @version 1.0 10/10/2019 */ public interface UserService { /** * 新增修改用戶 * * @param user 用戶 */ void saveUser(User user); /** * 刪除用戶 * * @param id 用戶id */ void deleteUser(int id); }
UserServiceImpl.java
package com.tong.service.impl; import com.tong.dao.UserDao; import com.tong.entity.User; import com.tong.service.UserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 服務層實現 * * @author tongl */ @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); /** * 添加修改用戶 * * @param user 用戶 */ @Override public void saveUser(User user) { Integer id = user.getId(); User u = userDao.getUser(id); if (u == null) { // 若是查詢user爲空,那麼新增用戶 userDao.addUser(user); logger.info("新增用戶:{}", user); } else { // 若是user不爲空,那麼更改用戶 userDao.updateUser(user); logger.info("修改用戶信息:{}", user); } } /** * 刪除用戶 * * @param id 用戶id */ @Override public void deleteUser(int id) { User user = userDao.getUser(id); userDao.deleteUser(id); logger.info("刪除用戶:{}", user); } }
實現日誌切面
Log.java
package com.tong.aop; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.stereotype.Component; /** * 日誌服務 * * @author tongl */ @Component @ComponentScan(basePackages = {"com.fiberhome"}) @Aspect @EnableAspectJAutoProxy public class Log { Logger logger = LoggerFactory.getLogger(Log.class); /** * 配置後置通知:新增/修改用戶打印日誌 */ @AfterReturning("execution(* com.tong.service.*.saveUser(..))") public void addLog() { logger.info("添加/修改用戶操做-日誌記錄"); } /** * 配置後置通知:刪除用戶打印日誌 */ @AfterReturning("execution(* com.tong.service.*.deleteUser(..))") public void deleteLog() { logger.info("刪除用戶操做-日誌記錄"); } }
本項目使用Java配置方式,這裏是Java配置文件。
DataConfig.java
package com.tong.conf; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.*; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; @Configuration @ComponentScan(basePackages = {"com.tong"}) @PropertySource(value = "classpath:db.properties") @Scope("singleton") public class DataConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; /** * 建立鏈接池 * * @return dataSource */ @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } @Bean public JdbcTemplate getJdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }
UserServiceTest
package com.tong.service; import com.tong.conf.DataConfig; import com.tong.entity.User; 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; /** * 用戶服務測試類 * @author tongl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {DataConfig.class}) public class UserServiceTest { @Autowired private UserService userService; /** * 添加用戶測試 */ @Test public void testAddUser(){ User user = new User(1001,"張三","男",17); User user2 = new User(1001,"張三","男",20); User user3 = new User(1012,"張四","男",18); //System.out.println(user); userService.saveUser(user); userService.saveUser(user2); userService.saveUser(user3); } /** * 刪除用戶測試 */ @Test public void testDeleteUser(){ userService.deleteUser(1001); userService.deleteUser(1002); } }
db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///user?useUnicode=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=root
log4j.properties
### 設置### log4j.rootLogger = info,stdout,D,E ### 輸出信息到控制擡 ### log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n ### 輸出DEBUG 級別以上的日誌到logs/debug.log ### log4j.appender.D = org.apache.log4j.DailyRollingFileAppender log4j.appender.D.File = logs/debug.log log4j.appender.D.Append = true log4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayout log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### 輸出ERROR 級別以上的日誌到logs/error.log ### log4j.appender.E = org.apache.log4j.DailyRollingFileAppender log4j.appender.E.File =logs/error.log log4j.appender.E.Append = true log4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayout log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n