1.实例概述
对Spring技术既陌生又熟悉,常听闻SpringMVC技术的优秀,从而将Spring等同于SpringMVC,其实Spring是一个很大的生态,SpringMVC仅仅是一个子项目。
持久层的“Spring JDBC”的, 业务层的“声明式事务”, 和展现层的“Spring MVC”。 这几个原生的技术就能实现一个简单的Web应用
实例简介:
一个普通的登入模块,登入时增加积分,然后后台需要做日志记录
开发分析:
1.首先是考虑数据库的设计,这里使用两张表,分别记录用户信息和登入日志。
2.然后考虑DAO层的设计,这里是对两张表进行操作,所以对应两个DAO类。
3.再者Services的设计,登入操作是一个业务逻辑只对应一个Services,其中具体的逻辑再分别调用两个DAO进行持久化
4.最后是展现层的设计,在本例中,有登录页和欢迎页,在登录页输入帐号和密码,匹配成功后跳转到欢迎页且显示登录名。登入失败重定向到登入页。
开发的准备
数据库的创建: 注意引擎为 ENGINE=InnoDB,这个支持事务,默认的是MyISAM,不支持事务,但是读写比较快
这里学学习在DOS命令下运行脚本,在脚本环境该开始经常混淆的是文件地址的编写 不同系统的路径
项目工程的创建: 首先对工程的编码格式统一为UTF-8
在pom.xml文件中配置Spring,数据源和数据库连接驱动,Servlet类库的依赖信息
规划Spring的配置文件
类包的规划:domain(领域对象)严格是属于业务层,但是领域对象可能同时被持久成和展现层共享,所以一般单独划分为一个包。
测试类和程序的类包一样,但是放在不同的物理位置,方便以后部署时打包
spring的配置文件规划:spring可以将所有的配置信息放到同一个文件夹也可以分开,根据项目的大小决定。
2. 代码开发
领域对象domain/entity
实体类,代表了业务的状态并被实体化到数据库中,领域对象不一定等同于数据库表,在mybatis中,领域对象的属性和数据库表的字段不一定一一对应。
针对需求,设置两个实体类,对应用户信息的User.java和对应登录日志的LoginLog.java
2.1 持久层DAO
2.1.1 DAO层类和方法的设计
首先需要明白DAO层的意义,DAO层简单的说就是调用数据库,对数据库进行增删改查,而往往删除是用“改”来操作的。一个DAO层往往都是根据实体去分的,和用户有关的一个DAO类之类的。然后DAO里面包括多个方法,一个方法就是一次具体的增删改查的操作。而DAO是给Service调用的,一次Service往往包括多个DAO,像一次“登入”就包括积分,登入ip,账户匹配等多个DAO方法。
负责数据的访问和操作,被业务层调用。将数据表中加载的数据实例化为领域对象,将领域对象持久化到数据表中。(持久化的全称:一些专业名次往往只有动词,尝试补充完整的主宾能加深理解)
DAO层的操作就是如下几种,这里我们考虑的是dao层方法的设计!注意和API设计分开:
- 增:
dao层方法的插入,往往是接收一个对象参数,然后将对象里面的属性取出来,再调用API,执行sql语句和赋参
update(String sql, Object... args)
- 改:
改变数据肯定也需要先找到那条数据然后再进行改动吧,所以方法签名也一定会有字符串的条件。 - 查:
查就是比较常用的操作,分为两种查询方式吧。一种是带操作的查,一种是仅仅看是否存在的查。但是查找一定都是根据条件的查,所以方法签名一定有条件的。 - 返回一个对象的查
数据库API的操作结果是一个结果集,怎么把这个集合的元素转换为对象集或者对象输出呢。这是要好好使用API考虑的地方
使用jdbcTemplate:
void query(String sql, Object[] args, RowCallbackHandler rch)
- 返回一个表示查询结果的值
service层传入几个参数,然后DAO调用数据库,将这几个参数变为数据库一条数据,返回的一个判断是否成功的值(boolean,或者数字)
2.2.2 在spring中装配DAO
原因(意义):
在DAO层类中都只有sql的执行语句(也就是涉及业务的部分),只是调用jdbcTemplate,那么现在就应该解决数据库的打开和连接操作。
做法思路:
jdbcTemplate里面包含数据库连接的样板操作,所以需要配置一个DataSource,这样就能从数据源中获取连接。具体的操作如下:
- 声明一个数据源
- 定义一个jdbcTemplate Bean
- 通过Spring的上下文绑定记着进行Bean的注入
2.2.2.1 声明一个数据源
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/sampledb"
p:username="root"
p:password="admin" />
2.2.2.2 定义一个jdbcTemplate Bean
<!-- 配置Jdbc模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />
2.2.2.3 通过Spring的上下文绑定记着进行Bean的注入
声明一个jdbcTemplate的变量
注解@Autowired生成一个,jdbcTemplate的setter方法
2.2 业务层Service
Service层需要在类上注解@Service
2.2.1 业务层的实现
思路介绍:
业务层就是实现一次操作,可以抽象认为是用户的一次点击,往往涉及到多个Dao方法的操作,这时候要加上事务的注解。
@Service
public class UserService {
private UserDao userDao;
private LoginLogDao loginLogDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
// 这就是IoC的属性注入的方式,当被调用时才会使用
@Autowired
public void setLoginLogDao(LoginLogDao loginLogDao) {
this.loginLogDao = loginLogDao;
}
/**
* 登入匹配,调用Dao中方法查询是否数据库中存在这个值
* @param userName
* @param password
* @return
*/
public boolean hasMatchUser(String userName,String password){
int matchCout = userDao.getMatchCount(userName,password);
return matchCout > 0;
}
/**
* 通过用户名查询实体
* @param userName
* @return
*/
public User findUserByUserName(String userName){
User user = userDao.findUserByUserName(userName);
return user;
}
/**
* 这是登入成功时调用的方法
* @param user
*/
@Transactional
public void loginSuccess(User user){
user.setCredits(5 + user.getCredits());
LoginLog loginLog = new LoginLog();
loginLog.setIp(user.getLastIp());
loginLog.setUserId(user.getUserId());
loginLog.setLoginDate(user.getLastVisit());
userDao.updateLoginInfo(user);
loginLogDao.insertLoginLog(loginLog);
}
}
2.2.2 装配业务层
原因(意义):
事务管理的代码虽然没出现在程序中(程序中我们只是在一个方法中调用多个dao方法,然后在方法上添加一个@Transaction)。但是必须告诉spring那些业务需要工作在事务环境下、以及食物的规则等。这样spring才能实现事务管理的功能。
做法思路:
- 添加aop和tx命名空间的Schema定义文件,这样才能使用配置标签
- 添加包到上下文扫描路径中,这样注解才能生效
- 配置事务管理器
- 增加事务增强
实现: - 添加aop和tx命名空间的Schema定义文件,这样才能使用配置标签
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
- 添加包到上下文扫描路径中,这样注解才能生效
- 配置事务管理器,基于数据源,需要引用
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
- 增加事务增强,使她们都工作在事务环境中
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod"
expression="(execution(* com.smart.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>
2.3 展现层View(Web)
2.3.1 配置spring MVC框架
- 通过web容器的上下文参数指定配置spring配置文件的地址
- 指定web容器的监听器,该监听器在web容器启动时自动运行,加载spring的配置文件,然后启动spring容器
- 在web.xml配置一个Servlet拦截url请求
- 最后需要配置spring mvc相关的信息
具体: - 对web.xml文件进行配置````
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mymaster-context.xml</param-value>
</context-param>
2. 指定web容器的监听器,该监听器在web容器启动时自动运行,加载spring的配置文件,然后启动spring容器
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
3. 在web.xml配置一个Servlet拦截url请求
<servlet>
<servlet-name>smart</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>smart</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
Servlet有一个契约,就是servlet名字-servlet.xml的配置文件,且这个不用想spring容器的配置文件那样上下文参数声明contextConfigLocation
4. 最后需要配置spring mvc相关的信息
###2.3.2 处理登入请求
####2.3.2.1 pojo控制器类
####2.3.2.2 SpringMVC配置文件
####2.3.2.3 ModelAndView的解析配置
###2.3.3 JSP视图页面
####2.3.3.1 登入页
####2.3.3.2 欢迎页
##2.4 运行Web应用
问题:
springon容器是如何启动的?
通过配置文件启动的,项目中是通过web容器读取配置文件启动spring容器,测试是直接读取配置文件
配置文件有哪些?
web.xml:这是配置web容器的
servletname-servlet.xml: 这是配置spring的扫描包和视图解析器
spring-context:这是配置spring容器
pom.xml:配置依赖的模块
网友评论