Spring是分层的Java平台应用一站式的轻量级开源框架,以反转控制(Inversion of Control,IoC)和面向切面编程(Aspect Oriented Programming,AOP)为内核,提供了展现层SpringMVC、持久层SpringJDBC以及业务层事务管理等众多企业级应用技术,此外Spring还整合了中国第三方框架和类库。
Spring给我们带来以下几个好处:
-
方便解耦,简化开发。通过Spring提供的IoC容器,可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。
-
AOP编程的支持。通过Spring提供的AOP功能,用户可以方便地进行面向切面编程
-
声明式事务。在Spring中,用户可以从单调烦闷的事务管理代码中解脱出来,通过声明式事务灵活地进行事务管理,提高开发效率和质量
-
方便程序的测试。可以用非容器依赖的编程方式进行所有的测试工作。
-
方便集成各种优秀的框架。Spring是非入侵是框架,能够整合其他优秀框架,如Struts、Hibernate、Quartz等
-
降低JavaEEAPI的使用难度。Spring为JavaEE API(如JDBC、JavaMail和JMS等)提供了一个薄薄的封装层,通过Spring的简易封装,大大降低了这些JavaEE API的使用难度
-
Spring是开源项目,并且是源码是Java技术的最佳实践规范。
Spring的组成:IoC、AOP、数据访问和继承、Web及远程调用以及测试框架。
-
IoC,Spring核心模块实现了IoC的功能,它将类和类之间的依赖从代码中脱离出来,用配置的方式进行依赖关系描述,由IoC容器负责依赖类之间的创建、拼接、管理和获取等工作。BeanFactory接口是Spring框架的核心接口,它实现了容器的许多核心功能。Context模块构建于BeanFactory之上,扩展了BeanFactory的功能。提供了邮件服务、任务调度以及JNDI定位、远程访问等。ApplicationContext是Context模块的核心接口。
-
AOP模块,AOP是进行横切逻辑编程的思想。在AOP模块里,Spring提供了满足AOP Alliance规范的实现,此外和整合了AspectJ这种AOP语言级的框架。
-
数据访问和集成。任何应用程序的核心问题都是对数据的访问和操作。数据有很多表现形式,如数据表、XML、消息等。Spring站在DAO的抽象层面,简历了一套面向DAO层统一的异常体系。其次,Spring通过模板化技术对各种数据访问技术进行了薄层封装,将模式化的代码隐藏起来,是数据访问的程序得到大幅简化。这样Spring就建立起了和数据形式及访问技术无关的统一的DAO层,借助AOP技术,Spring提供了声明式事务的功能。
-
Web及远程访问。Spring提供了MVC,SpringMVC类似于StrutsMVC框架。此外Spring在远程访问以及WebService上提供了很多著名框架的整合。
本章将通过一个登陆示例来演示SpringMVC。
1、准备工作,创建数据库和数据表
DROP DATABASE IF EXISTS spring_src;
CREATE DATABASE spring_src DEFAULT CHARACTER SET utf8;
CREATE USER 'spring_src'@'localhost' IDENTIFIED BY 'spring_src';
GRANT ALL ON spring_src.* TO 'spring_src'@'localhost';
USE spring_src;
##创建用户表
CREATE TABLE t_user (
user_id INT AUTO_INCREMENT PRIMARY KEY,
user_name VARCHAR(30),
password VARCHAR(32),
last_visit datetime,
last_ip VARCHAR(23)
)ENGINE=InnoDB;
##创建用户登录日志表
CREATE TABLE t_login_log (
login_log_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
ip VARCHAR(23),
login_datetime datetime
)ENGINE=InnoDB;
##插入初始化数据
INSERT INTO t_user (user_name,password)
VALUES('admin','123456');
COMMIT;
2、创建的工程如下:
maven项目sprProject的主目录的pom文件内容:
<?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.smart</groupId>
<artifactId>chapter</artifactId>
<packaging>pom</packaging>
<version>3.1-SNAPSHOT</version>
<name>Spring3.1 </name>
<description>Spring3.1</description>
<properties>
<file.encoding>UTF-8</file.encoding>
<java.version>1.6</java.version>
<spring.action.version>3.1-SNAPSHOT</spring.action.version>
<org.springframework.version>3.1.1.RELEASE</org.springframework.version>
<mysql.version>5.1.6</mysql.version>
<commons-dbcp.version>1.2.2</commons-dbcp.version>
<aspectjweaver.version>1.6.9</aspectjweaver.version>
<apache.commons.version>1.1.1</apache.commons.version>
<commons-collections.version>3.2.1</commons-collections.version>
<javassist.version>3.9.0.GA</javassist.version>
<commons-beanutils.version>1.8.3</commons-beanutils.version>
<ehcache.version>1.6.2</ehcache.version>
<hibernate.version>3.6.10.Final</hibernate.version>
<hibernate-validator.version>4.0.2.GA</hibernate-validator.version>
<slf4j-jdk14.version>1.6.1</slf4j-jdk14.version>
<commons-fileupload.version>1.2.1</commons-fileupload.version>
<jsp-api.version>2.0</jsp-api.version>
<servlet-api.version>2.5</servlet-api.version>
<jstl.version>1.2</jstl.version>
<standard.version>1.1.2</standard.version>
<freemarker.version>2.3.8</freemarker.version>
<jetty.version>6.1.5</jetty.version>
<mockito-all.version>1.8.5</mockito-all.version>
<junit.version>4.9.0</junit.version>
<testng.version>6.3.1</testng.version>
<unitils.version>3.1</unitils.version>
<dbunit.version>2.4.8</dbunit.version>
</properties>
<modules>
<module>chapter1</module>
</modules>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
chapter1的pom文件配置依赖关系
<?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">
<parent>
<groupId>com.smart</groupId>
<artifactId>chapter</artifactId>
<version>3.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>chapter1</artifactId>
<version>3.1-SNAPSHOT</version>
<name>第一章示例</name>
<description>Spring 快速入门</description>
<packaging>war</packaging>
<dependencies>
<!--① 依赖的Spring模块类库 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!--② 依赖的持久化类库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--③ 依赖的公共类库-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.logging</artifactId>
<version>${apache.commons.version}</version>
</dependency>
<dependency>
<groupId>fakepath</groupId>
<artifactId>com.springsource.net.sf.cglib</artifactId>
<version>2.1.3</version>
</dependency>
<!--④ 依赖的WEB类库-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>${standard.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!--⑤ 依赖的测试类库-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>
</dependencies>
<build>
<finalName>chapter1</finalName>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<!-- jetty插件 -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.5</version>
<configuration>
<webAppSourceDirectory>src/main/webapp</webAppSourceDirectory>
<scanIntervalSeconds>3</scanIntervalSeconds>
<contextPath>/chapter1</contextPath>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>8088</port>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>
chapter项目的目录结构
相对应的代码如下:
domain(领域对象)包代码如下:
package com.smart.domain; import java.io.Serializable; import java.util.Date; public class User implements Serializable { private int userId; private String userName; private String password; private String lastIp; private Date lastVisit; public String getLastIp() { return lastIp; } public void setLastIp(String lastIp) { this.lastIp = lastIp; } public Date getLastVisit() { return lastVisit; } public void setLastVisit(Date lastVisit) { this.lastVisit = lastVisit; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } 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; } } package com.smart.domain; import java.io.Serializable; import java.util.Date; public class LoginLog implements Serializable { private int loginLogId; private int userId; private String ip; private Date loginDate; public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Date getLoginDate() { return loginDate; } public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } public int getLoginLogId() { return loginLogId; } public void setLoginLogId(int loginLogId) { this.loginLogId = loginLogId; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } }
dao(持久层)代码如下:
package com.smart.dao; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.stereotype.Repository; import com.smart.domain.User; @Repository public class UserDao { @Autowired private JdbcTemplate jdbcTemplate; public int getMatchCount(String userName, String password) { String sqlStr = " SELECT count(*) FROM t_user " + " WHERE user_name =? and password=? "; return jdbcTemplate.queryForInt(sqlStr, new Object[]{userName, password}); } public User findUserByUserName(final String userName) { String sqlStr = " SELECT user_id,user_name " + " FROM t_user WHERE user_name =? "; final User user = new User(); jdbcTemplate.query(sqlStr, new Object[]{userName}, new RowCallbackHandler() { public void processRow(ResultSet rs) throws SQLException { user.setUserId(rs.getInt("user_id")); user.setUserName(userName); } }); return user; } public void updateLoginInfo(User user) { String sqlStr = " UPDATE t_user SET last_visit=?,last_ip=?" + " WHERE user_id =?"; jdbcTemplate.update(sqlStr, new Object[]{user.getLastVisit(), user.getLastIp(), user.getUserId()}); } } package com.smart.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import com.smart.domain.LoginLog; @Repository public class LoginLogDao { @Autowired private JdbcTemplate jdbcTemplate; public void insertLoginLog(LoginLog loginLog) { String sqlStr = "INSERT INTO t_login_log(user_id,ip,login_datetime) " + "VALUES(?,?,?)"; Object[] args = {loginLog.getUserId(), loginLog.getIp(), loginLog.getLoginDate()}; jdbcTemplate.update(sqlStr, args); } }
在Spring中装配dao, 本案例在applicationContext.xml配置中装配dao
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
<context:component-scan base-package="com.smart.dao"/>
<context:component-scan base-package="com.smart.service"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/sampledb31"
p:username="root"
p:password="" />
<!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
<!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务 -->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod"
expression=" execution(* com.smart.service..*(..))" />
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
</beans>
业务层(service)代码:
package com.smart.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.smart.dao.LoginLogDao; import com.smart.dao.UserDao; import com.smart.domain.LoginLog; import com.smart.domain.User; @Service public class UserService { @Autowired private UserDao userDao; @Autowired private LoginLogDao loginLogDao; public boolean hasMatchUser(String userName, String password) { int matchCount = userDao.getMatchCount(userName, password); return matchCount > 0; } public User findUserByUserName(String userName) { return userDao.findUserByUserName(userName); } public void loginSuccess(User user) { LoginLog loginLog = new LoginLog(); loginLog.setUserId(user.getUserId()); loginLog.setIp(user.getLastIp()); loginLog.setLoginDate(user.getLastVisit()); loginLogDao.insertLoginLog(loginLog); } }
在Spring中装配Service,具体内容将applicationContext.xml。
单元测试。TestNG是一种基于注解的新一代单元测试框架,通过添加灵活的配置、测试分类和参数设置以及依赖测试等特性来克服JUnit的不足之处。首先在pom.xml文件中配置testNG、Spring-test的两个类的依赖。详见chapter1项目下的pom.xml。
单元测试模块结构:
单元测试代码如下:
package com.smart.service; import java.util.Date; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.*; import static org.testng.Assert.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import com.smart.domain.User; @ContextConfiguration(locations = {"/applicationContext.xml"}) public class UserServiceTest extends AbstractTestNGSpringContextTests { @Autowired private UserService userService; @Test public void hasMatchUser() { boolean b1 = userService.hasMatchUser("admin", "123456"); boolean b2 = userService.hasMatchUser("admin", "1111"); assertTrue(b1); assertTrue(!b2); } @Test public void findUserByUserName() { User user = userService.findUserByUserName("admin"); assertEquals(user.getUserName(), "admin"); } @Test public void loginSuccess() { User user = userService.findUserByUserName("admin"); user.setUserId(1); user.setUserName("admin"); user.setLastIp("192.168.12.7"); user.setLastVisit(new Date()); userService.loginSuccess(user); } } package com.smart.dao; import com.smart.domain.User; import com.smart.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.testng.annotations.Test; import java.util.Date; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; @ContextConfiguration(locations = {"/applicationContext.xml"}) public class UserDaoTest extends AbstractTestNGSpringContextTests { @Autowired private UserDao userDao; @Test public void hasMatchUser() { int count = userDao.getMatchCount("admin", "123456"); assertTrue(count>0); } @Test public void findUserByUserName() { User user = userDao.findUserByUserName("admin"); assertNotNull(user); assertEquals(user.getUserName(), "admin"); } } package com.smart.web; import com.smart.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; @ContextConfiguration(locations = {"classpath:applicationContext.xml","file:d:/actionSpring/chapter/chapter1/src/main/webapp/WEB-INF/viewspace-servlet.xml"}) public class LoginControllerTest extends AbstractTestNGSpringContextTests { @Autowired private AnnotationMethodHandlerAdapter handlerAdapter; @Autowired private LoginController controller; //声明Request与Response模拟对象 private MockHttpServletRequest request; private MockHttpServletResponse response; //执行测试前先初始模拟对象 @BeforeMethod public void before() { request = new MockHttpServletRequest(); request.setCharacterEncoding("UTF-8"); response = new MockHttpServletResponse(); request.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, true); //Spring3.1 存在的BUG } // 测试LoginController#loginCheck()方法 @Test public void loginCheck() throws Exception { //测试登陆成功的情况 request.setRequestURI("/admin/loginCheck.html"); request.addParameter("userName", "admin"); // 设置请求URL及参数 request.addParameter("password", "123456"); //向控制发起请求 ” /loginCheck.html” ModelAndView mav = handlerAdapter.handle(request, response, controller); User user = (User) request.getSession().getAttribute("user"); assertNotNull(mav); assertEquals(mav.getViewName(), "main"); assertNotNull(user); request.getSession().removeAttribute("user"); //测试登陆失败的情况 request.setRequestURI("/admin/loginCheck.html"); request.addParameter("userName", "test"); request.addParameter("password", "123456"); mav = handlerAdapter.handle(request, response, controller); user = (User) request.getSession().getAttribute("user"); assertNotNull(mav); assertEquals(mav.getViewName(), "login"); assertNull(user); } }
示例更多内容及运行结果请见附件
本文出自 “阿酷博客源” 博客,请务必保留此出处http://aku28907.blog.51cto.com/5668513/1787920
转载于:https://my.oschina.net/mrku/blog/693727
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108968.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...