Spring Boot实战(三)

1. @Enable*注解

1.1. 注解描述

@EnableAspectJAutoProxy - 开启对AspectJ自动代理技术

@EnableConfigurationProperties - 开启对@ConfigurationProperties注解配置Bean的支持

@EnableJpaRepositories - 开启对Spring data JPA Repository的支持

@EnableTransactionManagement 开启注解式事务的支持,比如在某个公有方法中添加@Transactional

通过简单的@Enable*来开启一项功能的支持,从而避免自己配置大量的代码,大大降低使用难度。

1.2. 简单使用

1.2.1. @EnableAspectJAutoProxy

1)使用xml时的配置:

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

属性说明:

①boolean proxyTargetClass() default false;

描述:启用cglib代理,proxyTargetClass默认为false。

②boolean exposeProxy() default false;

描述:如果在一个方法中,调用内部方法,需要在调用内部方法时也能够进行代理,比如内部调用时,使用

(IService)AopContext.currentProxy().sayHello(),需要将exposeProx设置为true,默认为false。

2)使用注解@EnableAspectJAutoProxy配置

@EnableAspectJAutoProxy(proxyTargetClass=true, exposeProxy=true)
@SpringBootApplication
public class BootStrap {
	public static void main(String[] args) {
		SpringApplication.run(BootStrap.class, args);
	}
}

注:也可以不使用@EnableAspectAutoProxy注解开启AspectJ自动代理技术,可以在spring boot的默认配置appllication.properties中进行配置,配置如下:

# 增加@EnableAspectJAutoProxy
spring.aop.auto=true
# 开启CGLIB代理
spring.aop.proxy-target-class=true

1.2.2. @ConfigurationProperties

通过@ConfigurationProperties将properties属性和一个Bean及其属性关联,从而实现类型安全的配置

在appllication.properties中添加如下配置:

spring.http.encoding=utf-8

2)类型安全的Bean

@Component
@ConfigurationProperties(prefix="spring.http")
public class SpringEncoding {
	private String encoding;

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

}

注:@ConfigurationProperties既可以放在类上也可以放在方法上,放在方法上使用和类上一样。@ConfigurationProperties加载properties文件内的配置,通过prefix属性指定properties配置的前缀,通过locations指定properties文件所在路径,例如:

@Component
@ConfigurationProperties(prefix="spring.http", locations={"classpath:encoding.properties"})
public class SpringEncoding {
	private String encoding;
	public String getEncoding() {
		return encoding;
	}
	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
}

1.2.3. @EnableJpaRepositories和EnableTransactionManagement

1)使用xml配置:



2)使用EnableJpaRepositories和EnableTransactionManagemen注解

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryDemo",
        transactionManagerRef = "transactionManagerDemo",
        basePackages = {"com.happygo.gitlab.domain.demo.repository"})
@Profile(value = {"dev", "serverForDev"})
public class DataSourceConfig {
    @Autowired
    private JpaProperties jpaProperties;

    @Autowired
    @Qualifier("demohDS")
    private DataSource demoDataResource;

    @Bean(name = "entityManagerDemo")
    @Primary
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactoryDemo")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(schDataResource)
                .properties(getVendorProperties(schDataResource))
                .packages("com.happygo.sample.domain.sch.entity") //设置实体类所在位置
                .persistenceUnit("schPersistenceUnit")
                .build();
    }

    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

    @Bean(name = "transactionManagerDemo")
    @Primary
    PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

注:@Configuration指定这个bean为配置类,相当于某个Spring xml文件配置,@Bean声明为一个bean,相当于xml中的<bean></bean>,@Primary默认级别,@Profile是一条条件化配置,基于运行时激活的Profile,会使用或者忽略不同的Bean或配置类。@EnableJpaRepositories中的属性entityManagerFactoryRef 对应于xml文件中的红色字体①处,transactionManagerRef对应于②处,basePackages对应于红色字体③处。

1.2.4. @EnableConfigurationProperties

见5.2.简单使用

2. Profile配置

当应用程序需要部署到不同的运行环境时,一些配置细节会有所不同,比如数据连接的细节在开发环境和测试环境下就会不一样,Spring框架从3.1开始支持基于Profile的配置。Profile是一条条件化的配置,基于运行时激活的Profile,会使用或者或略不同的Bean或配置类。

全局Profile配置使用application-{profile}.properties(如application-prod.properties)

1)在apllication.properties添加配置:

spring.profiles.active=dev

2)@Profile在配置类中使用:

@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing=true)
@Profile("dev")
public class HelloServiceAutoConfiguration {
	@Autowired
	private HelloServiceProperties helloServiceProperties;
	
	@Bean
	@ConditionalOnMissingBean(HelloService.class)
	public HelloService helloService(){
		HelloService helloService = new HelloService();
		helloService.setMsg(helloServiceProperties.getMessage());
		return helloService;
	}
}

