Spring注解驱动开发

一、Spring注解驱动开发

1,组件注册

@Configuration&@Bean给容器中组建组件

1、不同于XML方式使用config配置类替代配置文件。

package com.demo.spring;
​
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
// 配置类等同于配置文件
@Configuration
public class Confige {
​
    // 给容器中注册一个Bean;类型为返回值类型,id默认方法名作为id
    @Bean("person1")
    public Person person() {
        return new Person("lisi", 20);
    }
}

使用Configuration注解表明配置类。

使用Bean注册一个Bean,其中可以在括号内设置id;

2、获得bean也不同于XML方式

package com.demo.spring;
​
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
​
public class MainTest {
​
    public static void main(String[] args) {
​
        ApplicationContext ac = new AnnotationConfigApplicationContext(Confige.class);
        Person p = ac.getBean(Person.class);
        System.out.print(p.toString());
    }
​
}
​

由ClassPathXmlApplicationContext("application.xml") 改为AnnotationConfigApplicationContext(Confige.class)。

@ComponentScan-自动扫描组件和扫描规则

指定要扫描的包

Configuration
@ComponentScan(value = "com.demo", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes ={Controller.class})
            }, useDefaultFilters = false
)
// @ComponentScan 指定要扫描的包
// @excludeFilters = Filter[] ; 指定扫描的时候按照什么规则排除那些组件。
// @includeFilters = Filter[] ; 指定扫描的时候只需要包含那些组件。
  1. 在配置类上加上@ComponentScan注解,使用该注解的Values属性可以指定扫描的包。

  2. 在includeFilters属性中可以添加规则(@ComponentScan.Filter()),指定扫描的时候只需要包含那些组件。在使用includeFilters时要将useDefaultFilters属性改为false;

  3. 在excludeFilters中同上。useDefaultFilters可以不修改。

自定义TypeFilter指定过滤规则

1, 按照注解添加过滤规则

@ComponentScan.Filter(type = FilterType.ANNOTATION, classes ={Controller.class})

2,按照类型过滤

@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})

 

3,使用ASPectJ表达式

这种使用不多

4,使用REGEX(正则)表达式

使用正则表达式的规则即可。

5, 使用CUSTOM: 使用自定义规则

使用自定义规则需要创建一个继承自TypeFilter类的Filter类

