JavaEE

JavaWeb开发之Spring

2018-05-03  本文已影响13人  平安喜乐698
目录

1. 框架简介
    Spring是一个开源的Java框架。
    最初是由 Rod Johnson 编写,于 2003 年 6 月首次在 Apache 2.0 许可下发布。

Spring框架如下:
Spring框架
1.核心容器
由 Beans、Core核心、Context上下文、SpEL表达式语言 4个模块组成
    Beans模块
        提供 BeanFactory,它是一个工厂模式的复杂实现。
    Core核心模块
        提供了框架的基本组成部分(包括 IoC 和依赖注入功能)。
    上下文模块
        建立在由核心和 Beans 模块提供的坚实基础上,它是访问定义和配置的任何对象的媒介。ApplicationContext 接口是上下文模块的重点。
    表达式语言模块
        表达式语言。

2.数据访问/集成
由 JDBC,ORM,OXM,JMS 和事务处理模块 组成
    JDBC 模块
        提供了JDBC 抽象层(删除冗余的 JDBC 相关编码)。
    ORM 模块
        为流行的对象关系映射 API(包括 JPA,JDO,Hibernate 和 iBatis)提供了集成层。
    OXM 模块
        提供了抽象层,它支持对 JAXB,Castor,XMLBeans,JiBX 和 XStream 的对象/XML 映射实现。
     JMS 模块(Java 消息服务) 
        包含生产和消费的信息的功能。
    事务模块
        为实现特殊接口的类及所有的 POJO 支持编程式和声明式事务管理。

3.Web
由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成
    Web 模块
        提供了基本的面向 web 的集成功能,例如多个文件上传的功能和使用 servlet 监听器和面向 web 应用程序的上下文来初始化 IoC 容器。
    Web-MVC 模块
        包含 Spring 的模型-视图-控制器(MVC),实现了 web 应用程序。
    Web-Socket 模块
        为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。
    Web-Portlet 模块
        提供了在 portlet 环境中实现 MVC,并且反映了 Web-Servlet 模块的功能。

4.其他
AOP,Aspects,Instrumentation,Web 和测试模块
    AOP 模块
        提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,它实现了应该分离的功能。
    Aspects 模块
        提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。
    Instrumentation 模块
        在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。
    Messaging 模块
        为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。
    测试模块
        支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。

下载最新Spring框架二进制文件

最新Spring框架文件夹
jar说明

spring-core.jar(必须)
    这个jar 文件包含Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心。外部依赖Commons Logging, (Log4J)。

spring-beans.jar(必须)
    这 个jar 文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean 以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI 支持,引入spring-core.jar 及spring-beans.jar 文件就可以了。外部依赖spring-core,(CGLIB)。

spring-context.jar(必须)
    这个jar 文件在基础IOC功能上为Spring 核心提供了大量扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。外部依赖spring-beans, (spring-aop)。

spring-aop.jar(必须)
    这个jar 文件包含在应用中使用Spring 的AOP 特性时所需的类和源码级元数据支持。使用基于AOP 的Spring特性,如声明型事务管理(Declarative Transaction Management),也要在应用里包含这个jar包。外部依赖spring-core, (spring-beans,AOP Alliance, CGLIB,Commons Attributes)。

spring-jdbc.jar(必须) 
    这个jar 文件包含对Spring 对JDBC 数据访问进行封装的所有类。外部依赖spring-beans,spring-dao。

spring-web.jar(必须) 
    这个jar 文件包含Web 应用开发时,用到Spring 框架时所需的核心类,包括自动载入Web Application Context 特性的类、Struts 与JSF 集成类、文件上传的支持类、Filter 类和大量工具辅助类。外部依赖spring-context, Servlet API, (JSP API, JSTL, Commons FileUpload, COS)。

spring-webmvc.jar 
    这个jar 文件包含Spring MVC 框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、XSLT相关类。包括框架的Servlets,Web MVC框架,控制器和视图支持。当然,如果你的应用使用了独立的MVC 框架,则无需这个JAR 文件里的任何类。外部依赖spring-web, (spring-support,Tiles,iText,POI)。

spring-aspects.jar 
    提供对AspectJ的支持,以便可以方便的将面向方面的功能集成进IDE中,比如Eclipse AJDT。

spring-context-support.jar
    Spring context的扩展支持,用于MVC方面。

spring-expression.jar
    Spring表达式语言。

spring-instrument.jar
    Spring对服务器的代理接口

spring-instrument-tomcat.jar
    Spring对tomcat连接池的集成

spring-jms.jar
    为简化jms api的使用而做的简单封装。外部依赖spring-beans,spring-dao,JMS API。

spring-orm.jar
    整合第三方的orm实现,如hibernate,ibatis,jdo以及spring 的jpa实现

spring-oxm.jar
    Spring对于object/xml映射的支持,可以让JAVA与XML之间来回切换

spring-messaging.jar:

spring-test.jar
    对JUNIT等测试框架的简单封装

spring-tx.jar
    为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。

spring-webmvc-portlet.jar
    Spring MVC的增强

spring-websocket.jar:
  1. Java项目(Hello World)
MyEclipse项目栏右击新建Java项目 | 点击项目右键 | Build Path | Config Build Path | Libraries | add External JARs | 把spring文件夹下lib中的jar全部导入
新建包com.sst.cx
新建HelloWorld.java文件

package com.sst.cx;
public class HelloWorld {
       private String message;
       public void setMessage(String message){
          this.message  = message;
       }
       public void getMessage(){
          System.out.println("Your Message : " + message);
       }
}

新建Main.java
package com.sst.cx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
       public static void main(String[] args) {
              // 获取配置文件
              ApplicationContext context = 
                     new ClassPathXmlApplicationContext("Beans.xml");
              // 获取配置文件中的类实例,并调用方法
              HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
              obj.getMessage();
           }
}
src下新建Beans.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.sst.cx.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
Main.java文件右键 | Run As Java Application 

控制台输出
    Your Message : Hello World!
添加Spring jar 项目
2. 概念
  1. Spring IoC容器
Spring IoC容器
Spring IoC容器(Spring框架的核心)
    负责创建并管理对象。配置元数据3种方式:XML、Java注释、Java 代码。
    Spring 容器使用(DI)来管理组成一个应用程序的组件。这些对象被称为 Spring Beans。

分两种:
    1.Spring BeanFactory 容器
        最简单的容器,主要功能为依赖注入(DI) 提供了基本的支持。
        由org.springframework.beans.factory.BeanFactory 接口定义。
        BeanFactory 相关的接口(BeanFactoryAware,InitializingBean,DisposableBean)向后兼容其他三方框架
        移动设备或基于applet 的应用当中(资源宝贵), 优先选择BeanFactory
    2.Spring ApplicationContext 容器(推荐)
        BeanFactory容器的所有功能 + 更多实用功能。
        由 org.springframework.context.ApplicationContext 接口定义。

Spring BeanFactory 容器

替换上述Main.java文件

package com.sst.cx;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;


public class Main {
       public static void main(String[] args) {
           BeanFactory factory = new ClassPathXmlApplicationContext("Beans.xml");  
           HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");   
           obj.getMessage();
       }
}

Spring ApplicationContext 容器

替换上述Main.java文件

package com.sst.cx;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;


public class Main {
       public static void main(String[] args) {
           
           // 生成和初始化所有的对象(xml必须为完整路径 /代表项目根目录)
           ApplicationContext context = new FileSystemXmlApplicationContext
                    ("/src/Beans.xml");
/*
3种:
1.FileSystemXmlApplicationContext
    该容器从 XML 文件中加载已被定义的 bean。 XML 文件的完整路径
2.ClassPathXmlApplicationContext
    该容器从 XML 文件中加载已被定义的 bean。不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
3.WebXmlApplicationContext
    该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
*/
           HelloWorld obj = (HelloWorld) context.getBean("helloWorld");  
           obj.getMessage();   
           // 容器销毁
           context.registerShutdownHook();
       }
}
  1. Bean

