目录:
1、spring boot 整合thymeleaf
2、spring boot 整合mysql
3、spring boot 整合mongodb
4、spring boot 整合其它
5、读取配置文件处理
在最近的新项目开发环境搭建过程中,经常会对比较独立的业务进行单独服务化部署。一个项目动辄会被拆分成十多个子系统(子服务),每个子系统都需要进行spring相关配置,无论是采用xml还是java配置方式,都比较繁琐有大量重复copy工作。
采用Srping boot可以大幅度减少依赖包配置,以及版本配置,部分bean可以根据约定的规则自动注入到spring容器(契约式编程),比如自动注入 视图解析器、数据源等等。在减少我们配置工作量的同时,让整个代码工程看起来更加简洁。
总的来说,spring boot主要采用了两种手段来减轻我们的配置工作量:
1、利用包依赖,其实也不是什么先进技术,就是把各个版本一致的jar包整合到一起。比如你只需要引入spring-boot-starter-thymeleaf,就可以自动引入spring mvc相关jar包,以及thymeleaf视图解析器相关jar包。
2、自动发现自动注入bean。比如spring boot启动时如果发现classpath下存在thymeleaf相关jar包,就会把thymeleaf做为视图解析器自动注入到spring容器,而无需我们手动配置。
下面分别来看下spring boot与各种常用工具的整合,文章末尾附整合代码github地址:
1、spring boot 整合thymeleaf
Pom配置
org.springframework.boot spring-boot-starter-parent 1.5.2.RELEASE org.springframework.boot spring-boot-starter-thymeleaf
在顶级pom文件中配置parent,引入spring boot相关的依赖不再需要指定version,
Spring boot会自动引入版本配套的springmvc 以及thymeleaf相关jar包,我们再也不用担心各个版本之间的兼容性问题,全部交由spring boot处理。
在web容器中执行
Spring boot有两种启动方式:
1、通过java –jar运行,spring boot内部自动tomcat web容器,工程打包指定为jar即可。
2、部署到外部tomcat web容器,工程打包指定为war包即可。
由于已经习惯采用war包部署方式,这里在pom文件中指定为war包:
指定启动类,内容如下:
//@Configuration 配置类,类似xml //@EnableAutoConfiguration 启动自动查找配置 //@ComponentScan 扫描自定包 @SpringBootApplication public class BootTestInitializer extends SpringBootServletInitializer{ /** * 让spring boot在tomcat中运行 * @param builder * @return */ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(BootTestInitializer.class); } public static void main(String[] args) { SpringApplication.run(BootTestInitializer.class, args); } }
Spring boot启动类继承自SpringBootServletInitializer 类,定义main方法可以实现java –jar执行,如果要在web容器中执行必须重写protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)方法。
@SpringBootApplication注解相当于三个注解的集合:
1、@Configuration:表示该启动类为配置类(类似xml配置文件),可以通过@bean注解在该类中手动注入bean到spring容器。
2、@EnableAutoConfiguration:spring boot启动自动配置(契约式编程)
3、 @ComponentScan:自动扫描该启动类目录,以及其子目录下 被@Component标记的类,自动实例化并注入到spring 容器。
添加拦截器和静态资源
通过继承WebMvcConfigurerAdapter,重写addInterceptors方法可以实现拦截器添加,重写addResourceHandlers实现静态资源重定位,具体实现如下:
//定义拦截器 public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { //验证权限,使用ThreadLocal等 System.out.println("preHandle:在Controller之前调用,权限验证"); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("postHandle:在Controller之后调用"); } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { //清除ThreadLocal等 System.out.println("afterCompletion:在视图渲染完成之后调用"); } } @Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { /** * 添加拦截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { // addInterceptor方法 可以加入多个拦截器组成一个拦截器链 // addPathPatterns 用于添加拦截规则 // excludePathPatterns 用户排除拦截规则 registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } /** * 指定css,js等静态资源路径 * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/css") .addResourceLocations("classpath:/mystatic/"); } }
Spring boot的默认资源路径跟springmvc不同,webapp不再是其默认资源路径,默认资源路径变为:/META-INF/resources/,/resources/ ,/static/ ,/public/。但我们可以通过重新addResourceHandlers方法进行更改,如上述代码所示。
thymeleaf 视图解析器配置
spring boot默认会自动读取classpath下的application. properties(或application.yml),thymeleaf相关的配置内容如下:
#thymeleaf 配置(用于自动注入 TemplateResolver) spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html spring.thymeleaf.mode=HTML5 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.content-type=text/html spring.thymeleaf.cache=false
spring boot启动时发现thymeleaf相关jar包已经在classpath下,会自动注入thymeleaf视图解析器,需要的配置会自动从application.properties配置文件中获取:凡是以spring.thymeleaf开头的属性配置,会在初始化thymeleaf视图解析器时自动使用。
创建TestController和 thymeleaf模板文件hello.html,spring boot与thymeleaf整合完成,最终的代码结构如下:
到这里 spring boot与thymeleaf的整合完成,只需三步即可以完成:
1、引入spring-boot-starter-thymeleaf这个依赖
2、把thymeleaf需要的配置写入application.properties
3、创建spring boot启动类
2、spring boot 整合mybatis(mysql)
生产环境一般都会用连接池,这里以mybatis整合dbcp2连接池,连接mysql数据库为例。
首先看下pom.xml配置,只需引入三个依赖:
org.mybatis.spring.boot mybatis-spring-boot-starter mysql mysql-connector-java org.apache.commons commons-dbcp2
然后在application. properties中进行:mybatis配置、mysql数据源配置、dbcp2连接池配置。
#mybatis配置(其他属性查看MybatisProperties成员变量) mybatis.type-aliases-package=com.sky.boot.domain.mysql mybatis.mapper-locations=classpath:mapper/**/*Mapper.xml #mysql数据源配置(其他属性查看DataSourceProperties成员变量) spring.datasource.driverClassName = com.mysql.jdbc.Driver spring.datasource.url = jdbc:mysql:loadbalance://192.168.0.100:3306/test_dec?useUnicode=true&characterEncoding=UTF8 spring.datasource.username = test spring.datasource.password = test #dbcp2连接池配置(其他属性查看BasicDataSource成员变量) spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource spring.datasource.dbcp2.initial-size=5 spring.datasource.dbcp2.min-idle=5 spring.datasource.dbcp2.max-idle=10 spring.datasource.dbcp2.max-total=30
在spring boot中整合mybatis+dbcp2连接池+mysql,需要你做的也就这么多了。Spring boot发现classpath路径下有mybatis、dbcp、以及mysql jdbc相关的jar包,会自动注入数据库连接池相关的dbcp mysql连接池、并自动与mybastis整合。
这里笔者还采用mybatis自动生成代码工具mybatis-generator,自动生成mybatis xml配置、数据库表vo、mybatis mapper接口。具体代码从文章末尾的github地址中获取。
另外为了配合使用自动生成的mybatis代码,还需要在spring boot启动类中添加mapper接口扫描注解@MapperScan,在程序启动时 该注解会扫描指定路径下的mapper接口类,并自动为其生成实现类注入到spring 容器,如下:
@SpringBootApplication @MapperScan("com.sky.boot.dao.mysql") public class BootTestInitializer extends SpringBootServletInitializer{ //省略代码 }
到这里spring boot与mybatis、dbcp mysql数据库连接池整合完毕,需要我们做的也就是添加需要的jar包,并把相关的配置添加到application. properties配置文件
3、spring boot 整合mongodb
按照整合套路,首先引入mongodb相关的jar包,其实只需要一个依赖:
org.springframework.boot spring-boot-starter-data-mongodb
然后在application. properties配置文件中添加相关配置:
#mongdb相关配置(其他属性查看MongoProperties成员变量) spring.data.mongodb.host=192.168.0.100 spring.data.mongodb.port=27017 spring.data.mongodb.database=mongodb_test spring.data.mongodb.username=passport spring.data.mongodb.password=passport
整合mongodb需要我们做的也就这么多了,其它工作全部交给spring boot即可。
下列来看一个使用mongodb的案例,这里模拟一个订单的生成和查询,订单类Order 里面包含多个商品product,如下:
@Document(collection="order_info") public class Order { @Id private String id; @Field("client") private String customer; private String desc; private Collectionproducts = new LinkedHashSet (); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCustomer() { return customer; } public void setCustomer(String customer) { this.customer = customer; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public Collection getProducts() { return products; } public void setProducts(Collection products) { this.products = products; } public void put(Product product){ this.products.add(product); } }
public class Product { private Long id; private String name; private double price; private int num; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } }
@Document(collection="order_info")注解表示Order类对应的是一个mongodb中的文档,文档的名称为"order_info"(可以理解为mysql中的表)。
然后使用spring data mongodb Repository定义一个操作该文档的接口类:
public interface OrderRepository extends MongoRepository{ }
在Controller中,使用OrderRepository往mongodb中添加和查询订单信息:
@Controller @RequestMapping("/") public class TestController { @Resource private OrderService orderService; @RequestMapping("/mongodb") public String mongdb(Mapmap){ Order order = new Order(); order.setId("10000"); order.setCustomer("zhang san"); order.setDesc("一个订单"); Product p1 = new Product(); p1.setId(1111l); p1.setName("小鸡手机"); p1.setPrice(1000); p1.setNum(1); Product p2 = new Product(); p2.setId(2222l); p2.setName("小小鸡手机"); p2.setPrice(1000); p2.setNum(1); order.put(p1); order.put(p2); orderService.save(order); Order o1=orderService.getOrder("10000"); map.put("order",o1); return "mongdb"; } }
使用MongoVUE可以化工具查看 刚才插入的Order记录:
比直接使用mongoTemplate操作起来简单了很多。
spring boot 整合其它
通过上述的讲解,也许大家已经发现了,对应spring boot已经整合的常用框架,我们可以直接引入相关的spring boot jar依赖,并配置application. properties配置文件即可。具体spring boot已经整合了那些框架(或者说组件),可以参考spring boot官方文档:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-connecting-to-mongodb,打开该链接页面的最末尾。
对于spring boot没有实现自动整合的框架,我们可以通过java bean配置的方式,把所需的bean注入spring容器。
这里以模拟整合dubbo rpc框架为例:
首先:引入dubbo相关的jar包(这里只是模拟,没有真实引入)。
然后:配置application. properties配置文件,内容如下:
#dubbo相关配置,假设只需要下列两个配置 dubbo.zkAddress=xxxxxxxx dubbo.alias=test-group
最后:新建一个 spring bean配置类:
@Configuration @ConfigurationProperties(prefix = "dubbo") public class DubboConfig { private String zkAddress; private String alias; @Bean public OneService oneService(){ OneService oneService= new OneService(zkAddress,alias); return oneService; } public void setZkAddress(String zkAddress) { this.zkAddress = zkAddress; } public void setAlias(String alias) { this.alias = alias; } }
通过@ConfigurationProperties(prefix = "dubbo")注解,spring boot会自动读取application. properties配置文件中,前置为dubbo的配置,并把前面配置的两个数据,自动复制给zkAddress,alias。然后通过@Bean注解的oneService()方法,会生成一个单例的OneService对象 并注入到spring容器。在需要使用该Service的地方,直接通过@Resource(或@ Autowired)注解注入 即可使用。
@Controller @RequestMapping("/") public class TestController { @Resource private OneService oneService; @RequestMapping("/dubbo") public String dubbo(Mapmap){ map.put("dubbo",oneService.getPrice()); return "dubbo"; } }
这里只是模拟整合注入Dubbo,注入一个Dubbo的Service。其实采用这种方式可以完成,各种自定义框架的注入,唯一需要多处理的就是添加一个配置类(跟spring的xml配置方式等效)。
5、读取配置文件处理
在spring的java bean中使用.properties配置文件中的属性,有两种方式:
1、在java bean中,使用spring中的Environment。
首先采用xml配置placeholder
使用方式
@Resource Environment env; //省略 String value =env.containsProperty("key"); //省略
2、使用@Value注解
跟前一种方式一样,首先采用xml配置placeholder
在java bean的属性或者参数上使用@Value注解
@Value( "${key}" ) private String value;
两种方式中的xml配置方式,可以改为java bean配置方式,使用@PropertySource注解:
@Configuration @PropertySource("classpath:xxxxx.properties") public class PropertiesConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } }
3、spring boot中使用配置
最后再来看下 spring boot读取配置的方式,spring boot会默认自动读取application. properties和application.yml配置文件。自定义的属性key不要覆盖spring boot默认的整合的key,比如spring.datasource.*,这种开头的key,spring boot会默认读取出来生成数据源使用。本周上述内容都是以application. properties进行讲解,其实application.yml看起更简洁些:
spring: datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql:loadbalance://192.168.0.100:3306/test_dec?xxxxxxx username: test password: test
@ConfigurationProperties注解不指定配置文件,会默认读取application. properties和application.yml。但如果application. properties和application.yml在同一目录下使用,application.yml不会生效(不同目录下有优先级先后顺序,个人觉得不必去深究,实际运用中二选一即可)。
通过@ConfigurationProperties注解的bean中,可以把值自动注入到对应的成员变量,但必须要有setter方法;也可以用@Value注解获取,可以不用实现setter方法,如下zkAddress和alias都可以被注入:
@Configuration @ConfigurationProperties(prefix = "dubbo") public class DubboConfig { private String zkAddress; @Value("${alias}") private String alias; public void setZkAddress(String zkAddress) { this.zkAddress = zkAddress; } }
对于自定义的.properties文件,也可以通过@ConfigurationProperties注解进行指定读取:
@Configuration @ConfigurationProperties(value=" classpath:xxxxx.properties",prefix = "dubbo") public class DubboConfig { //省略代码 }
也就是说在spring boot 的java bean中读取配置文件,除了前面提到的两种方式,还提供第三种方式:@ConfigurationProperties注解,在spring boot中也推荐使用@ConfigurationProperties注解方式。
最后文章讲解的代码地址:https://github.com/gantianxing/boot-test.git,把application.properties配置文件中的mysql、mongo相关信息 替换成自己的,即可启动直接运行。