package com.demo.spring;
​
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
​
import java.io.IOException;
​
public class MyTypeFilter implements TypeFilter {
    /**
     *
     * @param metadataReader 读取当前正好在扫描类的信息
     * @param metadataReaderFactory 获取其他任何类信息
     * @return
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫面的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类资源信息 (类的路径)
        Resource resource = metadataReader.getResource();
​
        String className = classMetadata.getClassName();
        System.out.print("-------->" + className);
        if (className.contains("er")) {
            return  true;
        }
        return false;
​
    }
}
​

 

@Scope 设置组件作用域

四个作用域:

​ 1,prototype

​ 2,singleton

​ 3,request (一般不会用到)

​ 4,session (一般不会用到)

在@Bean注解上添加@Scope注解设置作用域

 @Scope("prototype")
 @Bean(value = "person")
 public Person person() {
     System.out.println("ioc容器添加中-----");
     return new Person("zhangsan", 25);
 }

 

prototype: 多实例的 ioc容器启动并不会调用方法创建对象,而是每次获取的时候才会调用方法创建对象。

singleton: 单实例的 ioc容器启动会调用方法创建对象放在ioc容器中。以后每次从容器中拿(map。get())。

request: 同一个请求创建一个实例

session: 同一个session创建一个实例

@lazy(懒加载)

容器启动不创建对象, 第一次使用(获取)的时候Bean创建对象,并初始化。

添加@lazy即可。

 @Scope("prototype")
 @lazy
 @Bean(value = "person")
 public Person person() {
     System.out.println("ioc容器添加中-----");
     return new Person("zhangsan", 25);
 }

@conditional-按照条件注册bean

1, 注册2个Person对象到IOC容器

@Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }
​
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 48);
    }

2,如果是windows系统,给容器中注册Bill。如果是Linux系统,给容器注册Linus。

2.1, 创建两个Condition接口的实现类 WindowsCondition 和 LinuxConditon

LinuxConditon类

package com.demo.condition;
​
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
​
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String property = environment.getProperty("os.name");
​
        return property.contains("Linux")?true:false;
​
    }
}
​

WindowsCondition类

package com.demo.condition;
​
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
​
/**
 *  判断是否 windows 系统,实现condition接口
 */
public class WindowsConditon implements Condition {
​
    /**
     *
     * @param conditionContext: 判断条件能使用的上下文(环境)
     * @param annotatedTypeMetadata: 注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        // 是否 Linux 系统
        // 1, 获取到 ioc 使用的 BeanFactory
        ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
        // 2, 获取类加载器
        ClassLoader classLoader = conditionContext.getClassLoader();
        // 3, 获取当前环境信息
        Environment environment = conditionContext.getEnvironment();
        // 4, 获取到Bean的定义
        BeanDefinitionRegistry registry = conditionContext.getRegistry();
​
        String property = environment.getProperty("os.name");
        return property.contains("Windows") ? true:false;
//return true;
    }
​
}
​

2.2, 在配置类上添加注解

LinuxConditon类

@Conditional({LinuxCondition.class})
    @Bean("linus")
    public Person person02() {
        return new Person("linus", 48);
    }

 

WindowsCondition类

 @Conditional(WindowsConditon.class) // 放condition数组
    @Bean("bill")
    public Person person01() {
        return new Person("Bill Gates", 62);
    }

2.3,这样即可根据Conditon实现类的具体实现注册Bean到IOC容器内。

2.4,也可以将@Conditional注解添加到配置类上

@Conditional(WindowsConditon.class) // 满足条件这个类中的所有注册才能生效。
@Configuration
public class Confige2 {
​
}

@import 给容器中快速添加一个组件

给容器中注册组件的方式

1, 包扫描+组件标注注解 (@Controller ,@Service, @Repository, @component)

2, @Bean 【导入第三方包里面的组件】

3, @import 【快速给容器导入一个组件】

3.1, 在配置类上添加 @import 注解(单个类添加)

@Conditional(WindowsConditon.class) // 满足条件这个类中的所有注册才能生效。
@Configuration
@Import({Color.class,Red.class}) // 快速导入组件id默认是组件全类名
public class Confige2 {
​
}

3.2,ImportSelector: 自定义逻辑返回需要导入的组件。

3.2.1,创建一个实现ImportSelector接口的类 MyImportSeletor

package com.demo.condition;
​
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
​
public class MyImportSelector implements ImportSelector {
​
    /**
     *
     * @param annotationMetadata
     * @return 返回要导入的组件全类名
     */
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 可以返回空数组但是不能是null,会空指针。
        return new String []{"com.demo.spring.blue", "com.demo.spring.yellow"};
    }
}
​

 

3.2.2,在配置类的@import 注解中添加 MyImportSeletor

@Conditional(WindowsConditon.class) // 满足条件这个类中的所有注册才能生效。
@Configuration
@Import({Color.class,Red.class, MyImportSelector.class}) // 快速导入组件id默认是组件全类名
public class Confige2 {
    
}

3.3,ImportBeanDefinitionRegistrar:在配置类上添加 @import 注解(加上ImportBeanDefinitionRegistrar实现类)

3.3.1, 创建一个ImportBeanDefinitionRegistrar接口的实现类

package com.demo.condition;
​
import com.demo.spring.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
​
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        boolean hasRed = beanDefinitionRegistry.containsBeanDefinition("com.demo.spring.Blue");
        boolean hasBlue = beanDefinitionRegistry.containsBeanDefinition("com.demo.spring.Yellow");
        if (hasRed && hasBlue) {
            // 指定Bean定义信息
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个Bean,指定Bean名
            beanDefinitionRegistry.registerBeanDefinition("rainbow", rootBeanDefinition);
        }
    }
}
​

使用

// 指定Bean定义信息
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个Bean,指定Bean名
            beanDefinitionRegistry.registerBeanDefinition("rainbow", rootBeanDefinition);

手动注册信息

3.3.2,配置类添加ImportBeanDefinitionRegistrar实现类

@Import({Color.class,Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})

4,使用用Spring提供的FactoryBean接口

4.1,实现Spring的FactoryBean接口

package com.demo.condition;
​
import com.demo.spring.Color;
import org.springframework.beans.factory.FactoryBean;
​
public class ColorFactoryBean implements FactoryBean<Color> {
    @Override
    public Color getObject() throws Exception {
        return new Color();
    }
​
    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }
