主要的内容
- 构建工具:Maven
- 例子:用户登陆校验
- 持久层:使用SpringJDBC和MyBatis
- 业务层是设计Spring的声明式事务
- 展现层:SpringMvc
- 开发工具:IDEA
- 实例使用
一.包类的规划
将项目划分为按照业务划分可以划分为三层,分别时持久层,业务层,展现层,但是所有的层使用到的对象可能会共用,所以将所有的对象放在领域对象的包内,使得这些公共的类都存放一个包里面。
单元测试的类包和程序的类包对应,但是方式再不同的的文件夹下,这样的目的是方便程序的打包和发布,因为测试是在开发的时候使用,无需部署到包中。
包类结构图如下:
二.配置文件规划
集成Spring的系统可以将所有的配置信息统一到一个文件中,也可以放置到多个文件中,对于简单的应用来说,由于配置信息少,使用一个配置文件足够应付,但是随着配置信息增加,一个配置文件就显得捉襟见肘,对于团队的协作开发也是很不利的。这里我们的配置信息很少,所以一个配置文件足够应付
配置内容: flexible-context.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: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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!--扫描类,使得使用了注解的类自动生成bean,同时完成Bean的注入-->
<context:component-scan base-package="com.flexible.dao"></context:component-scan>
<context:component-scan base-package="com.flexible.web"></context:component-scan>
<context:component-scan base-package="com.flexible.service"></context:component-scan>
<!--使用dbcp作为数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/springdb"
p:username="root"
p:password="root@123"
></bean>
<!--配置JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"
></bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"
></bean>
<!--通过AOP配置提供事务增强,让service包下的Bean的所有方法都拥有事务-->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod"
expression="(execution(* com.flexible.service..*(..))) and (@annotation(org.springframework.transaction.annotation.Transactional))"/>
<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>
flexible-servlet.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--扫描web包,应用Sprig的注解-->
<context:component-scan base-package="com.flexible.web"/>
<!--配置试图解析器,将ModelAndView及字符串解析为具体的页面-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/pages/"
p:suffix=".jsp"></bean>
</beans>
web.xml
三.持久层
创建领域对象
public class User implements Serializable {
/**
* 用户id
*/
private Integer userId;
/**
* 用户名称
*/
private String userName;
/**
*用户密码
*/
private String password;
/**
*签到分数
*/
private Integer credits;
/**
* 最新Ip
*/
private String lastIp;
/**
* 最后访问日期
*/
private Date lastVisit;
....
}
public class LoginLog {
/**
* 登陆日志id
*/
private Integer loginLogId;
/**
* 用户id
*/
private Integer userId;
/**
* ip
*/
private String ip;
/**
* 登陆日期
*/
private Date loginDate;
...
}
知识点总结: 领域对象可以细分为四种: PO(Persistent Object):持久化对象,表示持久层的的数据结果 DTO(Data Transfer Object):数据传输对象,以前是EJB分布式应用的粗粒度的数据事提,现在泛指展现层于服务之间的数据传输对象,可以堪称和DO等效 DO等等于DTO VO(View Object):试图对象,展示对象。
一.使用DAO 在DAO实现类中不需要我们手动得去链接和释放链接,jdbcTemplate将这些都已经抽取出来了,我们需要做得就是需要在配置文件里面配置 然后将jdbcTemplate使用注解@Autowired注解注入jdbcTemplate变量,所以我们必须先在配置文件声明数据源和定义jdbcTemplate的bean
flexible-context.xml
<!--使用dbcp作为数据库连接池-->
<bean id="dataSource"
//使用了DBCP数据源
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/springdb"
p:username="root"
p:password="root@123"
></bean>
<!--配置JDBC模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"
></bean>
Java掉代码 UserDao.java
[@Repository](https://my.oschina.net/u/3055569)
public class UserDao {
private JdbcTemplate jdbcTemplate;
private final static String MATCH_COUNT_SQL = " SELECT count(*) " +
"FROM t_user " +
"WHERE user_name =? " +
"AND password=? ";
private final static String UPDATE_LOGIN_INFO_SQL = " UPDATE t_user " +
"SET " +
"last_visit=?," +
"last_ip=?," +
"credits=?"+
" WHERE user_id =?";
@Autowired
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 根据用户名查询
*
* @param userName
* @return
*/
public User getUserByUserName(String userName) {
String searchSql = "SELECT user_id,user_name,credits " +
"FROM t_user " +
"WHERE user_name=?";
final User user = new User();
jdbcTemplate.query(searchSql, new Object[]{userName}, (resultSet) -> {
user.setUserId(resultSet.getInt("user_id"));
user.setUserName(userName);
user.setCredits(resultSet.getInt("credits"));
});
return user == null ? new User() : user;
}
/**
* 更新用户登陆日志
*
* @param user
*/
public Boolean updateLoginInfo(User user) {
System.out.println(user.toString());
Integer flag = jdbcTemplate.update(UPDATE_LOGIN_INFO_SQL, new Object[] { user.getLastVisit(),
user.getLastIp(),user.getCredits(),user.getUserId()});
return flag > 0 ? true : false;
}
/**
* 根据账号和密码查找匹配的数量
*
* @param userName
* @param password
* @return
*/
public int getMatchCount(String userName, String password) {
return jdbcTemplate.queryForObject(MATCH_COUNT_SQL, new Object[]{userName, password}, Integer.class);
}
}
LoginLogDao.java
@Repository
public class LoginLogDao {
private JdbcTemplate jdbcTemplate;
//保存登陆日志SQL
private final static String INSERT_LOGIN_LOG_SQL= "INSERT INTO t_login_log(user_id,ip,login_datetime) VALUES(?,?,?)";
public void insertLoginLog(LoginLog loginLog) {
Object[] args = { loginLog.getUserId(), loginLog.getIp(),
loginLog.getLoginDate() };
jdbcTemplate.update(INSERT_LOGIN_LOG_SQL, args);
}
@Autowired
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
二.使用Mapper
业务层
事务管理代码没有出现在程序的代码中,但是我们需要以某种方式告诉Spring哪些业务需要工作在事务环境下以及事务的规则等内容,以便Spring根据这些信息自动为目标业务添加事务管理的能力 flexible-context.xml
<!--扫描事务层的代码-->
<context:component-scan base-package="com.flexible.service"> </context:component-scan>
<!--通过AOP配置提供事务增强,让service包下的Bean的所有方法都拥有事务-->
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod"
expression="(execution(* com.flexible.service..*(..))) and (@annotation(org.springframework.transaction.annotation.Transactional))"/>
<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>
在Java代码里面我们需要做的就是将方法上面声明一个注解 @Transactional,例如
@Transactional
public void loginSuccess(User user) {
user.setCredits(5 + user.getCredits());
LoginLog loginLog = new LoginLog();
loginLog.setUserId(user.getUserId());
loginLog.setIp(user.getLastIp());
loginLog.setLoginDate(user.getLastVisit());
userDao.updateLoginInfo(user);
loginLogDao.insertLoginLog(loginLog);
}
单元测试
TestNG和JUnit相比有较大的改进,需要将TestNG依赖添加进pom.xml.Spring4.x的测试框架很好的整合了TestNG单元测试框架,通过继承AbstractTransactionalTestNGSpringContextTests类来启动测试运行器,@ContextConfiguration用于知道Spring的配置文件。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
单元测试代码如下:
@ContextConfiguration("classpath*:/flexible-context.xml")
public class UserServiceTest extends AbstractTransactionalTestNGSpringContextTests {
@Autowired
UserService userService;
@Test
public void testHasMatchUser(){
boolean b1 = userService.hasMatchUser("admin", "123456");
boolean b2 = userService.hasMatchUser("admin", "1111");
assertTrue(b1);
assertTrue(!b2);
}
}
展现层
Spring3.0提供了REST风格的MVC,是SpringMvc变得更加的轻便,易用。Spring4.x对mvc金行了全面的升级,支持了@CrossOrigi配置,Groovy Web集成,Gson,Jackson,Protobuf的HttpMessageConverter消息转换器,使得SpringMvc的功能更加丰富,强大。
@RestController
public class LoginController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
@RequestMapping(value = "/index.html")
public String loginPage() {
return "login";
}
@RequestMapping(value = "/loginCheck.html")
public ModelAndView loginCheck(HttpServletRequest request, LoginCommand loginCommand) {
boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(),
loginCommand.getPassword());
System.out.println("the request parameter is username {},password {}" + loginCommand.getUserName() + "," + loginCommand.getPassword());
if (!isValidUser) {
return new ModelAndView("login", "error", "用户名或密码错误。");
} else {
User user = userService.findUserByUserName(loginCommand
.getUserName());
user.setLastIp(request.getLocalAddr());
user.setLastVisit(new Date());
userService.loginSuccess(user);
request.getSession().setAttribute("user", user);
return new ModelAndView("main");
}
}
}
ModelAndView对象既包括试图信息,又包括渲染试图需要的模型信息,解析试图的配置在flexible-servlet.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--扫描web包,应用Sprig的注解-->
<context:component-scan base-package="com.flexible.web"/>
<!--配置试图解析器,将ModelAndView及字符串解析为具体的页面-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/pages/"
p:suffix=".jsp"></bean>
</beans>
项目地址: https://github.com/chenanddom/SpringSection1




3411

被折叠的 条评论
为什么被折叠?