配置(3种方式)

    基于 XML的配置
    基于 注解的配置
    基于 Java的配置

2.1 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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- 简单示例 -->
   <bean id="唯一标识用于实例化" class="包路径.类名">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- 懒加载 -->
   <bean id="..." class="..." lazy-init="true">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- 初始化方法 -->
   <bean id="..." class="..." init-method="...">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- 销毁方法 -->
   <bean id="..." class="..." destroy-method="...">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

<!--
可配置的bean属性

  class 
    指定类,包路径.类名(强制性)
  name  / id
    指定唯一标识符(XML可使用 ID 和/或 name)
  scope 
    指定作用域
  constructor-arg   
    用来注入依赖关系
  properties    
    用来注入依赖关系
  autowiring mode   
    用来注入依赖关系
  lazy-initialization mode  
    延迟初始化bean(第一次被请求时才去创建一个实例,而不是在启动时创建)
  initialization 方法 
    在 bean 的所有必需的属性被容器设置之后,调用回调方法。
  destruction 方法    
    当包含该 bean的容器被销毁时调用
-->
<!--
scope值(5种)

singleton   
    单例(默认),使用同一个实例
prototype   
    每次均新建实例
// ---------以下只在web-aware Spring ApplicationContext 的上下文中有效 ---------
request 
    限制为 HTTP 请求
session 
    限制为 HTTP 会话
global-session  
    限制为全局 HTTP 会话
-->

</beans>

补充

生命周期
  initialization 方法 、  destruction 方法   

方式1:全局指定
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
    default-init-method="init" 
    default-destroy-method="destroy">

方式2:单个类指定
<bean id="exampleBean" 
         class="examples.ExampleBean" init-method="init" destroy-method="destroy"/>

public class HelloWorld {
   private String message;

   public void setMessage(String message){
      this.message  = message;
   }
   public void getMessage(){
      System.out.println("Your Message : " + message);
   }
   public void init(){
      System.out.println("Bean is going through init.");
   }
   public void destroy(){
      System.out.println("Bean will destroy now.");
   }
}
BeanPostProcessor后置处理器
    ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,在其他bean初始化前后调用


InitHelloWorld.java

package com.sst.cx;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class InitHelloWorld implements BeanPostProcessor {
    
     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
          System.out.println("BeforeInitialization : " + beanName);
          return bean;  // you can return any other object as well
       }
       public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
          System.out.println("AfterInitialization : " + beanName);
          return bean;  // you can return any other object as well
       }
}
继承
    与 Java 类的继承无关,但概念是一样的

   <bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
      <property name="message1" value="Hello World!"/>
      <property name="message2" value="Hello Second World!"/>
   </bean>
   <bean id="helloIndia" class="com.sst.cx.HelloIndia" parent="helloWorld">
      <property name="message1" value="Hello India!"/>
      <property name="message3" value="Namaste India!"/>
   </bean>

父类可定义为抽象模版
   <bean id="beanTeamplate" abstract="true">
      <property name="message1" value="Hello World!"/>
      <property name="message2" value="Hello Second World!"/>
      <property name="message3" value="Namaste India!"/>
   </bean>
从Spring 2.5开始就可以使用(相关类,方法或字段声明的)注解来配置依赖注入。
注解注入在XML注入之前进行,会被覆写。
注解默认不打开,需在配置文件中打开
 <beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
 <context:annotation-config/>
 <!-- bean definitions go here -->
 </beans>

2.2 基于注解的配置

@Required注解
   用于setter方法上。相应的bean属性在配置时必须放在 XML 配置文件中,否则BeanInitializationException异常。
   @Required
   public void setName(String name) {
       this.name = name;
   }
   <bean id="helloWorld" class="com.sst.cx.HelloWorld">
       <property name="name" value="cx"/>
   </bean>


@Autowired注解
   用于setter方法上、非setter方法、构造函数、属性。

   用在setter方法(会自动使用byType,不用设置property)
   @Autowired
   public void setHelloB(String helloB) {
       this.helloB = helloB;
   }

   用在属性(不用写set方法,会自动使用byType,不用设置property)
   @Autowired
   String helloB;

   用在构造函数上(会自动使用byType,不用设置property)
   @Autowired
   public HelloWorld(String helloB) {
       this.helloB = helloB;
   }

   @Autowired(required=false)  设为非必须(默认是必须的)


@Qualifier注解
   当有多个相同类型的bean, @Autowired + @Qualifier

   @Autowired
   @Qualifier("helloB1")
   private HelloB helloB;

   <bean id="HelloB1" class="com.sst.cx.HelloB"></bean>
   <bean id="HelloB2" class="com.sst.cx.HelloB"></bean>


JSR-250 Annotations注解
   基于 JSR-250 注释,包括 @PostConstruct, @PreDestroy 和 @Resource 注释

   @PostConstruct 和 @PreDestroy 注释,初始化方法,销毁方法
   @PostConstruct
   public void init(){
       System.out.println("Bean is going through init.");
   }
   @PreDestroy
   public void destroy(){
       System.out.println("Bean will destroy now.");
   }

   <bean id="helloWorld" class="com.sst.cx.HelloWorld" init-method="init" destroy-method="destroy">
       <property name="message" value="Hello World!"/>
   </bean>

   @Resource 注释        by-name
   @Resource(name= "helloB")   默认为属性名
   public void setHelloB(String helloB) {
       this.helloB = helloB;
   }
   <bean id="helloB" class="com.sst.cx.HelloB"></bean>
 注入 Bean 的依赖性
 
    @Configuration
    public class AppConfig {
        @Bean
        public Foo foo() {
            return new Foo(bar());  // 依赖注入
        }
        @Bean
        public Bar bar() {
            return new Bar();
        }
    }

2.3 基于Java的配置(不用配置 XML )

 @Configuration 表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源
 @Bean 表示返回对象该被注册为在Spring应用程序上下文中的bean(方法名作id,返回类型作类)
 
 
 @Configuration
 public class HelloWorld{
    @Bean
    public HelloB helloB(){
        return new HelloB();
    }
 }
 等同于如下
 <beans>
    <bean id="helloB" class="com.sst.cx.HelloB"></bean>
 </beans>
 

 1
 public static void main(String[] args) {
 ApplicationContext ctx =
 new AnnotationConfigApplicationContext(HelloWorldConfig.class);
 HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
 helloWorld.setMessage("Hello World!");
 helloWorld.getMessage();
 }
 
 2
 public static void main(String[] args) {
 AnnotationConfigApplicationContext ctx =
 new AnnotationConfigApplicationContext();
 ctx.register(AppConfig.class, OtherConfig.class);
 ctx.register(AdditionalConfig.class);
 ctx.refresh();
 MyService myService = ctx.getBean(MyService.class);
 myService.doStuff();
 }
    @Bean(initMethod = "init", destroyMethod = "cleanup" )
    public HelloB helloB(){ // HelloB类中有init、cleanup方法
        return new HelloB();
    }
    @Bean
    @Scope("prototype")
    public HelloB helloB(){ // 作用范围,默认范围是单实例
        return new HelloB();
    }
 @Import 注解
    从另一个配置类中加载@Bean定义
 
 
 @Configuration
 public class ConfigA {
    @Bean
    public A a() {
        return new A();
    }
 }
 
 @Configuration
 @Import(ConfigA.class)
 public class ConfigB {
    @Bean
    public B a() {
        return new A();
    }
 }
 
 public static void main(String[] args) {
    ApplicationContext ctx =
 new AnnotationConfigApplicationContext(ConfigB.class);
    // now both beans A and B will be available...
    A a = ctx.getBean(A.class);
    B b = ctx.getBean(B.class);
 }
  1. 依赖注入

3.1 注入方式

    基于构造函数的依赖注入
    基于set函数的依赖注入