​
    /**
     *
     * @return @true : 单实例, 每次创建返回一个对象 @false : 多实例
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}
​

4.2,在配置类上添加这个BeanFactory

@Bean
    public ColorFactoryBean colorFactoryBean() {
        return  new ColorFactoryBean();
    }

 

2,生命周期

@Bean 指定初始化和销毁方法

1,创建一个Bean类,该类包含初始化和销毁方法的实现

package com.demo.spring;
​
public class Car {
​
    public  Car() {
        System.out.println("car constructor");
    }
​
    public void init() {
        System.out.println("car...init...");
    }
​
    public void destroy() {
        System.out.println("car...destroy...");
    }
}
​

2,在@Bean 标注初始化方法和销毁方法

package com.demo.spring;
​
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
@Configuration
public class ConfigOfLifeCycle {
​
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public  Car car() {
        return new Car();
    }
​
​
}
​

InitlizingBean 和 DisposalbleBean

通过让Bean实现InitlizingBean 初始化

通过让Bean实现DisposalbleBean销毁

@PostConstrucor 和 @PreDestory

@PorstConstrucor在Bean创建完成来执行初始化。

@PreDestory在容器销毁前。

在Bean内对应方法前加上注解即可。

PostProcessorBeforeInitialization 和 PostProcessorAfterInitalization

通过实现接口BeanPostProcessor的两个方法

PostProcessorBeforeInitialization

PostProcessorAfterInitalization

3,属性赋值

1,在Bean类中属性上加上@Value注解,有三种方式添加

package com.demo.spring;
​
import org.springframework.beans.factory.annotation.Value;
​
public class Person {
​
    // 使用@Value 赋值
    // 1, 基本数值
    // 2,SpEl #{}
    // 3,写${}配置文件中的值(在运行环境变量中的值)
​
    @Value("张三")
    private String name;
    @Value("#{20-2}")
    private Integer age;
    @Value("${person.nickname}")
    private String nickname;
}

2,使用外部配置文件时,在配置类中添加@PropertySource

@Configuration
//使用PropertySource读取外部配置文件
@PropertySource(value={"classpath:/person1.properties"})
public class ConfigOfPropertyValues {
​
    @Bean
    public Person person() {
        return new Person();
    }
}
​

4, 自动装配

@Autowried自动注入

Spring利用依赖注入,完成对IOC容器中各个组件的依赖关系

1, 默认优先按照类型去容器中找对应的组件:

2,如果找到多个相同类型的组件,再将属性的名称作为组件的Id去容器中查找。

3, @Qualifier("bookDao") 使用 @Qualifier指定需要装配的组件的id而不是组件名。

4,@primary: 让Spring进行自动装配的时候默认使用标注的bean对象。也可以继续使用@Qualifier指定的名字。

使用@Resource 和 @Inject

@Resource和@AutoWried一样但不支持@Qualifier@primary

@Inject需要导依赖和AutoWried功能一样

@Profile

Spring为我们提供的可以根据当前环境自动切换Bean的功能

在@Bean上添加 @Profile

package com.demo.spring;
​
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
@Configuration
public class ConfigOfLifeCycle {
    @profile("test")
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public  Car car() {
        return new Car();
    }
​
​
}

使用@profile 标识哪个环境

1、创建一个applicationContext
2、设置需要激活的环境
applicationContext.getEvironment().setActiveProfiles("test","dev");
3、注册主配置类
applicationContext.register(config.class);
4、启动刷新容器
applicationContext.refresh();

5,AOP

AOP指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。

1,导入AOP模块

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>

2,定义一个业务逻辑类,在业务逻辑进行时将日志进行打印。

package com.demo.spring;
​
/*
 * 业务逻辑类
 * 在业务逻辑运行时进行打印
 */
public class MathCaculator {
​
    public int div(int i, int j) {
        System.out.println("调用div");
        return i/j;
    }
}
​

 

3,定义一个日志切面类:切面类里面的方法需要动态感知业务逻辑类进行到哪部。

通知方法:

前置通知(@Before):在目标方法运行前运行

 // 在目标方法前切入:切入点表达式
    @Before("pointcut()")
    public void logStart(JoinPoint joinPoint) {
        Object [] args = joinPoint.getArgs();
        System.out.println(""+joinPoint.getSignature().getName() + "除法运行。。。参数列表是{"
                + Arrays.asList(args)+ "}");
​
    }

 

后置通知(@After):在目标方法运行结束后运行,无论方法正常结束还是异常结束都调用

 // JoinPoint 一定要放在参数列表第一位
    @After("pointcut()")
    public void logEnd(JoinPoint joinPoint) {
        System.out.println(joinPoint.getSignature().getName() + "除法结束");
    }

 

返回通知(@AfterReturnning):在目标方法正常返回运行

@AfterReturning(value = "pointcut()", returning = "result")
    public void logReturn(Object result) {
        System.out.println("除法正常返回。。。运行结果是:{" +result + "}");
    }

 

