Spring 事务管理
事务管理四个关键属性 ACID:
- 原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。
- 一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。
- 隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。
- 持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。
Spring 支持编程式和声明式事务管理。EJBs 需要一个应用程序服务器,但 Spring 事务管理可以在不需要应用程序服务器的情况下实现。
局部事物 vs. 全局事务
局部事务是特定于一个单一的事务资源,如一个 JDBC 连接,而全局事务可以跨多个事务资源事务,如在一个分布式系统中的事务。
局部事务管理在一个集中的计算环境中是有用的,该计算环境中应用程序组件和资源位于一个单位点,而事务管理只涉及到一个运行在一个单一机器中的本地数据管理器。局部事务更容易实现。
全局事务管理需要在分布式计算环境中,所有的资源都分布在多个系统中。在这种情况下事务管理需要同时在局部和全局范围内进行。分布式或全局事务跨多个系统执行,它的执行需要全局事务管理系统和所有相关系统的局部数据管理人员之间的协调。
编程式 vs. 声明式
Spring 支持两种类型的事务管理:
- 编程式事务管理 :这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。
- 声明式事务管理 :这意味着你从业务代码中分离事务管理。你仅仅使用注解或 XML 配置来管理事务。
Spring 事务抽象
Spring 事务抽象的关键是由 org.springframework.transaction.PlatformTransactionManager 接口定义,如下所示:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition);
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
序号 方法 & 描述
1 TransactionStatus getTransaction(TransactionDefinition definition)根据指定的传播行为,该方法返回当前活动事务或创建一个新的事务。
2 void commit(TransactionStatus status)该方法提交给定的事务和关于它的状态。
3 void rollback(TransactionStatus status)该方法执行一个给定事务的回滚。
TransactionDefinition 是在 Spring 中事务支持的核心接口,它的定义如下:
public interface TransactionDefinition {
int getPropagationBehavior();
int getIsolationLevel();
String getName();
int getTimeout();
boolean isReadOnly();
}
序号 方法 & 描述
1 int getPropagationBehavior()该方法返回传播行为。Spring 提供了与 EJB CMT 类似的所有的事务传播选项。
2 int getIsolationLevel()该方法返回该事务独立于其他事务的工作的程度。
3 String getName()该方法返回该事务的名称。
4 int getTimeout()该方法返回以秒为单位的时间间隔,事务必须在该时间间隔内完成。
5 boolean isReadOnly()该方法返回该事务是否是只读的。
下面是隔离级别的可能值:
序号 隔离 & 描述
1 TransactionDefinition.ISOLATION_DEFAULT这是默认的隔离级别。
2 TransactionDefinition.ISOLATION_READ_COMMITTED表明能够阻止误读;可以发生不可重复读和虚读。
3 TransactionDefinition.ISOLATION_READ_UNCOMMITTED表明可以发生误读、不可重复读和虚读。
4 TransactionDefinition.ISOLATION_REPEATABLE_READ表明能够阻止误读和不可重复读;可以发生虚读。
5 TransactionDefinition.ISOLATION_SERIALIZABLE表明能够阻止误读、不可重复读和虚读。
下面是传播类型的可能值:
序号 传播 & 描述
1 TransactionDefinition.PROPAGATION_MANDATORY支持当前事务;如果不存在当前事务,则抛出一个异常。
2 TransactionDefinition.PROPAGATION_NESTED如果存在当前事务,则在一个嵌套的事务中执行。
3 TransactionDefinition.PROPAGATION_NEVER不支持当前事务;如果存在当前事务,则抛出一个异常。
4 TransactionDefinition.PROPAGATION_NOT_SUPPORTED不支持当前事务;而总是执行非事务性。
5 TransactionDefinition.PROPAGATION_REQUIRED支持当前事务;如果不存在事务,则创建一个新的事务。
6 TransactionDefinition.PROPAGATION_REQUIRES_NEW创建一个新事务,如果存在一个事务,则把当前事务挂起。
7 TransactionDefinition.PROPAGATION_SUPPORTS支持当前事务;如果不存在,则执行非事务性。
8 TransactionDefinition.TIMEOUT_DEFAULT使用默认超时的底层事务系统,或者如果不支持超时则没有。
TransactionStatus 接口为事务代码提供了一个简单的方法来控制事务的执行和查询事务状态。
public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
序号 方法 & 描述
1 boolean hasSavepoint()该方法返回该事务内部是否有一个保存点,也就是说,基于一个保存点已经创建了嵌套事务。
2 boolean isCompleted()该方法返回该事务是否完成,也就是说,它是否已经提交或回滚。
3 boolean isNewTransaction()在当前事务时新的情况下,该方法返回 true。
4 boolean isRollbackOnly()该方法返回该事务是否已标记为 rollback-only。
5 void setRollbackOnly()该方法设置该事务为 rollback-only 标记。
Spring 编程式事务管理
步骤:
- 配置事务管理bean:PlatformTransactionManager
- 依赖注入到操作类上。
- 创建事务,获得TransactionStatus
- 回滚或提交事务。
前提:新增表
CREATE TABLE IF NOT EXISTS t_bonus (
id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
developer_id BIGINT(20) NOT NULL COMMENT '员工id',
bonus DECIMAL(13,2) DEFAULT '0' COMMENT '奖金',
performance SMALLINT(2) DEFAULT NULL COMMENT '绩效',
PRIMARY KEY (id)
)ENGINE = INNODB AUTO_INCREMENT=10000 DEFAULT CHARSET=utf8 COMMENT '开发员工奖金表';
例子:
public class DeveloperDaotJDBCTemplate implements DeveloperDao {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
private SimpleJdbcCall simpleJdbcCall;
private PlatformTransactionManager transactionManager;
@Override
public void setDataSource(DataSource ds) {
this.dataSource = ds;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.simpleJdbcCall = new SimpleJdbcCall(dataSource).withProcedureName("getRecord");
}
@Override
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Override
public void insertDeveloperAndBonus(Developer developer, Bonus bonus) {
TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
String sql = "insert into t_developer(name,work_level,position,salary,status) values (?,?,?,?,?)";
int developerId = jdbcTemplate.update(sql, developer.getName(), developer.getWorkLevel(), developer.getPosition(), developer.getSalary(),
developer.getStatus());
String sqlBonus = "insert into t_bonus(developer_id,bonus,performance) values (?,?,?)";
jdbcTemplate.update(sqlBonus,developerId,bonus.getBonus(),bonus.getPerformance());
transactionManager.commit(transactionStatus);
System.out.println("-------------commit------------");
} catch (DataAccessException e) {
transactionManager.rollback(transactionStatus);
System.out.println("-------------rollback------------");
e.printStackTrace();
}
System.out.println("-------------insertDeveloperAndBonus------------");
}
}
public class Bonus {
/**
* 主键
*/
private Integer id;
/**
* 员工id
*/
private Integer developerId;
/**
* '奖金'
*/
private BigDecimal bonus;
/**
* ''绩效''
*/
private Integer performance;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getDeveloperId() {
return developerId;
}
public void setDeveloperId(Integer developerId) {
this.developerId = developerId;
}
public BigDecimal getBonus() {
return bonus;
}
public void setBonus(BigDecimal bonus) {
this.bonus = bonus;
}
public Integer getPerformance() {
return performance;
}
public void setPerformance(Integer performance) {
this.performance = performance;
}
}
DeveloperDao developerDao = (DeveloperDao)context.getBean("developerDaotJDBCTemplate");
Developer developer = new Developer();
developer.setStatus(1);
developer.setWorkLevel(3);
developer.setSalary(new BigDecimal("87010.78"));
developer.setPosition("贷款");
developer.setName("Master Ting");
Bonus bonus = new Bonus();
bonus.setBonus(new BigDecimal("100000.58"));
bonus.setPerformance(1);
developerDao.insertDeveloperAndBonus(developer,bonus);
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/hello_spring"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean class="com.self.jdbc.impl.DeveloperDaotJDBCTemplate" id="developerDaotJDBCTemplate">
<property name="dataSource" ref="dataSource"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
输出:
失败:
-------------rollback------------
-------------insertDeveloperAndBonus------------
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [insert into t_bonus(developer_id,bonus,performance) values (?,?,?)]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hello_spring.t_bonus' doesn't exist
成功:
-------------commit------------
-------------insertDeveloperAndBonus------------
Spring 声明式事务管理
这块声明式事务没讲清楚,一些xml配置没说明清楚。
声明式事务管理方法允许你在配置的帮助下而不是源代码硬编程来管理事务。这意味着你可以将事务管理从事务代码中隔离出来。你可以只使用注释或基于配置的 XML 来管理事务。 bean 配置会指定事务型方法。
扫描事务步骤:
- 我们使用标签,它创建一个事务处理的建议,同时,我们定义一个匹配所有方法的切入点,我们希望这些方法是事务型的并且会引用事务型的建议。
- 如果在事务型配置中包含了一个方法的名称,那么创建的建议在调用方法之前就会在事务中开始进行。
- 目标方法会在 try / catch 块中执行。
- 如果方法正常结束,AOP 建议会成功的提交事务,否则它执行回滚操作。
实例:
注意:如果 <tx:method name="insert*"/> 没有加 *,表示完全匹配,如果方法名不是insert,则不会加入事务;加 * 表示只要是前缀是insert的方法都会加入事务中
<!--注意这边要加入tx声明 -->
<xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/hello_spring"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean class="com.self.jdbc.impl.DeveloperDaotJDBCTemplate" id="developerDaotJDBCTemplate">
<property name="dataSource" ref="dataSource"/>
<!--<property name="transactionManager" ref="transactionManager"/>-->
</bean>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txManager" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="insert*"/>
<tx:method name="update*"/>
<tx:method name="delete*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.self.jdbc.*.*(..))"/>
<aop:advisor advice-ref="txManager" pointcut-ref="txPointcut"/>
</aop:config>
public class DeveloperDaotJDBCTemplate implements DeveloperDao {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
@Override
public void setDataSource(DataSource ds) {
this.dataSource = ds;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.simpleJdbcCall = new SimpleJdbcCall(dataSource).withProcedureName("getRecord");
}
@Override
public void insertDeveloperAndBonus(Developer developer, Bonus bonus) {
try {
String sql = "insert into t_developer(name,work_level,position,salary,status) values (?,?,?,?,?)";
int developerId = jdbcTemplate.update(sql, developer.getName(), developer.getWorkLevel(), developer.getPosition(), developer.getSalary(),
developer.getStatus());
String sqlBonus = "insert into t_bonus(developer_id,bonus,performance) values (?,?,?)";
jdbcTemplate.update(sqlBonus,developerId,bonus.getBonus(),bonus.getPerformance());
throw new RuntimeException("error occures");
//System.out.println("-------------commit------------");
} catch (DataAccessException e) {
System.out.println("-------------rollback------------");
e.printStackTrace();
}
System.out.println("-------------insertDeveloperAndBonus------------");
}
}
输出:
成功:
-------------commit------------
-------------insertDeveloperAndBonus------------
失败:
Exception in thread "main" java.lang.RuntimeException: error occures
at com.self.jdbc.impl.DeveloperDaotJDBCTemplate.insertDeveloperAndBonus(DeveloperDaotJDBCTemplate.java:133)
Spring Web MVC 框架
Spring web MVC 框架提供了模型-视图-控制的体系结构和可以用来开发灵活、松散耦合的 web 应用程序的组件。MVC 模式导致了应用程序的不同方面(输入逻辑、业务逻辑和 UI 逻辑)的分离,同时提供了在这些元素之间的松散耦合。
- 模型封装了应用程序数据,并且通常它们由 POJO 组成。
- 视图主要用于呈现模型数据,并且通常它生成客户端的浏览器可以解释的 HTML 输出。
- 控制器主要用于处理用户请求,并且构建合适的模型并将其传递到视图呈现。
DispatcherServlet
Spring Web 模型-视图-控制(MVC)框架是围绕 DispatcherServlet 设计的,DispatcherServlet 用来处理所有的 HTTP 请求和响应。Spring Web MVC DispatcherServlet 的请求处理的工作流程如下图所示:
下面是对应于 DispatcherServlet 传入 HTTP 请求的事件序列:
- 收到一个 HTTP 请求后,DispatcherServlet 根据 HandlerMapping 来选择并且调用适当的控制器。
- 控制器接受请求,并基于使用的 GET 或 POST 方法来调用适当的 service 方法。Service 方法将设置基于定义的业务逻辑的模型数据,并返回视图名称到 DispatcherServlet 中。
- DispatcherServlet 会从 ViewResolver 获取帮助,为请求检取定义视图。
- 一旦确定视图,DispatcherServlet 将把模型数据传递给视图,最后呈现在浏览器中。
上面所提到的所有组件,即 HandlerMapping、Controller 和 ViewResolver 是 WebApplicationContext 的一部分,而 WebApplicationContext 是带有一些对 web 应用程序必要的额外特性的 ApplicationContext 的扩展。
web.xml 文件将被保留在你的应用程序的 WebContent/WEB-INF 目录下。好的,在初始化 HelloWeb DispatcherServlet 时,该框架将尝试加载位于该应用程序的 WebContent/WEB-INF 目录中文件名为 [servlet-name]-servlet.xml 的应用程序内容。在这种情况下,我们的文件将是 springhello-servlet.xml。
默认配置web.xml,下面的配置默认回去加载<servlet-name>hellospring</servlet-name>:对应的 springhello-servlet.xml名字的spring mvc配置,该配置一般用来加载spring mvc容器。
<servlet>
<servlet-name>hellospring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hellospring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
如果要自定义加载的配置名,不用默认的,可以如下这样配置,加载classpath:spring/appcontext-core.xml配置文件:
<servlet>
<servlet-name>hellospring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/appcontext-core.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hellospring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
在 web.xml 文件中添加 servlet 监听器 ContextLoaderListener 自定义该文件的名称和位置 ,这个一般是用来加载spring容器,前面的一般用来加载spring mvc容器。两个容器区分开来,我能想到的好处就是避免耦合;可以灵活获取单一容器,单一职责,避免容器过于庞大。
自定义配置加载如下,在web.xml中添加,可以添加多个配置文件:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/appcontext-core.xml,
classpath*:com/spring/dataAccessContext-ibatis-IS.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>加 <listener>组合加载配置文件时如果没有配置<servlet>,就会去加载默认的DispatcherServlet,这时候如果没有默认的 springhello-servlet.xml文件加载就会因此获取不到配置,导致虽然tomcat可以启动,但因为spring mvc容器没能加载到配置bean,如没能扫描到@Controller,导致会报加载404,The requested resource is not available. 这时候在配置servlet时用自定义的配置文件名就不会有这种问题。
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/appcontext-core.xml
</param-value>
</init-param>
Spring MVC Hello World 例子
实例:
@Controller
public class HelloController {
@RequestMapping("/hello")
public String getHello(ModelMap modelMap){
modelMap.addAttribute("message","hello,I'am soul good man");
return "hello";
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>hellospring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/hellospring-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hellospring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/appcontext-core.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
hellospring-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:tx="http://www.springframework.org/schema/tx"
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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<!--spring mvc容器扫描配置-->
<context:component-scan base-package="com.self" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
WEB-INF/jsp/hello.jsp:
<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2>${message}</h2>
</body>
</html>
输出:
期间遇到的错误解答:
当输出${message}时,jsp不解析el表达式
用Maven-archetype-webapp 创建项目时,使用的servlet版本是2.3,而servlet2.4以下的版本是不会自动解析el表达式的,改成3.0的即可。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
一开始项目配置tomcat启动不了:
注意检查是否配置pom.xml时打的是否为war包,之前我配置成jar包了,还有就是要注意打印日志输出出来的失败原因。大可以把其中的关键字语句放到百度,Google上搜索一下,看下别人的解答。我这边是因为在idea配置项目配置设置。
错误:
Artifact tlks: com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException: E: not found for the web module.
找不到这个web module,在project structure 中添加Artifact配置,一直是exploded.
然后配置tomcat,项目访问路径名:
设置项目编译后的文件输出位置:
Spring MVC 表单处理例子
实例:
public class Developer {
/**
* 主键
*/
private Integer id;
/**
* '姓名'
*/
private String name;
/**
* '等级'
*/
private Integer workLevel;
/**
* '职位'
*/
private String position;
/**
* '薪水'
*/
private BigDecimal salary;
/**
* '状态'
*/
private Integer status;
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 Integer getWorkLevel() {
return workLevel;
}
public void setWorkLevel(Integer workLevel) {
this.workLevel = workLevel;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}
@Controller
public class DeveloperController {
@RequestMapping("/developer")
public ModelAndView developer(){
return new ModelAndView("developer","command",new Developer());
}
@RequestMapping(value = "/addDeveloper",method = RequestMethod.POST)
public String addDeveloper(@ModelAttribute("SpringWeb") Developer developer,ModelMap modelMap){
modelMap.addAttribute("name",developer.getName());
modelMap.addAttribute("position",developer.getPosition());
modelMap.addAttribute("salary",developer.getSalary());
modelMap.addAttribute("workLevel",developer.getWorkLevel());
modelMap.addAttribute("status",developer.getStatus());
modelMap.addAttribute("id",developer.getId());
return "result";
}
}
developer.jsp :
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Spring MVC Form Handling</title>
</head>
<body>
<h2>Developer Information</h2>
<form:form method="POST" action="/hellospring/addDeveloper">
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td><form:label path="workLevel">workLevel</form:label></td>
<td><form:input path="workLevel" /></td>
</tr>
<tr>
<td><form:label path="position">position</form:label></td>
<td><form:input path="position" /></td>
</tr>
<tr>
<td><form:label path="salary">salary</form:label></td>
<td><form:input path="salary" /></td>
</tr>
<tr>
<td><form:label path="status">status</form:label></td>
<td><form:input path="status" /></td>
</tr>
<tr>
<td><form:label path="id">id</form:label></td>
<td><form:input path="id" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
result.jsp :
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Spring MVC Form Handling</title>
</head>
<body>
<h2>Submitted Developer Information</h2>
<table>
<tr>
<td>Name</td>
<td>${name}</td>
</tr>
<tr>
<td>workLevel</td>
<td>${workLevel}</td>
</tr>
<tr>
<td>position</td>
<td>${position}</td>
</tr>
<tr>
<td>salary</td>
<td>${salary}</td>
</tr>
<tr>
<td>status</td>
<td>${status}</td>
</tr>
<tr>
<td>ID</td>
<td>${id}</td>
</tr>
</table>
</body>
</html>
web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>hellospring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/hellospring-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hellospring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/appcontext-core.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
hellospring-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:tx="http://www.springframework.org/schema/tx"
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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<!--spring mvc容器扫描配置-->
<context:component-scan base-package="com.self" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
输出:
Spring 页面重定向例子
例子:
@Controller
public class RedirectController {
@RequestMapping("/index")
public String index(){
return "index";
}
@RequestMapping("/redirect")
public String redirect(){
return "redirect: final";
}
@RequestMapping("/final")
public String finalPage(){
return "final";
}
}
index.jsp :
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Spring Page Redirection</title>
</head>
<body>
<h2>Spring Page Redirection</h2>
<p>Click below button to redirect the result to new page</p>
<form:form method="GET" action="/hellospring/redirect">
<table>
<tr>
<td>
<input type="submit" value="GO FINAL"/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
final.jsp :
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Spring Page Redirection</title>
</head>
<body>
<h2>Redirected Final Page</h2>
</body>
</html>
输出:
Spring 使用 Log4J 记录日志
一般项目配置日志有2种打印日志的方法:
一种是slf4j api + slf4j-log412 + log4j .
另一种是slf4j api + logback-classic + logback-core
<!--=================log4j依赖===============-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!--=================log4j依赖===============-->
<!--=================logback依赖===============-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!--=================logback依赖===============-->
例子:
@Controller
public class DeveloperController {
private static final Logger LOGGER = LoggerFactory.getLogger(DeveloperController.class);
@RequestMapping("/developer")
public ModelAndView developer(){
return new ModelAndView("developer","command",new Developer());
}
@RequestMapping(value = "/addDeveloper",method = RequestMethod.POST)
public String addDeveloper(@ModelAttribute("SpringWeb") Developer developer,ModelMap modelMap){
LOGGER.error("====================start===================");
modelMap.addAttribute("name",developer.getName());
modelMap.addAttribute("position",developer.getPosition());
modelMap.addAttribute("salary",developer.getSalary());
modelMap.addAttribute("workLevel",developer.getWorkLevel());
modelMap.addAttribute("status",developer.getStatus());
modelMap.addAttribute("id",developer.getId());
LOGGER.error("====================end===================");
return "result";
}
}
log4j.properties:
log4j.rootLogger = ERROR,CONSOLE
#RollingFile Appender
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.Threshold = error
log4j.appender.R.File =
log4j.appender.R.Append = true
log4j.appender.R.ImmediateFlush = true
log4j.appender.R.DatePattern = '.'yyyy-MM-dd'.txt'
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %t %c{15}:%M(%L) - %m%n
#DB Appender
log4j.appender.DB=
log4j.appender.DB.Threshold=INFO
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
log4j.appender.DB.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %C{8}@(%F:%L)%n [%-5p]: %m%n
#Console Appender
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %C{8}@(%F:%L)%n [%-5p]: %m%n
pom.xml
<!--=================log4j依赖===============-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!--=================log4j依赖===============-->
注意log4j.properties在resources的根目录下
疑问
Q:Spring 可以使开发人员使用 POJOs 开发企业级的应用程序。只使用 POJOs 的好处是你不需要一个 EJB 容器产品,比如一个应用程序服务器,但是你可以选择使用一个健壮的 servlet 容器,比如 Tomcat 或者一些商业产品。
怎么理解这句话?
Q:Spring Bean 后置处理器在具体的项目中有哪些实际的用法呢?感觉目前接触的项目都没有用到过?
Q: @Resource 如果没有明确地指定一个 ‘name’,默认名称源于字段名或者 setter 方法。在字段的情况下,它使用的是字段名;在一个 setter 方法情况下,它使用的是 bean 属性名称。 在一个 setter 方法情况下,它使用的是 bean 属性名称是指使用的是容器里注册的bean名称?
应该不是,其实还是字段名,也就是要被注入依赖bean的实例的属性名称。
Q:注解里的value()不需要知道value=“happy" ,name()是要指定name = "computer" ?比如下面两个注解
@Resource(name = "computer")
@Qualifier("chineseLanguage")
A:一般注解中如果只有一个值,比如@Qualifier注解中只有一个变量 String value() default ""; 则不需要指定变量名;如果有多个值,最好还是要指定变量名与值的键值对,想这样: @Resource(name = "computer");
而像@RequestMapping("/doPrepayment") 这种有多个值的,当不写变量名时,默认是value变量的值。
Q: Spring 的事件处理是单线程的?
Q:Spring事件处理一般在什么情况下使用?
Q:JdbcTemplate 类的实例是线程安全配置的.JdbcTemplate是怎么做到线程安全的?需要并发编程知识解释。
Q:JdbcTemplate 类框架的经典和最受欢迎的方法。这是管理所有数据库通信和异常处理的中央框架类。为什么这么说,是因为其他dao框架都是在Q:JdbcTemplate 上包装出来的么?
Q://无法获得到想要的实现类,还需要研究下像注解@Autowire是怎么把实现类注入到接口中的,或者订单是怎么通过serviceFactory来通过接口获取到实现类的//DeveloperDao developerDao = (DeveloperDao)context.getBean("DeveloperDao"); ?
Q:如下,为什么DriverManagerDataSource及其父类都没有driverClassName,这个属性在哪呢?
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/hello_spring"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
A:Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。有基于构造函数和基于 setter 方法的 两种DI方法。<property>标签就是基于setter方法。因此并不需要一定要有属性值driverClassName。
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
对应依赖注入的是这样的setter方法。
public void setDriverClassName(String driverClassName) {
}
Q:EJBs 需要一个应用程序服务器,但 Spring 事务管理可以在不需要应用程序服务器的情况下实现。应用程序服务器是指一个专门的事务管理系统么?
Q:如果一个方法被注解和配置事务扫描扫到执行事务怎么样?
Q:这里只展示了aop面向切面的事务配置,注解事务呢,如何配置?
Q:Controller类的方法上的参数比如ModelMap model 里的数据是怎么传输的呢?记得好像是键值对映射上了就可以获取和设置值?
Q:新下载的tomcat 8 使用时控制台输出乱码?
纪实
第一个hello world 项目实现。
首先通过maven创建一个maven-archetype-webapp 项目。
创建maven项目约定的项目结构文件夹。
创建一个配置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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<!--<context:component-scan base-package="com"/>-->
<!--<context:annotation-config/>-->
<bean id="message" class="com.self.Message">
<property name="msg" value="hello lairf"></property>
</bean>
</beans>
//如果是要通过扫描来注入bean,则要加个@Component注解
//@Component
public class Message {
private Integer code;
private String msg;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
public class MainApp {
public static void main(String[] args) {
//获得容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring/appcontext-core.xml");
Message message = (Message)context.getBean("message");
String msg = message.getMsg();
System.out.println("================================"+msg);
}
}
配置中心存储架构
redis + git
缓存 + 版本控制
网友评论