spring5.14参考文档

spring总结

  • spring mvc
    request-->DispatcherServlet-->MappingHandler-->AdaptorHandler-->Handler-->ModelAndView(String逻辑视图,void直接response、sendRedict、forward)-->view-->response
  • IOC控制反转
    对象的声明周期交给spring容器来管理,xml配置<bean id/name="" class/type="" scope="" lazy-init="true">,也可以通过注解的方式向spring容器注册bean;也可以通过代码注册(通过context获得DefaultListableBeanFactory接口类型的对象,调用registerSingleton和registerBeanDefinition方法注册)
注解 描述
@Component 没有明确的角色分工
@Repository dao,dao层
@Service service,service层
@Controller action,表现层

使用注解的时候可以指定bean的id,如@Repository("userDao"),如果不指定,默认为把类名的首字母改为小写后的字符串作为bean的id

  • DI依赖注入
    可以使用XML配置文件的方式(分为基于getter/setter方法和构造函数两种配置方式),也可以使用注解的方式。
注解 描述
@Autowired(require=true/false) Autowired按类型进行自动装配,配合@Qualifier使用,@Qualifier("beanid")
@Inject 是JSR-330提供的注解
@Resource(name="beanname") 是JSR-250提供的注解

AOP面向切面编程

以动态代理为基础

其他注解

注解 描述
@RequestBody request数据使用json形式
@ResponseBody json形式返回
@RequestMapping url映射
@RequestParam 参数绑定

spring核心组件

Bean,Context,Core

  • Bean,即bean,是IOC容器中的bean
  • Context,应用上下文,是IOC容器,是容器中各个bean之间的关系的集合
  • Core,一些核心类,Resource表示资源,是通用的,屏蔽了不同类型的资源的差异。Resource 接口继承了 InputStreamSource 接口,这个接口中有个 getInputStream 方法,返回的是 InputStream 类,这样所有的资源都被可以通过 InputStream 这个类来获取,所以也屏蔽了资源的提供者。另外还有一个问题就是加载资源的问题,也就是资源的加载者要统一,这个任务是由 ResourceLoader 接口完成,它屏蔽了所有的资源加载者的差异,只需要实现这个接口就可以加载所有的资源,它的默认实现是 DefaultResourceLoader。
  • BeanFactory接口;ApplicationContext接口就是IOC容器,它继承了BeanFactory接口。ApplicationContext有好几个实现,常见的有ClassPathXmlApplicationContextFileSystemXmlApplicationContextWebApplicationContext,配置的方式有多种,xml-based,annotation-based,java-based
  • 一般在IOC容器中注册dao,service,action,基础设施如SessionFactory等,domain的bean一般不注册,非IOC容器创建的bean也可以通过IOC来管理

Typically, you define service layer objects, data access objects (DAOs), presentation objects such as Struts Action instances, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth. Typically, one does not configure fine-grained domain objects in the container, because it is usually the responsibility of DAOs and business logic to create and load domain objects. However, you can use Spring’s integration with AspectJ to configure objects that have been created outside the control of an IoC container.

IOC(xml注册(单个或包扫描),注解注册,DefaultListableBeanFactory代码注册)

  • Naming
<bean id="myBean" name="mybean" class/type="com.example.MyBean" scope="prototype" lazy-init="true" init-method="" destroy-method="">
  • Alias
<alias name="fromName" alias="toName"/>
  • Instantiate
  1. 默认构造器
<bean id="exampleBean" class="examples.ExampleBean"/>
  1. 静态工厂方法
<bean id="clientService"
    class="examples.ClientService"
    factory-method="createInstance"/>

对应的java代码

public class ClientService {
    private static ClientService clientService = new ClientService();
    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}
  • 实例工厂方法
<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
    <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="clientService"
    factory-bean="serviceLocator"
    factory-method="createClientServiceInstance"/>

<bean id="accountService"
    factory-bean="serviceLocator"
    factory-method="createAccountServiceInstance"/>

对应java代码

public class DefaultServiceLocator {

    private static ClientService clientService = new ClientServiceImpl();
    private static AccountService accountService = new AccountServiceImpl();

    public ClientService createClientServiceInstance() {
        return clientService;
    }

    public AccountService createAccountServiceInstance() {
        return accountService;
    }
}

DI(xml配置,注解)

IOC容器通过构造器或者工厂方法创建了bean后,对bean进行依赖注入

  • constructor-based
  1. 构造器参数是引用类型