基于构造函数的依赖注入

HelloWorld.java

package com.sst.cx;
public class HelloWorld {
       private HelloB helloB;

       public HelloWorld(HelloB helloB) {
              System.out.println("hello b" );
              this.helloB = helloB;   
       }
       public void methodB(){
              helloB.methodB(); 
       } 
}


HelloB.java

package com.sst.cx;
public class HelloB {
       public HelloB(){
              System.out.println("helloB init" );   
       }
       
       public void methodB(){
              System.out.println("helloB" );   
       }  
}


Beans.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.sst.cx.HelloWorld">
      <constructor-arg ref="helloB"/>
   </bean>

   <bean id="helloB" class="com.sst.cx.HelloB">
       
   </bean>
</beans>
参数顺序

   <bean id="exampleBean" class="examples.ExampleBean">
      <constructor-arg type="int" value="2001"/>
      <constructor-arg type="java.lang.String" value="Zara"/>
   </bean>

或

   <bean id="exampleBean" class="examples.ExampleBean">
      <constructor-arg index="0" value="2001"/>
      <constructor-arg index="1" value="Zara"/>
   </bean>

基于set函数的依赖注入

HelloWorld.java

package com.sst.cx;
public class HelloWorld {
       private HelloB helloB;
       private String name;
       public void setHelloB(HelloB helloB) {
              System.out.println("hello b" );
              this.helloB = helloB;   
       }
       public void methodB(){
              helloB.methodB(); 
       } 
}


HelloB.java

package com.sst.cx;
public class HelloB {
       public HelloB(){
              System.out.println("helloB init" );   
       }
       
       public void methodB(){
              System.out.println("helloB" );   
       }  
}


Beans.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.sst.cx.HelloWorld">
      <property name="name" value="Zhang San"/>
      <property name="helloB" ref="helloBB"/>
   </bean>

   <bean id="helloBB" class="com.sst.cx.HelloB">
       
   </bean>
</beans>
简写
     <bean id="helloWorld" class="com.sst.cx.HelloWorld" p:name="Zhang San"
      p:spouse-ref="helloBB"/>
内部 Beans(属性为类类型)

   <bean id="helloWorld" class="com.sst.cx.HelloWorld">
      <property name="helloB">
         <bean id="helloBB" class="com.sst.cx.HelloB"/>
       </property>
   </bean>

3.2 注入集合

4种

<list>
    注入一列值,允许重复
<set>   
    注入一列值,但不能重复。
<map>   、  <props>  
    注入名称-值对的集合,其中名称和值可以是任何类型。
HelloWorld.java

package com.sst.cx;
import java.util.*;
public class HelloWorld {
       List addressList;
       Set  addressSet;
       Map  addressMap;
       Properties addressProp;
    public List getAddressList() {
        System.out.println("List Elements :"  + addressList);
        return addressList;
    }
    public void setAddressList(List addressList) {
        this.addressList = addressList;
    }
    public Set getAddressSet() {
        System.out.println("Set Elements :"  + addressSet);
        return addressSet;
    }
    public void setAddressSet(Set addressSet) {
        this.addressSet = addressSet;
    }
    public Map getAddressMap() {
        System.out.println("Map Elements :"  + addressMap);
        return addressMap;
    }
    public void setAddressMap(Map addressMap) {
        this.addressMap = addressMap;
    }
    public Properties getAddressProp() {
        System.out.println("Property Elements :"  + addressProp);
        return addressProp;
    }
    public void setAddressProp(Properties addressProp) {
        this.addressProp = addressProp;
    }
}



Beans.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="com.sst.cx.HelloWorld">
         <!-- results in a setAddressList(java.util.List) call -->
      <property name="addressList">
         <list>
            <value>A</value>
            <value>B</value>
            <value>C</value>
            <value>C</value>
         </list>
      </property>

      <!-- results in a setAddressSet(java.util.Set) call -->
      <property name="addressSet">
         <set>
            <value>A</value>
            <value>B</value>
            <value>C</value>
            <value>C</value>
        </set>
      </property>

      <!-- results in a setAddressMap(java.util.Map) call -->
      <property name="addressMap">
         <map>
            <entry key="1" value="A"/>
            <entry key="2" value="B"/>
            <entry key="3" value="C"/>
            <entry key="4" value="C"/>
         </map>
      </property>

      <!-- results in a setAddressProp(java.util.Properties) call -->
      <property name="addressProp">
         <props>
            <prop key="one">A</prop>
            <prop key="two">B</prop>
            <prop key="three">C</prop>
            <prop key="four">C</prop>
         </props>
      </property>
   </bean>
</beans>




Main.java

package com.sst.cx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
       public static void main(String[] args) {
           
               ApplicationContext context = 
                      new ClassPathXmlApplicationContext("Beans.xml");
               HelloWorld jc=(HelloWorld)context.getBean("helloWorld");
               jc.getAddressList();
               jc.getAddressSet();
               jc.getAddressMap();
               jc.getAddressProp();
       }
}
注入引用
      <property name="addressSet 或 addressList">
         <list>
           <value>A</value>
            <ref bean="B"/>
         </list>
      </property>

      <property name="addressMap">
         <map>
            <entry key="one" value="A"/>
            <entry key ="two" value-ref="B"/>
         </map>
      </property>
  1. Bean自动装配
Spring容器可以在不使用<constructor-arg>和<property>情况下,自动装配属性(包括与其他bean联系),简化XML


使用<bean>的autowire
    no
        默认,没有自动装配
    byName
        由属性名自动装配。将尝试属性与在配置文件中被定义为相同名称的beans的进行连接。
    byType
        由属性数据类型自动装配。如果存在多个对应的bean则异常。
    constructor
        类似于byType,但该类型适用于构造函数参数类型。如果不存在对应的构造函数参数类型的bean则异常。
    autodetect
        首先尝试 constructor ,如果它不执行则尝试 byType 。
    可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合。
 

自动装配的局限性
    当自动装配始终在同一个项目中使用时,它的效果最好。
    重写的可能性
        你可以使用总是重写自动装配的 <constructor-arg>和 <property> 设置来指定依赖关系。
    原始数据类型
        你不能自动装配所谓的简单类型包括基本类型,字符串和类。
    混乱的本质
        自动装配不如显式装配精确,所以如果可能的话尽可能使用显式装配。 
 byName
    由属性名自动装配,仍然可以使用 <property> 标签连接其余的属性。
    例:在配置文件中,一个bean设置为自动装配byName,并且它包含helloB属性(即,它有一个 setHelloB(...) 方法),那么 Spring 就会查找定义名为 helloB 的 bean,并且用它来设置这个属性。

    <bean id="helloWorld" class="com.sst.cx.HelloWorld" autowire="byName">
    </bean>
    <bean id="helloB" class="com.sst.cx.HelloB">
    </bean>
 byType
    由属性数据类型自动装配。如果存在多个对应的bean则异常。仍然可以使用 <property> 标签连接其余的属性。
    例:在配置文件中,一个bean设置为自动装配byType,并且它包含 HelloB类型的 helloB 属性,那么 Spring 就会查找定义名为 HelloB 的 bean,并且用它来设置这个属性。

 
    <bean id="helloWorld" class="com.sst.cx.HelloWorld" autowire="byType">
    </bean>
    <bean id="HelloB" class="com.sst.cx.HelloB">
    </bean>
 constructor
    类似于byType,但该类型适用于构造函数参数类型。仍然可以使用 <constructor-arg> 标签连接其余属性。
    例如,在配置文件中,一个bean定义设置为通过构造函数自动装配,而且它有一个带有 HelloB 类型的参数之一的构造函数,那么 Spring 就会查找定义名为 HelloB 的 bean,并用它来设置构造函数的参数。
 
    <bean id="helloWorld" class="com.sst.cx.HelloWorld" autowire="constructor">
    </bean>
    <bean id="HelloB" class="com.sst.cx.HelloB">
    </bean>
  1. 事件
    ApplicationContext负责管理beans的整个生命周期,会触发一系列事件。
    任何一个bean实现了ApplicationListener,则每次ApplicationContext 触发ApplicationEvent事件,都会通知那个bean。(相当于加入到通知者中心数组)
    Spring的事件处理是单线程的,一个事件被触发后,进程会被阻塞直至所有接收者得到该消息。
 