异常通知(@AfterThrowing):在目标方法运行异常时运行

 @AfterThrowing(value = "pointcut()",throwing = "exception")
    public void logEcxeption(Exception exception) {
        System.out.println("除法异常。。。异常信息是:");
    }

环绕通知(@Around):动态代理,手动推进目标方法运行

 @AfterReturning(value = "pointcut()", returning = "result")
    public void logReturn(Object result) {
        System.out.println("除法正常返回。。。运行结果是:{" +result + "}");
    }


 

4,通知注解

  • @Before

  • @After

  • @ReturnThrowing

  • @ReturnReturning

5,给切面类和业务逻辑类加入到IOC容器中。

 // 业务逻辑加入到容器中
    @Bean
    public MathCaculator mathCaculator() {
        return new MathCaculator();
    }
​
    // 切面类加入到容器中
    @Bean
    public  LogAspect logAspect() {
        return new LogAspect();
    }

 

6,必须告诉Spring哪个类是切面类,给切面类上加一个注解@Aspect。

@Aspect
public class LogAspect {
    
}


 

7,在配置类中加上@EnableAspectJAutoProxy 启用基于注解的AOP模式。

@EnableAspectJAutoProxy // 启用基于注解的Aop模式
@Configuration
public class ConfigOfAOP {

}


6,声明式事务

声明式事务

1,导入相关依赖

​ 数据源、数据库驱动、Spring-jdbc模块

<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>

 

2,配置数据源及jdbcTemplate操作数据

// 数据源
    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC&characterEncoding=utf-8  ");
        return dataSource;
    }
​
// spring 对 configuration类会特殊处理,给容器中加组件的方法多次调用只是给容器中加组件。
    @Bean
    public JdbcTemplate jdbcTemplate() throws PropertyVetoException {
​
        return  new JdbcTemplate(dataSource());
    }

 

3,给方法上标注@Transactional表示当前方法是事务方法

package com.demo.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void insert() {
        String sql = "insert into t_user(username,age) values(?,?)";
        String args = UUID.randomUUID().toString().substring(0,5);
        jdbcTemplate.update(sql,args,19);
    }
}



 

4,@EnableTransactionManagement 开启事务管理功能

@EnableTransactionManagement
@ComponentScan({"com.demo.dao","com.demo.service"})
@Configuration
public class TXConfig {
    
}

5,配置事务管理器来控制事务

// 将事务管理器添加到容器中
    @Bean
    public PlatformTransactionManager platformTransactionManager() throws PropertyVetoException {
        return  new DataSourceTransactionManager(dataSource());
    }

7,servlet3.0注解支持

在类上添加@WebServlet即可以实现以前在web.xml里写的<servlet>相关标签。

@WebServlet("hello")
public class HelloServlet extends HttpServlet {
    //override  doget()
}

注册listener filter 同理 @WebFilter @WebListener

1,servlet3.0注册外部组件到servlet容器

Servlet容器启动时会扫描当前应用中每一个jar包中的在META-INF/services/javax.servlet.ServletContainerInitializer文件(该文件没有后缀名)中配置的ServletContainerInitializer的实现类,javax.servlet.ServletContainerInitializer文件的内容就是ServletContainerInitializer实现类的全类名,启动时会运行这些实现类的onStartUp方法,可以通过@HandlesTypes传入一些感兴趣的类型,在onStartUp方法中做一些操作。一个jar包中只能有一个javax.servlet.ServletContainerInitializer配置文件,一个javax.servlet.ServletContainerInitializer配置文件中只能配置一个ServletContainerInitializer实现类。

ServletContainerInitializer实现类:

@HandlesTypes({HelloServiceInterface.class})
public class MyServletContainerInitializer implements ServletContainerInitializer{
 
	@Override
	public void onStartup(Set<Class<?>> set, ServletContext context) throws ServletException {
		System.out.println("感兴趣的类:");
		for (Class<?> clazz : set) {
			System.out.println(">>>>>>" + clazz);
		}
	}
 
}



onStartUp方法的入参:

set是@HandlesTypes中传入的接口或者类的所有子接口或者子类(不包含该接口或该类本身);context是web项目的servlet上下文,一个web项目对应一个ServletContext,通过ServletContext可以来注册web组件,比如第三方的filter组件(由于第三方的组件并不是我们写的,我们无法通过@WebServlet、@WebFilter、@WebListener来标注使其拦截相应的请求,这个时候就需要在ServletContainerInitializer中通过ServletContext来注册了)

javax.servlet.ServletContainerInitializer配置文件内容:

com.bdm.servlet.MyServletContainerInitializer



 

2,添加web组件