package x.y;

public class ThingOne {

    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        // ...
    }
}
<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </bean>

    <bean id="beanTwo" class="x.y.ThingTwo"/>

    <bean id="beanThree" class="x.y.ThingThree"/>
</beans>
  1. 构造器函数式简单类型
ackage examples;

public class ExampleBean {

    // Number of years to calculate the Ultimate Answer
    private int years;

    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}

①使用type

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

②使用index,index从0开始

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

③使用name

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

Keep in mind that, to make this work out of the box, your code must be compiled with the debug flag enabled so that Spring can look up the parameter name from the constructor. If you cannot or do not want to compile your code with the debug flag, you can use @ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample class would then have to look as follows:

package examples;

public class ExampleBean {

    // Fields omitted

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
  • setter-based
    spring团队提倡使用CDI,对于必须的依赖选择CDI,对于可选的依赖使用SDI,有的场景不得不使用SDI,比如要求可以重新配置或赋值的bean,再比如循环依赖,则必须对其中一个使用SDI
    ①SDI
<bean id="exampleBean" class="examples.ExampleBean">
    <!-- setter injection using the nested ref element -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- setter injection using the neater ref attribute -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }
}

②CDI

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- constructor injection using the nested ref element -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>

    <!-- constructor injection using the neater ref attribute -->
    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    private AnotherBean beanOne;

    private YetAnotherBean beanTwo;

    private int i;

    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}

③静态工厂方法

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
public class ExampleBean {

    // a private constructor
    private ExampleBean(...) {
        ...
    }

    // a static factory method; the arguments to this method can be
    // considered the dependencies of the bean that is returned,
    // regardless of how those arguments are actually used.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }
}
  • ref
    <bean id="" ref="">,ref可以引用同一IOC容器或父容器中的bean,不管是不是定义在同一个xml文件中
  • idref
  • 集合
<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>
  • ·depends-on,保证自己所依赖的项在自己创建之前创建
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
  • scope为singleton的bean,和有默认值的bean在IOC容器创建的时候被创建,需要懒加载可以使用lazy-init属性

scope

image.png
  • proxy-target-class属性
    false为jdk动态代理,true为cglib动态代理

生命周期callback函数

构建后和销毁前
Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:

  1. Methods annotated with @PostConstruct

  2. afterPropertiesSet() as defined by the InitializingBean callback interface

  3. A custom configured init() method

Destroy methods are called in the same order:

  1. Methods annotated with @PreDestroy

  2. destroy() as defined by the DisposableBean callback interface

  3. A custom configured destroy() method

使用注解需要开启<context:annotation-config/>

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

    <context:annotation-config/>

</beans>
  • @Autowired @Inject @Resource @Value
  • JavaConfig方式@Configuration @Bean @Import
    @Configuration@Bean一起使用
    @Import
    @Configuration用在类上,@Bean用在方法上,该方法返回一个对象,将返回的对象注册到IOC容器中,注册的bean的name就是方法名
  • @Primary @Qualifier
    @Autowired是根据类型来匹配的,如果存在多个condidates,我们使用@Primary @Qualifier来指明精确的匹配
    @Resource(name="")
@Configuration
public class MovieConfiguration {

    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }

    @Bean
    public MovieCatalog secondMovieCatalog() { ... }

    // ...
}
public class MovieRecommender {

    @Autowired
    private MovieCatalog movieCatalog;

    // ...
}

be equivalent to the following 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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog" primary="true">
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>

</beans>
public class MovieRecommender {

    @Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;

    // ...
}
public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

be equivalent to the following 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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="main"/> 

        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="action"/> 

        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>

</beans>
  • @RestController=@ResponseBody+Controller
  • 开启自动扫描,自动检测被@Component, @Repository, @Service, @Controller注解的类,自动注册到IOC容器中,如果没指定name属性的值,自动注册的bean的name为类名首字母小写
    xml方式<context:component-scan base-package="org.example"/>
@Service
public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}
@Repository
public class JpaMovieFinder implements MovieFinder {
    // implementation elided for clarity
}
//javaConfig方式
@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    ...
}

AnnotationConfigApplicationContext

ClassPathXMLApplicationContext使用xml文件作为bean definition,AnnotationConfigApplicationContext使用注解

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}
  • @Respository @Service @Controller @Configuration这几个注解的定义上都有@Component注解,所以<context:component-scan />可以检测到