事件如下:
 ContextRefreshedEvent
    ApplicationContext被初始化或刷新(context.refresh(); )时,触发该事件。
 ContextStartedEvent  上下文启动
    context.start(); 触发该事件。
    操作数据库,或者重启任何停止的应用程序。
 ContextStoppedEvent  上下文停止
    context.stop();触发该事件。
    做清理工作。
 ContextClosedEvent
    context.close(); 触发该事件。
    不能被刷新或重启。
 RequestHandledEvent
    web-specific 事件,告诉所有bean ,HTTP 请求已经被处理。

例:监听上下文事件

cStopEventHandler.java

package com.sst.cx;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;

public class CStopEventHandler implements ApplicationListener<ContextStoppedEvent>{
       public void onApplicationEvent(ContextStoppedEvent event) {
              System.out.println("ContextStoppedEvent Received");
           }
}
ContextStartedEvent.java

package com.sst.cx;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;

public class CStartEventHandler implements ApplicationListener<ContextStartedEvent>{
       public void onApplicationEvent(ContextStartedEvent event) {
              System.out.println("ContextStartedEvent Received");
       }
}
Beans.xml

<bean id="helloWorld" class="com.sst.cx.HelloWorld"></bean>
<bean id="cStartEventHandler" class="com.sst.cx.CStartEventHandler"></bean>
<bean id="cStopEventHandler" class="com.sst.cx.CStopEventHandler"></bean>
Main.java

package com.sst.cx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
       public static void main(String[] args) {
           
           ConfigurableApplicationContext context = 
                      new ClassPathXmlApplicationContext("Beans.xml");                    
           context.start();
           HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
           obj.getMessage();
           context.stop();
       }
}

5.1 自定义事件

CustomEvent.java   事件类

package com.sst.cx;
import org.springframework.context.ApplicationEvent;

public class CustomEvent extends ApplicationEvent{
    public CustomEvent(Object source) {
          super(source);   
    }
    public String toString(){
        return "My Custom Event";   
    }
}
CustomEventPublisher.java 发布事件类

package com.sst.cx;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;

public class CustomEventPublisher implements ApplicationEventPublisherAware {
    
       private ApplicationEventPublisher publisher;
       public void setApplicationEventPublisher
                  (ApplicationEventPublisher publisher){
          this.publisher = publisher;
       }
       public void publish() {
          CustomEvent ce = new CustomEvent(this);
          publisher.publishEvent(ce);
       }
}
CustomEventHandler.java   事件处理类

package com.sst.cx;
import org.springframework.context.ApplicationListener;

public class CustomEventHandler implements ApplicationListener<CustomEvent>{
       public void onApplicationEvent(CustomEvent event) {
              System.out.println(event.toString());   
       }
}
Beans.xml

    <bean id="customEventHandler" class="com.sst.cx.CustomEventHandler">
    </bean>
    <bean id="customEventPublisher" class="com.sst.cx.CustomEventPublisher">
    </bean>
Main.java

package com.sst.cx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
       public static void main(String[] args) {
           
              ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");          
              CustomEventPublisher cvp = (CustomEventPublisher) context.getBean("customEventPublisher");
              cvp.publish();  
              cvp.publish();
       }
}
  1. AOP
    Spring框架有一个关键组件是面向方面的编程(AOP)框架。
    面向方面的编程需要把程序逻辑分解成不同的部分称为所谓的关注点。跨一个应用程序的多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。

用于监听方法执行

AOP 术语(不特定于 Spring)

Aspect  
    一个模块具有一组提供横切需求的 APIs。
Join point  
    一个点,使用 Spring AOP 框架。
Advice  
    行动之前或之后执行的方法。这是在程序执行期间通过 Spring AOP 框架实际被调用的代码。
Pointcut    
    这是一组一个或多个连接点,通知应该被执行。
    你可以使用表达式或模式指定切入点正如我们将在 AOP 的例子中看到的。
Introduction    
    引用允许你添加新方法或属性到现有的类中。
Target object   
    被一个或者多个方面所通知的对象,这个对象永远是一个被代理对象。也称为被通知对象。
Weaving Weaving 
    把方面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时,类加载时和运行时完成。

通知的类型(5)

前置通知    
    在一个方法执行之前,执行通知。
后置通知    
    在一个方法执行之后,不考虑其结果,执行通知。
返回后通知   
    在一个方法执行之后,只有在方法成功完成时,才能执行通知。
抛出异常后通知 
    在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知    
    在建议方法调用之前和之后,执行通知。

实现自定义方面

方式1、@AspectJ annotation style 
    @AspectJ 引用一种声明方面的风格作为带有 Java 5 注释的常规 Java 类注释
方式2、XML
    使用常规类以及基于配置的 XML 来实现的

6.1 基于 AOP 的 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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <!-- bean definition & AOP specific configuration -->

</beans>
需导入spring中的如下库文件

aspectjrt.jar
aspectjweaver.jar
aspectj.jar
aopalliance.jar

声明一个 aspect

XML中

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

声明一个切入点

XML中

定义了一个名为 “businessService” 的切入点,该切入点将与 com.tutorialspoint 包下的 Student 类中的 getName() 方法相匹配
<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
   <aop:pointcut id="businessService"
      expression="execution(* com.tutorialspoint.Student.getName(..))"/>
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

声明建议

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
      <aop:pointcut id="businessService"
         expression="execution(* com.xyz.myapp.service.*.*(..))"/>
      <!-- a before advice definition -->
      <aop:before pointcut-ref="businessService" 
         method="doRequiredTask"/>
      <!-- an after advice definition -->
      <aop:after pointcut-ref="businessService" 
         method="doRequiredTask"/>
      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning pointcut-ref="businessService"
         returning="retVal"
         method="doRequiredTask"/>
      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing pointcut-ref="businessService"
         throwing="ex"
         method="doRequiredTask"/>
      <!-- an around advice definition -->
      <aop:around pointcut-ref="businessService" 
         method="doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

Main.java

package com.sst.cx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Main {
       private static ConfigurableApplicationContext context;

    public static void main(String[] args) {
           
           context = new ClassPathXmlApplicationContext("Beans.xml");          
               Student student = (Student) context.getBean("hello");
               student.getName();
               student.getAge();      
               student.printThrowException();
       }
}
LogT.java

package com.sst.cx;
public class LogT {
    
       /** 
        * This is the method which I would like to execute
        * before a selected method execution.
        */
       public void beforeAdvice(){
          System.out.println("Going to setup student profile.");
       }
       /** 
        * This is the method which I would like to execute
        * after a selected method execution.
        */
       public void afterAdvice(){
          System.out.println("Student profile has been setup.");
       }
       /** 
        * This is the method which I would like to execute
        * when any method returns.
        */
       public void afterReturningAdvice(Object retVal){
          System.out.println("Returning:" + retVal.toString() );
       }
       /**
        * This is the method which I would like to execute
        * if there is an exception raised.
        */
       public void afterThrowingAdvice(IllegalArgumentException ex){
          System.out.println("There has been an exception: " + ex.toString());   
       }  
}
Student.java

package com.sst.cx;