注:如果Profile=prod(生产环境),这个配置类就会忽略。


3. Spring MVC常用注解

3.1. 注解描述

①@Controller

这个注解我们很常见,加了这个注解我们就知道这是一个控制器,DispatchServlet会自动扫描注解了此注解的类,并将Web请求映射到注解了@RequestMapping的方法上,这里特别指出,在声明普通Bean对象时,使用@Component、@Service、@Repository和@Controller是等同的,因为@Service、@Repository和@Controller都组合了@Component元注解,但在Spring MVC中声明控制器bean,只能只用@Controller

②@RequestMapping

@RequestMapping注解是用来映射Web请求(访问路径和参数)、处理类和方法的。@RequestMapping可注解在类或者方法上,注解在方法上的@RequestMapping路径会继承注解在类上的路径

③ResponseBody

@ResponseBody支持将返回值放在response体内,而不是返回一个页面。此注解可放置在返回值前或者方法上

④RequestBody

@RequestBody允许request的参数在reques体内,而不是链接在地址后面,此注解放置在参数前

⑤@RestController

@RestController是一个组合注解,组合了@Controller和@ResponseBody如果在类中加了@RestController就无需在添加@ResponseBody注解,SpringMVC就会自动将实体对象转换成xml或者json等媒体类型.

3.2. 简单使用

请见(报文转换工程中的controller包)

4. 多数据源配置

4.1. 配置数据源(两个)

@Configuration
public class DataSourceConfig {
    @Bean(name = "primaryDS")  
    @Qualifier("primaryDS")  
    @Primary        @ConfigurationProperties(prefix="spring.primary.datasource")  
    public DataSource primaryDataSource(){  
        return DataSourceBuilder.create().build();  
    }  
  
@Bean(name = "secondaryDS")  
@Qualifier("secondaryDS")    @ConfigurationProperties(prefix="spring.secondary.datasource")  
    public DataSource secondaryDataSource(){  
        return DataSourceBuilder.create().build();  
    }
}

1)将数据源通过java配置的形式配置,数据库的连接地址url、密码、账户等通过注解@ConfigurationProperties绑定,这些属性配置在application.properties文件中

2)@Primary注解为默认级别,加了该注解会默认使用声明的bean

3)@Qualifier注解,如果有多个类型一样的bean,就可以通过@Qualifier注明名称区分

4)DataSourceBuilder类是Spring Boot中提供的用于创建数据源的类

4.2. 配置事务管理器等配置

具体的java配置见1.2.3,下面对1.2.3中的java配置做详细解释

1)片段一

 @Autowired
 private JpaProperties jpaProperties;

说明:Spring Boot启动时会将JPA的默认属性值值与JpaProperties进行关联,如果想改变默认属性值,可以通过在application.properties文件中添加相关属性,前缀必须为spring.jpa,JpaProperties相关属性如下:

spring.jpa.database

要操作的目标数据库,默认自动检测,也可以通过databasePlatform属性设置

spring.jpa.database-platform

要操作的目标数据库,默认自动检测,也可以通过Database枚举设置

spring.jpa.generate-ddl

启动时要初始化schema(默认为false)

spring.jpa.hibernate.ddl-auto

DDL模式(none、validate、update、create和create-drop),这是hibernate.hbm2ddl.atuto属性的一个快捷方式,在使用嵌入式数据库时,默认为create-drop,其他情况为none

spring.jpa.hibernate.naming-strategy

Hibernate命名策略全限定类名

spring.jpa.open-in-view

注册OpenEntityManagerInViewInterceptor,在请求的这个处理过程中,将一个JPAEntityManager绑定到线程(默认值为true)

spring.jpa.properties

JPA提供方要设置的额外原生属性

spring.jpa.show-sql

在使用Bitronix Transaction Manager时打开SQL语句的日志(默认为false)

2)片段二:

private Map<String, String> getVendorProperties(DataSource dataSource){
        return jpaProperties.getHibernateProperties(dataSource);
}

说明:用于获取hibernate出厂属性

3)片段三:

    @Bean(name = "entityManagerFactorySch")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(schDataResource)
                .properties(getVendorProperties(schDataResource))
                .packages("com.happygo.pss.sample.domain.sch.entity") //设置实体类所在位置
                .persistenceUnit("schPersistenceUnit")
         

说明:EntityManagerFactoryBuilder设置数据源,hibernate属性,实体所在包位置及持久化单元,通过build方法返回一个LocalContainerEntityManagerFactoryBean。

片段四:

@Bean(name = "entityManagerSch")
    @Primary
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
 }

说明:通过片段三生成的实体管理工厂类去创建实体管理类,用于对持久化对象进行数据操作。

5. Spring Boot核心注解