xml配置和javaConfig配置结合使用

  • xml为主,JavaConfig为辅
    开启<context:anotation-config /><context:component-scan />,然后在代码中使用注解
  • JavaConfig为主,xml为辅
    使用@ImportResource导入xml文件
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(url, username, password);
    }
}

xml文件

properties-config.xml
<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>

jdbc.properties文件

jdbc.properties
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    TransferService transferService = ctx.getBean(TransferService.class);
    // ...
}

profile

不同的环境下(开发,测试,生产环境),不同的配置

  1. 开启profile
  • 注解方式,如@Profile("development")
  • xml方式,如<beans profile="development">
  1. 激活profile
  • 代码方式
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();
  • 系统变量方式
    -Dspring.profiles.active="development"

Resource接口

表示资源,重要的方法有getInputStream(),多个实现UrlResource
ClassPathResource,FileSystemResource,ServletContextResource
InputStreamResource,ByteArrayResource

ResourceLoader接口

方法为getResource(String location),所有的ApplicationContext的实现都实现了这个接口

Validator ValidationUtils

supports(Class c)
validate(Object target, Errors errors)

Converter

package org.springframework.core.convert.converter;

public interface Converter<S, T> {

    T convert(S source);
}

SpEL

AOP

  1. concepts
  • Aspect
  • Advise(5种类型,在join point上要干的事)
  • join point(通常是一个方法执行)
  • pointcut(pointcut expression)
  • target object(目标对象)
  • Proxy(代理,jdk动态代理或cglib代理)
  • weaving(织入的时机可以是编译,加载,运行时)
  • Introduction(给被代理的对象引入额外的的接口实现)
  1. types of advise
  • before
  • after return(正常结束)
  • after exception(异常退出)
  • after(finally,无论哪种退出方式)
  • around(环绕通知,前后都可以定义定制化的操作,可以选择是否进入join point的执行流程,也可以shortcut advised method execution)

AspectJ

  • enable aspectj supports
    <aop:aspectj-autoproxy/>
  • define aspect
  1. annotation-stytle
    @Aspect @Component(为了能使用扫描器)
  2. xml-style
  • pointcut expression format
    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
    修饰符 返回值类型 全限定类名 方法名 参数 异常,除了execution操作符还可以使用within target annotation args bean等操作符

  • advise body可以获取advised method 的参数,返回值,异常

@Pointcut("com.xyz.myapp.SystemArchitecture.dataAccessOperation() && args(account,..)")
private void accountDataAccessOperation(Account account) {}

@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
    // ...
}
  • xml形式
<aop:config>

    <aop:aspect id="myAspect" ref="aBean">

        <aop:pointcut id="businessService"
            expression="execution(* com.xyz.myapp.service..(..)) and this(service)"/>

        <aop:before pointcut-ref="businessService" method="monitor"/>
<!-- 或者
        <aop:before pointcut="execution(* com.xyz.myapp.service..(..)) and this(service)" method="monitor"/>
-->

        ...
    </aop:aspect>
</aop:config>

<bean id="aBean" class="">
  ...
</bean>

Aspect代码

public void monitor(Object service) {
    ...
}

after return

<aop:aspect id="afterReturningExample" ref="aBean">

    <aop:after-returning
        pointcut-ref="dataAccessOperation"
        returning="retVal"
        method="doAccessCheck"/>

    ...

</aop:aspect>

corresponding to java code

public void doAccessCheck(Object retVal) {...}
<aop:config>

    <aop:pointcut id="businessService"
        expression="execution(* com.xyz.myapp.service.*.*(..))"/>

    <aop:advisor
        pointcut-ref="businessService"
        advice-ref="tx-advice"/>

</aop:config>

<tx:advice id="tx-advice">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
  • force to use cglib proxy
<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>

or

<aop:aspectj-autoproxy proxy-target-class="true"/>

transation

  • PlatformTransactionManager
public interface PlatformTransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}
  • @Transactional @EnableTransactionManagement

  • <tx:advice/>
    advisor相当于只有一个方法的aspect

<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- this is the service object that we want to make transactional -->
    <bean id="fooService" class="x.y.service.DefaultFooService"/>

    <!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- the transactional semantics... -->
        <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="get*" read-only="true"/>
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

    <!-- ensure that the above transactional advice runs for any execution
        of an operation defined by the FooService interface -->
    <aop:config>
        <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
    </aop:config>

    <!-- don't forget the DataSource -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
        <property name="username" value="scott"/>
        <property name="password" value="tiger"/>
    </bean>

    <!-- similarly, don't forget the PlatformTransactionManager -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- other <bean/> definitions here -->