public class Student {
       private Integer age;
       private String name;
       public void setAge(Integer age) {
          this.age = age;
       }
       public Integer getAge() {
          System.out.println("Age : " + age );
          return age;
       }
       public void setName(String name) {
          this.name = name;
       }
       public String getName() {
          System.out.println("Name : " + name );
          return name;
       }  
       public void printThrowException(){
           System.out.println("Exception raised");
           throw new IllegalArgumentException();
       }
}
Beans.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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    <!-- 切面类 -->  
    <bean id="logT" class="com.sst.cx.LogT"></bean>  
    
    <!-- AOP -->  
   <aop:config>
      <!-- 定义一个切入点表达式: 拦截哪些方法 --> 
      <aop:pointcut id="selectT" expression="execution(* com.sst.cx.*.*(..))"/>
      
      <aop:aspect ref="logT">
      <!-- 切面 -->  
         <aop:before pointcut-ref="selectT" method="beforeAdvice"/>
         <aop:after pointcut-ref="selectT" method="afterAdvice"/>
         <aop:after-returning pointcut-ref="selectT" returning="retVal" method="afterReturningAdvice"/>
         <aop:after-throwing method="afterThrowingAdvice" throwing="ex" pointcut-ref="selectT" />
      </aop:aspect>
      
   </aop:config>

   <!-- Definition for student bean -->
   <bean id="hello" class="com.sst.cx.Student">
      <property name="name"  value="zhangSan" />
      <property name="age"  value="11"/>      
   </bean>
</beans>

6.2 基于 AOP 的 @AspectJ

XML+

<aop:aspectj-autoproxy/>
  1. JDBC
JdbcTemplate类
    线程安全

除了spring文件夹下的lib还有mysql-connector-java.jar
Mac设置 | 启动mysql
CREATE TABLE Student(
   ID   INT NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(20) NOT NULL,
   AGE  INT NOT NULL,
   PRIMARY KEY (ID)
);
// sql
String SQL = "select count(*) from Student";
// 查询int型
int rowCount = jdbcTemplateObject.queryForInt( SQL );
// 查询lang型
long rowCount = jdbcTemplateObject.queryForLong( SQL );

// 带占位符查询---int型
String SQL = "select age from Student where id = ?";
int age = jdbcTemplateObject.queryForInt(SQL, new Object[]{10});

// 带占位符查询---String
String SQL = "select name from Student where id = ?";
String name = jdbcTemplateObject.queryForObject(SQL, new Object[]{10}, String.class);

// 查询并返回一个对象
String SQL = "select * from Student where id = ?";
Student student = jdbcTemplateObject.queryForObject(SQL, 
                  new Object[]{10}, new StudentMapper());
public class StudentMapper implements RowMapper<Student> {
   public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
      Student student = new Student();
      student.setID(rs.getInt("id"));
      student.setName(rs.getString("name"));
      student.setAge(rs.getInt("age"));
      return student;
   }
}

// 查询并返回多个对象
String SQL = "select * from Student";
List<Student> students = jdbcTemplateObject.query(SQL,
                         new StudentMapper());
public class StudentMapper implements RowMapper<Student> {
   public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
      Student student = new Student();
      student.setID(rs.getInt("id"));
      student.setName(rs.getString("name"));
      student.setAge(rs.getInt("age"));
      return student;
   }
}

// 新增
String SQL = "insert into Student (name, age) values (?, ?)";
jdbcTemplateObject.update( SQL, new Object[]{"Zara", 11} );

// 更新
String SQL = "update Student set name = ? where id = ?";
jdbcTemplateObject.update( SQL, new Object[]{"Zara", 10} );

// 删除
String SQL = "delete Student where id = ?";
jdbcTemplateObject.update( SQL, new Object[]{20} );
// 另一种方式执行sql
String SQL = "CREATE TABLE Student( " +
   "ID   INT NOT NULL AUTO_INCREMENT, " +
   "NAME VARCHAR(20) NOT NULL, " +
   "AGE  INT NOT NULL, " +
   "PRIMARY KEY (ID));"
jdbcTemplateObject.execute( SQL );
<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/TEST"/>
   <property name="username" value="root"/>
   <property name="password" value="password"/>
</bean>

7.1 例

Test数据库下新建Student表

CREATE TABLE Student(
   ID   INT NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(20) NOT NULL,
   AGE  INT NOT NULL,
   PRIMARY KEY (ID)
);
Beans.xml(src下)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">

   <!-- Definition for studentJDBCTemplate bean -->
   <bean id="studentJDBCTemplate" 
      class="com.sst.cx.StudentJDBCTemplate">
      <property name="dataSource"  ref="dataSource" />    
   </bean>


    <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/Test"/>
        <property name="username" value="root"/>
        <property name="password" value="数据库密码"/>
    </bean>
</beans>
StudentDAO.java

package com.sst.cx;
import java.util.List;
import javax.sql.DataSource;

public interface StudentDAO {

       /** 
        * This is the method to be used to initialize
        * database resources ie. connection.
        */
       public void setDataSource(DataSource ds);
       /** 
        * This is the method to be used to create
        * a record in the Student table.
        */
       public void create(String name, Integer age);
       /** 
        * This is the method to be used to list down
        * a record from the Student table corresponding
        * to a passed student id.
        */
       public Student getStudent(Integer id);
       /** 
        * This is the method to be used to list down
        * all the records from the Student table.
        */
       public List<Student> listStudents();
       /** 
        * This is the method to be used to delete
        * a record from the Student table corresponding
        * to a passed student id.
        */
       public void delete(Integer id);
       /** 
        * This is the method to be used to update
        * a record into the Student table.
        */
       public void update(Integer id, Integer age);
}
StudentJDBCTemplate.java

package com.sst.cx;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;


public class StudentJDBCTemplate implements StudentDAO{
       private DataSource dataSource;
       private JdbcTemplate jdbcTemplateObject; 
       public void setDataSource(DataSource dataSource) {
          this.dataSource = dataSource;
          this.jdbcTemplateObject = new JdbcTemplate(dataSource);
       }
       public void create(String name, Integer age) {
          String SQL = "insert into Student (name, age) values (?, ?)";     
          jdbcTemplateObject.update( SQL, name, age);
          System.out.println("Created Record Name = " + name + " Age = " + age);
          return;
       }
       public Student getStudent(Integer id) {
          String SQL = "select * from Student where id = ?";
          Student student = jdbcTemplateObject.queryForObject(SQL, 
                            new Object[]{id}, new StudentMapper());
          return student;
       }
       public List<Student> listStudents() {
          String SQL = "select * from Student";
          List <Student> students = jdbcTemplateObject.query(SQL, 
                                    new StudentMapper());
          return students;
       }
       public void delete(Integer id){
          String SQL = "delete from Student where id = ?";
          jdbcTemplateObject.update(SQL, id);
          System.out.println("Deleted Record with ID = " + id );
          return;
       }
       public void update(Integer id, Integer age){
          String SQL = "update Student set age = ? where id = ?";
          jdbcTemplateObject.update(SQL, age, id);
          System.out.println("Updated Record with ID = " + id );
          return;
       }
}
StudentMapper.java

package com.sst.cx;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;

public class StudentMapper implements RowMapper<Student>{

    @Override
    public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
          Student student = new Student();
          student.setId(rs.getInt("id"));
          student.setName(rs.getString("name"));
          student.setAge(rs.getInt("age"));
          return student;
    }
    
}
Student.java

package com.sst.cx;

public class Student {
       private Integer id;
       private Integer age;
       private String name;
       public void setAge(Integer age) {
          this.age = age;
       }
       public Integer getAge() {
          System.out.println("Age : " + age);
          return age;
       }
       public void setName(String name) {
          this.name = name;
       }
       public String getName() {
          System.out.println("Name : " + name );
          return name;
       }  
       public void printThrowException(){
           System.out.println("Exception raised");
           throw new IllegalArgumentException();
       }
       public void setId(Integer id) {
           this.id = id;
       }
           
       public Integer getId() {
           return id;   
       }
}
Main.java

package com.sst.cx;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;

public class Main {