5.1. 注解描述

@ConditionalOnBean:当容器里有指定的Bean条件下

@ConditionalOnClass:当类路径下有指定的类的条件下

@ConditionalOnExpression:基于SPEL表达式作为判断条件

@ConditionalOnJava:基于JVM版本作为判断条件

@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置

@ConditionalOnMissingBean:当容器里没有指定Bean的情况下

@ConditionalOnMissingClass:当类路径下没有指定的类的条件下

@ConditionalOnNotWebApplication:当前项目不是web项目的条件下

@ConditionalOnProperty:指定的属性是否有指定的值

@ConditionalOnResource:类路径下是否有指定的值

@ConditionalOnWebApplication:当前项目是Web项目条件下

5.2. 简单使用

自定义自己的自动化配置

1)属性配置

@ConfigurationProperties(prefix="hello")
public class HelloServiceProperties {
	private static final String MSG = "word";
	
	private String message = MSG;

	public String getMessage() {
		return message;
	}

	public void setMessage(String msg) {
		this.message = msg;
	}
}

2)判断依据类

public class HelloService {
	private String msg;
	
	public String sayHello(){
		return "hello " + msg;
	}
	public String getMsg() {
		return msg;
	}
	public void setMsg(String msg) {
		this.msg = msg;
	}
}

3)自动配置类

@Configuration
@EnableConfigurationProperties(HelloServiceProperties.class)
@ConditionalOnClass(HelloService.class)
@ConditionalOnProperty(prefix="hello", value="enabled", matchIfMissing=true)
@Profile("dev")
public class HelloServiceAutoConfiguration {
	@Autowired
	private HelloServiceProperties helloServiceProperties;
	
	@Bean
	@ConditionalOnMissingBean(HelloService.class)
	public HelloService helloService(){
		HelloService helloService = new HelloService();
		helloService.setMsg(helloServiceProperties.getMessage());
		return helloService;
	}
}

注:根据HelloServiceProperties提供的参数,并通过@Conditional判断HelloService这个类是否存在,且当容器中没有这个Bean的情况下自动配置这个Bean。

1)注册配置

若想自动配置生效,需要注册自动配置类,在src/main/resources下新建META-INF/spring.factories,添加如下内容:

com.happygo.samples.config.HelloServiceAutoConfiguration


6.内存数据库

在使用内存数据库的时候,你需要引入H2的依赖包,如果是通过JPA的方式去操作数据库,你需要引入spring-boot-starter-data-jpa起始依赖,H2内存数据库在Spring Boot启动时就能使用,启动时H2采用的是默认配置。

6.1. 实现h2本地化

H2在程序重新启动后,数据就会消失,有些时候我们需要数据能一直存在,那么你就可以在application.properties文件中进行配置:

spring.datasource.url=jdbc:h2:file:D:\\test\\db\\testDB
spring.datasource.username = sa
spring.datasource.password = sa
spring.datasource.driverClassName = org.h2.Driver

6.2. hsqldb替换H2

替换h2使用hsqldb,需要修改maven的pom文件,覆盖掉h2的maven依赖:

<!-- 内存数据库hsqldb --> 
<dependency>
	<groupId>org.hsqldb</groupId>
	<artifactId>hsqldb</artifactId>
	<scope>runtime</scope>
</dependency>

6.@ControllerAdvice

通过@ControllerAdivce,我们可以对于控制台的全局配置放置在一个位置,注解了@Controller的类使用@ExceptionHandler、@InitBinder注解到方法上,这对所有注解了@RequestMapping的控制器内的方法有效。

@ExceptionHandler:用于对全局处理控制器的异常

@InitBinder:用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中

示例:

定制ControllerAdvice

@ControllerAdvice
public class HandleExceptionController {
	
	/**
	 * 捕捉所有Controller中的异常
	 */
	@ResponseBody
	@ExceptionHandler({PatternException.class, BusinessValidateException.class, Exception.class})
	public CommonResult handleException(Exception e){
		CommonResult result = new CommonResult();
	    if(e instanceof PatternException){
			LogUtil.getAppLogger().info("格式校验异常, " + e.getMessage());
			result.setCode(CodeEnum.PATTERN_ERROR.getCode()); 
			result.setMessage(e.getMessage());
	    }else if(e instanceof BusinessValidateException){
			LogUtil.getAppLogger().info("业务校验异常, " + e.getMessage());
			result.setCode(((BusinessValidateException) e).getErrorCode());
			result.setMessage(e.getMessage());
	    }else{
			LogUtil.getAppLogger().error("系统异常, " + e);
			result.setCode(CodeEnum.SYSTEM_ERROR.getCode());
			result.setMessage(CodeEnum.SYSTEM_ERROR.getMessage());
			result.setErrors("系统异常");
	    }
		
		return result;
	}

}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值