分别创建Servlet、Listener、Filter的实现类

public class UserServlet extends HttpServlet{
 
    private static final long serialVersionUID = -5343785314009218808L;
 
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("tomcat...");
    }
}
​
public class UserListener implements ServletContextListener {
 
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        System.out.println("UserListener...contextDestroyed...");
    }
 
    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("UserListener...contextInitialized...");
    }
 
}
​
public class UserFilter implements Filter{
 
    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        
    }
 
    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("UserFilter...doFilter...");
        chain.doFilter(arg0, arg1);
    }
 
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub
        
    }
 
}
​

注册web组件到Servlet

@HandlesTypes({HelloServiceInterface.class})
public class MyServletContainerInitializer implements ServletContainerInitializer{
 
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext context) throws ServletException {
        // 添加servlet
        ServletRegistration.Dynamic userServlet = context.addServlet("userServlet", new UserServlet());
        userServlet.addMapping("/user");
        
        // 添加filter
        FilterRegistration.Dynamic filter = context.addFilter("userFilter", UserFilter.class);
        filter.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST), true, "userServlet");
        filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
        
        // 添加Listener
        context.addListener(UserListener.class);
    }
 
}
​

3,Servlet3.0和SpringMvc整合

以注解方式来启动SpringMVC:

​ 继承AbstractAnnotationConfigDispatcherServletInitializer;

​ 实现抽象方法指定DispatcherServlet的配置信息

1,创建两个配置类 AppConifg 以及 RootConfig

AppConifg

package com.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

import com.demo.service.HelloService;

@ComponentScan(value="com.demo",excludeFilters={
		@Filter(type=FilterType.ANNOTATION,classes={Controller.class})
})
@Configuration
public class AppConfig {
	
	
}



RootConfig

package com.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

import com.demo.service.HelloService;

// SrpingMVC 只扫描Controller
@ComponentScan(value="com.demo",includeFilters={
		@Filter(type=FilterType.ANNOTATION,classes=Controller.class)
},useDefaultFilters=false)
@Configuration
public class RootConfig {
	
	@Bean
	public HelloService helloService() {
		return new HelloService();
	}
}



将各组件加入容器

2,各组件类

Hello Controller

package com.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.demo.service.HelloService;

@Controller
public class HelloController {

	@Autowired
	HelloService helloService;
	
	
	@ResponseBody
	@RequestMapping("/hello")
	public String hello() {
		String hello = helloService.sayHello("tomcat.. ");
		return hello;
	}
}



HelloService

package com.demo.service;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
	
	public String sayHello(String name) {
		
		return "Hello" + name;
	}
}



3, 继承AbstractAnnotationConfigDispatcherServletInitializer;

​ 实现抽象方法指定DispatcherServlet的配置信息

MyWebAppinitalizer

package com.demo;
​
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
​
import com.demo.config.AppConfig;
import com.demo.config.RootConfig;
​
// web容器启动创建对象; 调用方法初始化容器及前端控制器
public class MyWebAppinitalizer extends AbstractAnnotationConfigDispatcherServletInitializer {
​
    // 获取根容器的配置类(Spring配置文件) 父容器
    @Override
    protected Class<?>[] getRootConfigClasses() {
        // TODO Auto-generated method stub
        return new Class<?>[] {RootConfig.class};
    }
​
    // 获取Web容器的配置类(SpringMVC配置文件 ) 子容器
    @Override
    protected Class<?>[] getServletConfigClasses() {
        // TODO Auto-generated method stub
        return new Class<?>[] {AppConfig.class};
    }
​
    // 获取前端控制器映射信息
    // 拦截所有请求包括静态资源不拦截*.jsp
    @Override
    protected String[] getServletMappings() {
        // TODO Auto-generated method stub
        return new String[]{"/"};
    }
​
}
​

4,springmvc定制与接管springmvc

@EnableWebMvc:开启springmvc定制配置功能。

​ 相当于配置文件< Mvc:annotation-driven >

配置组件(视图解析器、视图映射器、静态资源映射器、拦截器)

实现WebMvcConfigurer接口(一般继承它的子类WebMvcConfigurerAdapter)

@ComponentScan(value = "com.demo", excludeFilters = {
		@Filter(type = FilterType.ANNOTATION, classes = { Controller.class }) })
@Configuration
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
    
}


 

定制configureViewResolvers方法实现前端视图解析

@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.jsp("/WEB-INF/views/", ".jsp");
	}


定制静态资源访问

// 静态资源访问
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}


MarkDowm直接复制过来格式有点不一样。。。​

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值