    public static void main(String[] args) {
           
         ApplicationContext context = 
                 new ClassPathXmlApplicationContext("Beans.xml");
          StudentJDBCTemplate studentJDBCTemplate = 
          (StudentJDBCTemplate)context.getBean("studentJDBCTemplate");    
          System.out.println("------Records Creation--------" );
          studentJDBCTemplate.create("Zara", 11);
          studentJDBCTemplate.create("Nuha", 2);
          studentJDBCTemplate.create("Ayan", 15);
          System.out.println("------Listing Multiple Records--------" );
          List<Student> students = studentJDBCTemplate.listStudents();
          for (Student record : students) {
             System.out.print("ID : " + record.getId() );
             System.out.print(", Name : " + record.getName() );
             System.out.println(", Age : " + record.getAge());
          }
          System.out.println("----Updating Record with ID = 2 -----" );
          studentJDBCTemplate.update(2, 20);
          System.out.println("----Listing Record with ID = 2 -----" );
          Student student = studentJDBCTemplate.getStudent(2);
          System.out.print("ID : " + student.getId() );
          System.out.print(", Name : " + student.getName() );
          System.out.println(", Age : " + student.getAge());      
       }
}

7.2 存储过程

StudentJDBCTemplate类可以被用于调用一个包含 IN 和 OUT 参数的存储过程。
数据库执行如下语句

DELIMITER $$
DROP PROCEDURE IF EXISTS `TEST`.`getRecord` $$
CREATE PROCEDURE `TEST`.`getRecord` (
IN in_id INTEGER,
OUT out_name VARCHAR(20),
OUT out_age  INTEGER)
BEGIN
   SELECT name, age
   INTO out_name, out_age
   FROM Student where id = in_id;
END $$
DELIMITER ;
替换上例中的StudentJDBCTemplate.java


package com.sst.cx;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;


public class StudentJDBCTemplate implements StudentDAO{
       private DataSource dataSource;
       private SimpleJdbcCall jdbcCall;
       public void setDataSource(DataSource dataSource) {
          this.dataSource = dataSource;
          this.jdbcCall =  new SimpleJdbcCall(dataSource).
                           withProcedureName("getRecord");
       }
       public void create(String name, Integer age) {
          JdbcTemplate jdbcTemplateObject = new JdbcTemplate(dataSource);
          String SQL = "insert into Student (name, age) values (?, ?)";
          jdbcTemplateObject.update( SQL, name, age);
          System.out.println("Created Record Name = " + name + " Age = " + age);
          return;
       }
       public Student getStudent(Integer id) {
          SqlParameterSource in = new MapSqlParameterSource().
                                  addValue("in_id", id);
          Map<String, Object> out = jdbcCall.execute(in);
          Student student = new Student();
          student.setId(id);
          student.setName((String) out.get("out_name"));
          student.setAge((Integer) out.get("out_age"));
          return student;
       }
       public List<Student> listStudents() {
          JdbcTemplate jdbcTemplateObject = new JdbcTemplate(dataSource);
          String SQL = "select * from Student";    
          List <Student> students = jdbcTemplateObject.query(SQL, 
                                          new StudentMapper());
          return students;
       }
    @Override
    public void delete(Integer id) {
        // TODO Auto-generated method stub
        
    }
    @Override
    public void update(Integer id, Integer age) {
        // TODO Auto-generated method stub
        
    }
}

7.3 事务

一个数据库事务要么完整地执行,要么完全不执行。
特性
    原子性:要么成功,要么失败。
    一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。
    隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。
    持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。
步骤
    1.使用 begin transaction 命令开始事务。
    2.使用 SQL 查询语句执行各种删除、更新或插入操作。
    3.如果所有的操作都成功,则执行提交操作,否则回滚所有操作。
局部事务
    是特定于一个单一的事务资源,如一个 JDBC 连接。
    局部事务管理在一个集中的计算环境中是有用的,该计算环境中应用程序组件和资源位于一个单位点,而事务管理只涉及到一个运行在一个单一机器中的本地数据管理器。局部事务更容易实现。
全局事务
    可以跨多个事务资源事务,如在一个分布式系统中的事务。
    全局事务管理需要在分布式计算环境中,所有的资源都分布在多个系统中。在这种情况下事务管理需要同时在局部和全局范围内进行。分布式或全局事务跨多个系统执行,它的执行需要全局事务管理系统和所有相关系统的局部数据管理人员之间的协调。
Spring 支持两种类型的事务管理
    编程式事务管理
        这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。
    声明式事务管理
        这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。
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;
}


TransactionDefinition 是在 Spring 中事务支持的核心接口,它的定义如下:
public interface TransactionDefinition {
   // 该方法返回传播行为。
   int getPropagationBehavior();
   // 返回该事务独立于其他事务的工作的程度
   int getIsolationLevel();
   // 返回该事务的名称
   String getName();
   // 返回以秒为单位的时间间隔,事务必须在该时间间隔内完成
   int getTimeout();
   // 返回该事务是否是只读的
   boolean isReadOnly();
}

隔离级别
  TransactionDefinition.ISOLATION_DEFAULT
      默认
  TransactionDefinition.ISOLATION_READ_COMMITTED
      表明能够阻止误读;可以发生不可重复读和虚读。
  TransactionDefinition.ISOLATION_READ_UNCOMMITTED
      表明可以发生误读、不可重复读和虚读。
  TransactionDefinition.ISOLATION_REPEATABLE_READ
      表明能够阻止误读和不可重复读;可以发生虚读。
  TransactionDefinition.ISOLATION_SERIALIZABLE
      表明能够阻止误读、不可重复读和虚读。

传播类型
  TransactionDefinition.PROPAGATION_MANDATORY
      支持当前事务;如果不存在当前事务,则抛出一个异常。
  TransactionDefinition.PROPAGATION_NESTED
      如果存在当前事务,则在一个嵌套的事务中执行。
  TransactionDefinition.PROPAGATION_NEVER
      不支持当前事务;如果存在当前事务,则抛出一个异常。
  TransactionDefinition.PROPAGATION_NOT_SUPPORTED
      不支持当前事务;而总是执行非事务性。
  TransactionDefinition.PROPAGATION_REQUIRED
      支持当前事务;如果不存在事务,则创建一个新的事务。
  TransactionDefinition.PROPAGATION_REQUIRES_NEW
      创建一个新事务,如果存在一个事务,则把当前事务挂起。
  TransactionDefinition.PROPAGATION_SUPPORTS
      支持当前事务;如果不存在,则执行非事务性。
  TransactionDefinition.TIMEOUT_DEFAULT
      使用默认超时的底层事务系统,或者如果不支持超时则没有。


TransactionStatus 接口为事务代码提供了一个简单的方法来控制事务的执行和查询事务状态
public interface TransactionStatus extends SavepointManager {
   // 返回该事务内部是否有一个保存点,也就是说,基于一个保存点已经创建了嵌套事务。
   boolean isNewTransaction();
   // 返回该事务是否完成,也就是说,它是否已经提交或回滚
   boolean hasSavepoint();
   // 在当前事务时新的情况下,该方法返回 true
   void setRollbackOnly();
   // 该方法返回该事务是否已标记为 rollback-only。
   boolean isRollbackOnly();
   // 该方法设置该事务为 rollback-only 标记
   boolean isCompleted();
}

7.3.1 编程式事务管理

编程式事务管理方法允许你在对你的源代码编程的帮助下管理事务。这给了你极大地灵活性,但是它很难维护。
数据库执行

CREATE TABLE Student(
   ID   INT NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(20) NOT NULL,
   AGE  INT NOT NULL,
   PRIMARY KEY (ID)
);
CREATE TABLE Marks(
   SID INT NOT NULL,
   MARKS  INT NOT NULL,
   YEAR   INT NOT NULL
);
Beans.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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd  
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
        
   <!-- Definition for studentJDBCTemplate bean -->
   <bean id="studentJDBCTemplate" 
      class="com.sst.cx.StudentJDBCTemplate">
      <property name="dataSource"  ref="dataSource" />   
      <property name="transactionManager"  ref="transactionManager" />   
   </bean>
   <bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource"  ref="dataSource" />    
   </bean>


    <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/Test"/>
        <property name="username" value="root"/>
        <property name="password" value="密码"/>
    </bean>