</beans>
  • 默认回滚策略是发生了未处理的unchecked exception,checked exception默认不回滚

配置回滚的异常

<tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
    <tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/>
    <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

配置特定异常不回滚

<tx:advice id="txAdvice">
    <tx:attributes>
    <tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/>
    <tx:method name="*"/>
    </tx:attributes>
</tx:advice>
<tx:advice>settings
  • annotation-based transaction
    @EnableTransactionManagement @Transactional
<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- this is the service object that we want to make transactional -->
    <bean id="fooService" class="x.y.service.DefaultFooService"/>

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="txManager"/><!-- a PlatformTransactionManager is still required --> 

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- (this dependency is defined somewhere else) -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- other <bean/> definitions here -->

</beans>
  • programmatic transaction
  1. Using the TransactionTemplate
  2. Using the PlatformTransactionManager

spring mvc

  • DispacherServlet
  • HandlerMapping
  1. RequestMappingHandlerMapping
  2. SimpleUrlHandlerMapping
<!-- 配置Handler -->   
<bean id="hello1" class="com.ys.controller.HelloController" />
<bean id="hello2" class="com.ys.controller.HelloController" />
<!-- 第二种方法:简单URL配置处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="/hello1.do">hello1</prop>
            <prop key="/hello2.do">hello2</prop>
        </props>
    </property>
</bean>
  1. BeanNameUrlHandlerMapping(bean的name作为url)
  • HandlerAdapter
  1. SimpleControllerHandlerAdapter(handler需要直接或间接实现Controller)


    SimpleControllerHandlerAdapter
  2. HttpRequestHandlerAdapter(handler需要直接或间接实现HttpRequestHandler,public void handleRequest(HttpServletRequest request, HttpServletResponse response),没有返回值,可以通过转发、重定向、直接response.getWriter().write()

    HttpRequestHandlerAdapter

  • ViewResolver
  1. InternalResourceViewResolver
<!-- 配置视图解析器
    进行jsp解析,默认使用jstl标签,classpath下得有jstl的包,如果这样配,那么在 Handler 中返回的必须是路径+jsp页面名称+".jsp"-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />

or

<!--配置视图解析器  如果这样配,那么在 Handler 中只需要返回在 view 文件夹下的jsp 页面名就可以了-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 返回视图页面的前缀 -->
        <property name="prefix" value="/WEB-INF/view"></property>
        <!-- 返回页面的后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>
  • DispatcherServlet.properties
    如果用户没有配置springmvc全局配置文件,就会使用这个
  • HandlerExceptionResolver
  • HandlerInterceptor

参数绑定

@RequestParam @RequestHeader @CookieValue @PathVariable @ModelAttribute

  • ResponseEntity RequestEntity包含header和body
  • CORS
    @CrossOrigin
<mvc:cors>

    <mvc:mapping path="/api/**"
        allowed-origins="http://domain1.com, http://domain2.com"
        allowed-methods="GET, PUT"
        allowed-headers="header1, header2, header3"
        exposed-headers="header1, header2" allow-credentials="true"
        max-age="123" />

    <mvc:mapping path="/resources/**"
        allowed-origins="http://domain1.com" />

</mvc:cors>

FreeMarker模板引擎

<mvc:annotation-driven/>

<mvc:view-resolvers>
    <mvc:freemarker/>
</mvc:view-resolvers>

<!-- Configure FreeMarker... -->
<mvc:freemarker-configurer>
    <mvc:template-loader-path location="/WEB-INF/freemarker"/>
</mvc:freemarker-configurer>

Controller接口

  • 可以实现Controller接口或继承AbstractController抽象类,或者带有@Controller注解的普通类
public interface Controller {
       ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

AbstractController抽象类实现了Controller

缓存

  • cache头信息, Cache-Control :max-age=cacheSeconds
  • If-Modified-Since
  • etag
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容

  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 12,291评论 6 86
  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,712评论 0 11
  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,934评论 4 21
  • 什么是Spring Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Jav...
    jemmm阅读 16,461评论 1 133
  • 最近,被三本厚厚的大书碾压,还没打开就出现了满满的焦虑,越到考试越焦虑,脑海中的细胞全都在跟我说:“记不住怎么办,...
    Belle0阅读 175评论 2 4