</beans>
StudentDAO.java


package com.sst.cx;
import java.util.List;
import javax.sql.DataSource;


public interface StudentDAO {

       /** 
        * This is the method to be used to initialize
        * database resources ie. connection.
        */
       public void setDataSource(DataSource ds);
       /** 
        * This is the method to be used to create
        * a record in the Student and Marks tables.
        */
       public void create(String name, Integer age, Integer marks, Integer year);
       /** 
        * This is the method to be used to list down
        * all the records from the Student and Marks tables.
        */
       public List<StudentMarks> listStudents();
}
StudentJDBCTemplate.java

package com.sst.cx;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;


public class StudentJDBCTemplate implements StudentDAO{
       private DataSource dataSource;
       private JdbcTemplate jdbcTemplateObject;
       private PlatformTransactionManager transactionManager;
       public void setDataSource(DataSource dataSource) {
          this.dataSource = dataSource;
          this.jdbcTemplateObject = new JdbcTemplate(dataSource);
       }
       public void setTransactionManager(
          PlatformTransactionManager transactionManager) {
          this.transactionManager = transactionManager;
       }
       public void create(String name, Integer age, Integer marks, Integer year){
          TransactionDefinition def = new DefaultTransactionDefinition();
          TransactionStatus status = transactionManager.getTransaction(def);
          try {
             String SQL1 = "insert into Student (name, age) values (?, ?)";
             jdbcTemplateObject.update( SQL1, name, age);
             // Get the latest student id to be used in Marks table
             String SQL2 = "select max(id) from Student";
             int sid = jdbcTemplateObject.queryForObject(SQL2, null, Integer.class);
             String SQL3 = "insert into Marks(sid, marks, year) " + 
                           "values (?, ?, ?)";
             jdbcTemplateObject.update( SQL3, sid, marks, year);
             System.out.println("Created Name = " + name + ", Age = " + age);
             transactionManager.commit(status);
          } catch (DataAccessException e) {
             System.out.println("Error in creating record, rolling back");
             transactionManager.rollback(status);
             throw e;
          }
          return;
       }
       public List<StudentMarks> listStudents() {
          String SQL = "select * from Student, Marks where Student.id=Marks.sid";
          List <StudentMarks> studentMarks = jdbcTemplateObject.query(SQL, 
                                             new StudentMarksMapper());
          return studentMarks;
       }
}
Main.java

package com.sst.cx;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;

public class Main {

    public static void main(String[] args) {
           
          ApplicationContext context = 
                  new ClassPathXmlApplicationContext("Beans.xml");
           StudentJDBCTemplate studentJDBCTemplate = 
           (StudentJDBCTemplate)context.getBean("studentJDBCTemplate");     
           System.out.println("------Records creation--------" );
           studentJDBCTemplate.create("Zara", 11, 99, 2010);
           studentJDBCTemplate.create("Nuha", 20, 97, 2010);
           studentJDBCTemplate.create("Ayan", 25, 100, 2011);
           System.out.println("------Listing all the records--------" );
           List<StudentMarks> studentMarks = studentJDBCTemplate.listStudents();
           for (StudentMarks record : studentMarks) {
              System.out.print("ID : " + record.getId() );
              System.out.print(", Name : " + record.getName() );
              System.out.print(", Marks : " + record.getMarks());
              System.out.print(", Year : " + record.getYear());
              System.out.println(", Age : " + record.getAge());
           }
        
    }
}
StudentMarks.java


package com.sst.cx;

public class StudentMarks {
       private Integer age;
       private String name;
       private Integer id;
       private Integer marks;
       private Integer year;
       private Integer sid;
       public void setAge(Integer age) {
          this.age = age;
       }
       public Integer getAge() {
          return age;
       }
       public void setName(String name) {
          this.name = name;
       }
       public String getName() {
          return name;
       }
       public void setId(Integer id) {
          this.id = id;
       }
       public Integer getId() {
          return id;
       }
       public void setMarks(Integer marks) {
          this.marks = marks;
       }
       public Integer getMarks() {
          return marks;
       }
       public void setYear(Integer year) {
          this.year = year;
       }
       public Integer getYear() {
          return year;
       }
       public void setSid(Integer sid) {
          this.sid = sid;
       }
       public Integer getSid() {
          return sid;
       }
}
StudentMarksMapper.java


package com.sst.cx;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;

public class StudentMarksMapper implements RowMapper<StudentMarks> {
       public StudentMarks mapRow(ResultSet rs, int rowNum) throws SQLException {
              StudentMarks studentMarks = new StudentMarks();
              studentMarks.setId(rs.getInt("id"));
              studentMarks.setName(rs.getString("name"));
              studentMarks.setAge(rs.getInt("age"));
              studentMarks.setSid(rs.getInt("sid"));
              studentMarks.setMarks(rs.getInt("marks"));
              studentMarks.setYear(rs.getInt("year"));
              return studentMarks;
           }        
}

7.3.2 声明式事务管理

    声明式事务管理方法允许你在配置的帮助下而不是源代码硬编程来管理事务。这意味着你可以将事务管理从事务代码中隔离出来。你可以只使用注释或基于配置的 XML 来管理事务。 bean 配置会指定事务型方法。这是与声明式事务相关的步骤:
    1.我们使用 标签,它创建一个事务处理的建议,同时,我们定义一个匹配所有方法的切入点,我们希望这些方法是事务型的并且会引用事务型的建议。
    2.如果在事务型配置中包含了一个方法的名称,那么创建的建议在调用方法之前就会在事务中开始进行。
    3.目标方法会在 try / catch 块中执行。
    4.如果方法正常结束,AOP 建议会成功的提交事务,否则它执行回滚操作。
同上
  数据库
  StudentDAO.java
  StudentMarks.java
  StudentMarksMapper.java
StudentJDBCTemplate.java


package com.sst.cx;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;


public class StudentJDBCTemplate implements StudentDAO{
       private JdbcTemplate jdbcTemplateObject;
       public void setDataSource(DataSource dataSource) {
          this.jdbcTemplateObject = new JdbcTemplate(dataSource);
       }
       public void create(String name, Integer age, Integer marks, Integer year){
          try {
             String SQL1 = "insert into Student (name, age) values (?, ?)";
             jdbcTemplateObject.update( SQL1, name, age);
             // Get the latest student id to be used in Marks table
             String SQL2 = "select max(id) from Student";
             int sid = jdbcTemplateObject.queryForObject(SQL2, null, Integer.class);
             String SQL3 = "insert into Marks(sid, marks, year) " + 
                           "values (?, ?, ?)";
             jdbcTemplateObject.update( SQL3, sid, marks, year);
             System.out.println("Created Name = " + name + ", Age = " + age);
             // to simulate the exception.
             throw new RuntimeException("simulate Error condition") ;
          } catch (DataAccessException e) {
             System.out.println("Error in creating record, rolling back");
             throw e;
          }
       }
       public List<StudentMarks> listStudents() {
          String SQL = "select * from Student, Marks where Student.id=Marks.sid";
          List <StudentMarks> studentMarks=jdbcTemplateObject.query(SQL, 
          new StudentMarksMapper());
          return studentMarks;
       }
}
Beans.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:aop="http://www.springframework.org/schema/aop"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.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-3.0.xsd">
        
   <!-- Definition for studentJDBCTemplate bean -->
<!--
给数据库操作类 设置dataSource
-->
   <bean id="studentJDBCTemplate" 
      class="com.sst.cx.StudentJDBCTemplate">
      <property name="dataSource"  ref="dataSource" />    
   </bean>

<!-- 
给数据库操作类 设置事务(tx方式)
-->  
   <aop:config>
      <aop:pointcut id="createOperation" 
      expression="execution(* com.sst.cx.StudentJDBCTemplate.create(..))"/>      
      <aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/>
   </aop:config> 
   <tx:advice id="txAdvice"  transaction-manager="transactionManager">
      <tx:attributes>
      <tx:method name="create"/>
      </tx:attributes>
   </tx:advice>



<!-- 
配置事务管理器
-->  
   <bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource"  ref="dataSource" />    
   </bean>
   
<!--
配置数据库连接
-->
    <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/Test"/>
        <property name="username" value="root"/>
        <property name="password" value="密码"/>
    </bean>
</beans>
  1. Spring Web项目
处理请求的流程
处理请求的流程
    1、收到一个 HTTP 请求后,DispatcherServlet 根据 HandlerMapping 来选择并且调用适当的控制器。
    2、控制器接受请求,并基于使用的 GET 或 POST 方法来调用适当的 service 方法。Service 方法将设置基于定义的业务逻辑的模型数据,并返回视图名称到 DispatcherServlet 中。
    3、DispatcherServlet 会从 ViewResolver 获取帮助,为请求检取定义视图。
    4、一旦确定视图,DispatcherServlet 将把模型数据传递给视图,最后呈现在浏览器中。

8.1 Hello World

新建Web项目(名为HelloWeb)
    将spring的lib放在WEB-INF下的lib下,并添加入BuildPath
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name> HelloWeb </display-name>

   <!-- 此处命名需要和HelloWeb-servlet.xml的前缀一致 -->
   <servlet>
      <servlet-name>HelloWeb</servlet-name>
      <servlet-class>
         org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>

   <servlet-mapping>
      <servlet-name>HelloWeb</servlet-name>
      <url-pattern>/</url-pattern><!--不是/*-->
   </servlet-mapping>
</web-app>
HelloWeb-servlet.xml(WEB-INF下)

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
   http://www.springframework.org/schema/beans     
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <context:component-scan base-package="com.sst.cx" />

   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/jsp/" />
      <property name="suffix" value=".jsp" />
   </bean>

</beans>
src 下新建com.sst.cx包
新建HelloController.java

package com.sst.cx;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.ModelMap;

@Controller
@RequestMapping("/hello")
public class HelloController {

       @RequestMapping(method = RequestMethod.GET)
       public String printHello(ModelMap model) {
          model.addAttribute("message", "Hello Spring MVC Framework!");
          return "hello";    // 跳转hello.jsp
       }    
}
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>
Run
浏览器:http://localhost:8080/HelloSpring/hello

中途遇到错误,第二天再次运行竟然过了。
web.xml拦截,交给HelloWeb-servlet.xml,交给相应Controller.java,跳转到jsp

8.2 表单

配置如上
StudentController.java

package com.sst.cx;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.ui.ModelMap;

@Controller
public class StudentController {
       @RequestMapping(value = "/student", method = RequestMethod.GET)
       public ModelAndView student() {
          return new ModelAndView("student", "command", new Student());
       }   
       @RequestMapping(value = "/addStudent", method = RequestMethod.POST)
       public String addStudent(@ModelAttribute("SpringWeb")Student student, 
       ModelMap model) {
          model.addAttribute("name", student.getName());
          model.addAttribute("age", student.getAge());
          model.addAttribute("id", student.getId());      
          return "result";
       }
}
Student.java

package com.sst.cx;

public class Student {
       private Integer id;
       private Integer age;
       private String name;
       public void setAge(Integer age) {
          this.age = age;
       }
       public Integer getAge() {
          System.out.println("Age : " + age);
          return age;
       }
       public void setName(String name) {
          this.name = name;
       }
       public String getName() {
          System.out.println("Name : " + name );
          return name;
       }  
       public void setId(Integer id) {
           this.id = id;
       }   
       public Integer getId() {
              System.out.println("id : " + id );
           return id;   
       }
}
student.jsp

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
    <title>Spring MVC Form Handling</title>
</head>
<body>

<h2>Student Information</h2>
<form:form method="POST" action="/HelloWeb/addStudent"><!--此处为项目名/路径-->
   <table>
    <tr>
        <td><form:label path="name">Name</form:label></td>
        <td><form:input path="name" /></td>
    </tr>
    <tr>
        <td><form:label path="age">Age</form:label></td>
        <td><form:input path="age" /></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 Student Information</h2>
   <table>
    <tr>
        <td>Name</td>
        <td>${name}</td>
    </tr>
    <tr>
        <td>Age</td>
        <td>${age}</td>
    </tr>
    <tr>
        <td>ID</td>
        <td>${id}</td>
    </tr>
</table>  
</body>
</html>
Run

8.3 重定向

<form:form method="GET" action="/HelloWeb/redirect"><!--此处为项目名/路径-->

       @RequestMapping(value = "/redirect", method = RequestMethod.GET)
       public String redirect() {     
          return "redirect:finalPage";
       }   
       @RequestMapping(value = "/finalPage", method = RequestMethod.GET)
       public String finalPage() {     
          return "final";
       }

8.4 含有静态页面

HelloWeb-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:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 http://www.springframework.org/schema/mvc
 http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <context:component-scan base-package="com.sst.cx" />

    <!-- 用来映射动态页面 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/jsp/" />
      <property name="suffix" value=".jsp" />
   </bean>

    <!-- 用来映射静态页面 mapping:访问URL location:资源位置-->
    <mvc:resources mapping="/pages/**" location="/WEB-INF/pages/" />
    <mvc:annotation-driven/>
</beans>
<form:form method="GET" action="/HelloWeb/staticPage">

       @RequestMapping(value = "/staticPage", method = RequestMethod.GET)
       public String redirect() {     
          return "redirect:/pages/final.html";
       }
WEB-INF下新建pages文件夹
新建final.html

8.5 处理异常

HelloWeb-servlet.xml中+

    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
   <property name="exceptionMappings">
      <props>
         <prop key="com.sst.cx.SpringException">  <!--处理异常的类-->
            ExceptionPage<!--处理异常的jsp-->
         </prop>
      </props>
   </property>
   <property name="defaultErrorView" value="error"/><!--处理?的jsp-->
</bean>
SpringException.java

package com.sst.cx;
public class SpringException extends RuntimeException{
       private String exceptionMsg;   
       public SpringException(String exceptionMsg) {
          this.exceptionMsg = exceptionMsg;
       }   
       public String getExceptionMsg(){
          return this.exceptionMsg;
       }   
       public void setExceptionMsg(String exceptionMsg) {
          this.exceptionMsg = exceptionMsg;
       }
}
Controller.java中+

       @RequestMapping(value = "/addStudent", method = RequestMethod.POST)
       @ExceptionHandler({SpringException.class})
       public String addStudent( @ModelAttribute("HelloWeb")Student student, 
          ModelMap model) {
          if(student.getName().length() < 5 ){
             throw new SpringException("Given name is too short");
          }else{
           model.addAttribute("name", student.getName());
          }     
          if( student.getAge() < 10 ){
             throw new SpringException("Given age is too low");
          }else{
           model.addAttribute("age", student.getAge());
          }
          model.addAttribute("id", student.getId());
          return "result";
       }
ExceptionPage.jsp

<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
    <title>Spring MVC Exception Handling</title>
</head>
<body>

<h2>Spring MVC Exception Handling</h2>

<h3>${exception.exceptionMsg}</h3>

</body>
</html>
error.jsp

<html>
<head>
    <title>Spring Error Page</title>
</head>
<body>

<p>An error occured, please contact webmaster.</p>

</body>
</html>

8.6 使用 Log4J 记录日志

http://logging.apache.org 下载Log4J.jar
上一篇下一篇

猜你喜欢

热点阅读