SpringBoot实战总汇--详解

 

简介  

Spring 诞生时是 Java 企业版(Java Enterprise EditionJEE,也称 J2EE)的

轻量级代替品。无需开发重量级的 Enterprise JavaBeanEJB),Spring 为企业级

Java 开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java 对象(Plain Old Java ObjectPOJO)实现了 EJB 的功能。

 

springboot起步

  1、添加依赖

  

pom.xml中添加依赖

 

 

org.springframework.boot

 

spring-boot-starter-parent

 

1.4.4.RELEASE

 

 

com.huiyang.springboot

 

huiyang-springboot

 

0.0.1-SNAPSHOT

 

 

 

 

 

org.springframework.boot

 

spring-boot-starter-web

 

 

这样就将简单的web服务依赖所需的jar包添加完毕,是不是很简单,注意是springboot默认的jdk版本是1.6,官方推荐使用1.8版本,所以需要添加

1.8

2、引导类

  
  引导类是springboot服务启动的开端:

  

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication

public class Demo {

 

public static void main(String[] args) {

SpringApplication.run(Demo.class, args);

}

}

它会扫描本包下所有类和子包,所以只需要将controller层,service层,dao层放到同级目录或者子包下即可,不需要添加扫描;

 

Springboot的整合

 

1.1. 整合MyBatis

1.1.1. 环境准备

1.1.1.1. 导入数据库表

MySQL数据库执行以下语句

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `username` varchar(100) DEFAULT NULL COMMENT '用户名',

  `password` varchar(100) DEFAULT NULL COMMENT '密码',

  `name` varchar(100) DEFAULT NULL COMMENT '姓名',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

 

INSERT INTO `user` VALUES ('1', 'zhangsan', '123456', '张三');

INSERT INTO `user` VALUES ('2', 'lisi', '123456', '李四');

INSERT INTO `user` VALUES ('3', 'wangwu', '123456', '王五');

INSERT INTO `user` VALUES ('4', 'zhangwei', '123456', '张伟');

INSERT INTO `user` VALUES ('5', 'lina', '123456', '李娜');

INSERT INTO `user` VALUES ('6', 'lilei', '123456', '李磊');

 

1.1.1.2. 加入MyBatis的启动器

pom.xml中加入如下依赖

org.mybatis.spring.boot

mybatis-spring-boot-starter

1.1.1

 

mysql

mysql-connector-java

 

1.1.1.3. 加入配置文件

src/main/resources 下添加application.properties 配置文件,内容如下:

#DB Configuration:

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/huiyang?useUnicode=true&characterEncoding=utf8

spring.datasource.username=root

spring.datasource.password=root

 

1.1.2. 简单整合

1.1.2.1. 创建pojo

public class User {

// 主键

private Long id;

// 用户名

private String username;

// 密码

private String password;

// 姓名

private String name;

get/set。。。。。。

}

 

1.1.2.2. 编写Mapper

和之前的方式一样,只是多了两个注解

@Mapper:声明Mapper接口

@Select声明这个接口所需要使用的sql当然查询的注解,肯定就有增删改的注解。

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import org.apache.ibatis.annotations.Select;

import com.huiyang.info.pojo.User;

 

@Mapper

public interface UserMapper {

 

@Select("select * from user where name like '%${value}%'")

public List queryUserByName(String name);

 

}

 

1.1.2.3. 编写Service

编写Service接口

import java.util.List;

import com.huiyang.info.pojo.User;

 

public interface UserService {

List queryUserByName(String name);

}

 

编写Service实现类

@Service

public class UserServiceImpl implements UserService {

 

@Autowired

private UserMapper userMapper;

 

@Override

public List queryUserByName(String name) {

List list = this.userMapper.queryUserByName(name);

return list;

}

}

 

1.1.2.4. 编写Controller

编写Controller

@RestController

@RequestMapping("user")

public class UserControlelr {

 

@Autowired

private UserService userService;

 

@RequestMapping("list/{name}")

public List queryUserByName(@PathVariable String name) {

List list = this.userService.queryUserByName(name);

return list;

}

}

 

1.1.2.5. 测试

浏览器地址栏输入:http://localhost:8080/user/list/

显示效果:

 

 

1.1.3. 整合通用Mapper和分页助手

以上所有的配置都是使用的默认配置,我们只需要专注java代码的开发即可,不需要加入配置文件了。

 

但并不是所有得场景都是简单的业务,有时候业务复杂,需要我们加入自定义的配置文件;有时候需要载入例如分页助手这样的插件,辅助开发,所以我们也需要了解如何加载这些配置。

 

需求:

  1. 实现用户分页查询接口(通用Mapper和分页助手实现)
  2. 使用Spring Boot + Spring MVC + MyBatis + EasyUI 实现用户列表查询,

效果如下:

 

 

1.1.3.1. 加入依赖

我们需要加入通用Mapper和分页插件,所以需要在pom.xml加入以下依赖

com.github.abel533

mapper

2.3.4

com.github.pagehelper

pagehelper

3.7.5

com.github.jsqlparser

jsqlparser

0.9.1

 

1.1.3.2. 修改配置文件

application.properties添加配置

#spring集成Mybatis环境

#pojo别名扫描

mybatis.type-aliases-package=com.huiyang.springboot.pojo

#加载Mybatis核心配置文件

mybatis.mapper-locations=classpath:mapper/*Mapper.xml

mybatis.config-location=classpath:mybatis/SqlMapConfig.xml

#配置连接池,还需要在pom.xml中加入该连接池的依赖

#spring.datasource.type=com.jolbox.bonecp.BoneCPDataSource

 

src\main\resources\mapper路径下加入UserMapper.xml配置文件

"1.0" encoding="UTF-8" ?>

"com.huiyang.springboot.mapper.UserMapper">

"queryAll" resultType="user">

select * from user

 

src\main\resources\mybatis加入SqlMapConfig.xml配置文件,以加载通用Mapper和分页助手

"1.0" encoding="UTF-8" ?>

  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-config.dtd">

"com.github.pagehelper.PageHelper">

"dialect" value="mysql" />

"rowBoundsWithCount" value="true" />

 

"com.github.abel533.mapperhelper.MapperInterceptor">

"IDENTITY" value="MYSQL" />

"mappers" value="com.github.abel533.mapper.Mapper" />

 

1.1.3.3. 编写Mapper

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

import org.apache.ibatis.annotations.Select;

import com.huiyang.info.pojo.User;

 

//extends com.github.abel533.mapper.Mapper:需要继承通用Mapper

@Mapper

public interface UserMapper extends com.github.abel533.mapper.Mapper {

 

@Select("select * from user where name like '%${value}%'")

public List queryUserByName(String name);

 

// 使用UserMapper.xml配置文件

public List queryAll();

}

 

1.1.3.4. 编写Service

编写Service接口

import java.util.List;

import com.huiyang.info.pojo.User;

 

public interface UserService {

 

List queryUserByName(String name);

List queryAll();

List queryUserByPage(Integer page, Integer rows);

}

 

Service实现类编写

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;

import com.huiyang.info.dao.UserMapper;

import com.huiyang.info.pojo.User;

import com.huiyang.info.service.UserService;

 

@Service("userServiceImpl")

public class UserServiceImpl implements UserService {

 

@Autowired

private UserMapper userMapper;

 

@Override

public List queryUserByName(String name) {

List list = this.userMapper.queryUserByName(name);

return list;

}

 

// 调用使用UserMapper.xmlMapper

@Override

public List queryAll() {

List list = this.userMapper.queryAll();

return list;

}

 

// 使用通用Mapper和分页助手

@Override

public List queryUserByPage(Integer page, Integer rows) {

// 设置分页

PageHelper.startPage(page, rows);

// 使用通用Mapper的方法进行查询所有数据

List list = this.userMapper.select(null);

return list;

}

}

 

1.1.3.5. 编写Controller

Controller编写

import java.util.List;

 

import javax.annotation.Resource;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.env.Environment;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

import com.huiyang.info.pojo.User;

import com.huiyang.info.service.UserService;

 

@RestController

@RequestMapping("user")

public class UserControlelr {

 

@Autowired

private UserService userService;

 

@RequestMapping("list/{name}")

public List queryUserByName(@PathVariable String name) {

List list = this.userService.queryUserByName(name);

return list;

}

 

@RequestMapping("list")

public List queryAll() {

List list = this.userService.queryAll();

return list;

}

 

@RequestMapping("list/{page}/{rows}")

public List queryUserAll(@PathVariable Integer page, @PathVariable Integer rows) {

List list = this.userService.queryUserByPage(page, rows);

return list;

}

 

}

 

1.1.3.6. 前端实现

把资料中的static文件夹,拷贝src/main/resources路径下

 

 

注意:

放在src/main/resources/static路径下的资源可以直接访问

 

1.1.3.7. 测试

测试使用通用Mapper和分页助手

浏览器地址栏输入:http://127.0.0.1:8080/user/list/2/2

 

 

测试使用UserMapper.xml

浏览器地址栏输入:http://localhost:8080/user.html

 

 

1.2. 整合Redis

1.2.1. 注解方式实现添加缓存

需求:基于上例代码,将列表数据缓存到Redis

1.2.1.1. 加入依赖

pom.xml加入依赖

org.springframework.boot

spring-boot-starter-redis

 

1.2.1.2. 修改引导类

修改开启缓存,添加注解@EnableCaching

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cache.annotation.EnableCaching;

 

@SpringBootApplication

@EnableCaching

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

 

}

 

1.2.1.3. 设置实现序列化接口

要缓存到redis中的实体,需要实体实现序列化接口

public class User implements Serializable {

private Long id;

private String userName;

private String password;

private String name;

 

。。。。。

}

 

1.2.1.4. 实现添加/删除缓存

修改UserServiceImpl

添加@Cacheable注解实现缓存添加

@Cacheable注解有三个参数,value是必须的,还有key和condition。第一个参数,也就是value指明了缓存将被存到什么地方

任何存储在缓存中的数据为了高速访问都需要一个key。spring默认使用被@Cacheable注解的方法的签名来作为key,当然你可以重写key,自定义key可以使用SpEL表达式。

?

1

2

3

4

@Cacheable(value = "employee", key = "#surname")   publicPerson findEmployeeBySurname(String firstName, String surname, intage) {

 

    returnnew Person(firstName, surname, age);

  }

       在findEmployeeBySurname()的注解中"#surname"是一个SpEL表达式,他将使用findEmployeeBySurname()方法中的surname参数作为key。

  @Cacheable的最后一个参数是condition(可选),同样的,也是引用一个SpEL表达式。但是这个参数将指明方法的返回结果是否被缓存。

添加@CacheEvict注解实现缓存删除

@Override

@CacheEvict(value = "userCache", key = "'user.queryAll'")

public List queryUserByName(String name) {

System.out.println("缓存清理了!");

List list = this.userMapper.queryUserByName(name);

return list;

}

 

// 调用使用UserMapper.xmlMapper

@Override

@Cacheable(value = "userCache", key = "'user.queryAll'")

public List queryAll() {

System.out.println("MySQL中查询");

List list = this.userMapper.queryAll();

return list;

}

这样设置完成后,执行queryAll()方法就会使用缓存,如果缓存没有就添加缓存,queryUserByName(String name)方法则是删除缓存

 

@Cacheable:添加/使用缓存

@CacheEvict删除缓存

参数value是缓存的名字,在执行的时候,找叫这个名字的缓存使用/删除

参数key默认情况下是空串””,Spring的一种表达式语言SpEL我们这里可以随意指定,但是需要注意一定要加单引号

 

1.2.2. redis的深入使用

1.2.2.1. 直接操作redis

redis除了作为缓存使用,还有很多其他的作用,例如利用redis的单线程获取唯一数,例如使用redis为单点登录系统存储用户登录信息等,我们就需要直接操作redis

 

官网提供了三种接口RedisConnectionFactory, StringRedisTemplate  RedisTemplate我们可以直接注入或者自己实现其他的实现类,直接操作redis。我们这里使用RedisTemplate来操作Redis

 

如下所示,我们只需要直接注入RedisTemplate即可使用以下方法操作redis的五种不同的数据类型

 

 

测试:

@Autowired

private RedisTemplate redisTemplate;

 

@Override

@CacheEvict(value = "userCache", key = "'user.findAll'")

public List queryUserByName(String name) {

// 保存数据

this.redisTemplate.boundValueOps("redis").set("Hello redis !");

// 设置有效时间为100

this.redisTemplate.boundValueOps("redis").expire(100l, TimeUnit.SECONDS);

// value每次执行加一操作

this.redisTemplate.boundValueOps("count").increment(1l);

 

System.out.println("缓存清理了!");

List list = this.userMapper.queryUserByName(name);

return list;

}

 

1.2.2.2. 设置redis连接属性

redis单机版

redis启动器默认情况下会找本地的redis服务,端口号默认是6379如果需要访问其他服务器的redis需要在application.properties中进行如下配置:

#Redis

spring.redis.host=192.168.37.161

spring.redis.port=6379

这表示会去找ip192.168.37.161和端口为6379的服务

 

redis集群版

#Redis

#spring.redis.host=192.168.37.161

#spring.redis.port=6379

 

#Redis Cluster

spring.redis.cluster.nodes=192.168.37.161:7001,192.168.37.161:7002,192.168.37.161:7003,192.168.37.161:7004,192.168.37.161:7005,192.168.37.161:7006

切换到集群版只需要做以上配置,配置集群版节点信息,注释掉单机版信息

 

1.3. 整合ActiveMQRebbitMQ

1.3.1. 加入依赖

pom.xml中加入以下配置

org.springframework.boot

spring-boot-starter-activemq

 

1.3.2. 创建队列

在引导类中添加以下方法,设置队列

@SpringBootApplication

@EnableCaching

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

 

@Bean

public Queue queue() {

return new ActiveMQQueue("huiyang.queue");

}

 

}

 

1.3.3. 发送消息

编写Controller发送消息

import javax.jms.Destination;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jms.core.JmsTemplate;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

@RequestMapping("queue")

public class QueueController {

 

//注入发送消息的对象

@Autowired

private JmsTemplate jmsTemplate;

 

//注入消息队列

@Autowired

private Destination destination;

 

//编写发送消息的方法

@RequestMapping("send/{message}")

public String send(@PathVariable String message) {

this.jmsTemplate.convertAndSend(destination, message);

return "消息发送成功!消息内容:" + message;

}

 

}

 

1.3.4. 接收消息

编写bean加入@Component注解让spring管理这个bean,作为接收消息的消费者

package com.huiyang.info.queue;

 

import org.springframework.jms.annotation.JmsListener;

import org.springframework.stereotype.Component;

 

@Component

public class Consumer {

// 接受消息方法

@JmsListener(destination = "huiyang.queue")

public void readMessage(String text) {

System.out.println("接受到的消息是:" + text);

}

}

 

测试:

启动服务后,在浏览器输入以下地址

http://127.0.0.1:8080/queue/send/发消息了11

 

显示效果:

 

即可看到消息发送成功

 

同时可以在控制台看到以下打印信息

 

 

我们没有安装ActiveMQ为什么可以使用?因为Spring Boot 内置了ActiveMQ 的服务,所以我们不用单独启动也可以实现消息的发送和接收。

 

1.3.5. 使用外部服务

首先确认有一台外部ActiveMQ服务可以使用

 

 

application.properties中加入以下配置

#ActiveMQ

spring.activemq.broker-url=tcp://192.168.37.161:61616

 

这样就加入了ActiveMQ服务的地址

1.3.6. RebbitMq

添加依赖

       org.springframework.boot

       spring-boot-starter-amqp

1.3.6.1. 需要在启动类上添加

@SpringBootApplication

@EnableScheduling//启用任务调度.

(4) 配置信息

所以spring boot提供了默认的配置,那么我们应该怎么修改配置呢,只需要在application.properties进行配置即可:

# RABBIT (RabbitProperties) 

spring.rabbitmq.host= # connection host 

spring.rabbitmq.port=# connection port 

spring.rabbitmq.addresses= # connection addresses (e.g. myhost:9999,otherhost:1111) 

spring.rabbitmq.username= # login user 

spring.rabbitmq.password= # login password 

spring.rabbitmq.virtualhost= 

spring.rabbitmq.dynamic= 

1.3.7. 使用纯注解的形式开发

  • RabbitMQ
    i. 配置

    org.springframework.boot

    spring-boot-starter-amqp

 

  • ii.实现方式 RabbitMQDemoConfigration.java
  • import org.springframework.amqp.core.*;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/**

* RabbitMQDemo

*

* @author: sunjie

* @date: 16/01/10

*/

@Configuration

@SuppressWarnings("SpringJavaAutowiringInspection")public class RabbitMQDemoConfigration {

@Bean

 public CachingConnectionFactory myConnectionFactory() {

     CachingConnectionFactory connectionFactory = new CachingConnectionFactory();

     connectionFactory.setUsername("guest");

     connectionFactory.setPassword("guest");

     connectionFactory.setHost("192.168.1.1");

     connectionFactory.setPort(5672);

     connectionFactory.setVirtualHost("/myHost");

     return connectionFactory;

 }

 

 //  生成CachingConnectionFactory  也可以使用下面的方式,在application.properties

 //  中定义好属性即可

 

 //     @Autowired

 //    ConnectionFactory connectionFactory;@Bean

 public DirectExchange myExchange() {

     return new DirectExchange("myExchangeDemo", true, false);

 }

 

 @Bean

 public Queue myQueue() {

     return new Queue("myQueueDemo", true);

 }

 

 @Bean

 public Binding myExchangeBinding(@Qualifier("myExchange") DirectExchange directExchange,

                                  @Qualifier("myQueue") Queue queue) {

     return BindingBuilder.bind(queue).to(directExchange).with("routeDemo");

 }

 

 @Bean

 public RabbitTemplate myExchangeTemlate() {

     RabbitTemplate r = new RabbitTemplate(myConnectionFactory());

     r.setExchange("myExchangeDemo");

     r.setRoutingKey("routeDemo");

     return r;

 }

/**

  *  发送消息,工业使用需要自己做个性化实现

  */

 @Bean

 public void sendMessage(RabbitTemplate myExchangeTemlate) {

     String string = "Hello RabbitmQ";

     myExchangeTemlate.convertAndSend(string);

 }

 

 /**

  *  接受消息,工业使用时需要在监听类中实现process逻辑

  */

 @RabbitListener(queues = "myQueueDemo")

 public void process(Message message) {

     System.out.println("__________" + message.getBody().toString() + "__________");

     try {

         this.wait(1000);

     } catch (InterruptedException e) {

         e.printStackTrace();

     }

 }

 

1.4. 整合junit

1.4.1. 加入依赖

pom.xml中加入测试依赖

org.springframework.boot

spring-boot-starter-test

test

 

1.4.2. 编写测试类

import javax.jms.Destination;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.jms.core.JmsTemplate;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

import com.huiyang.info.Application;

 

@RunWith(SpringJUnit4ClassRunner.class)

@SpringBootTest(classes = Application.class)

public class MessageTest {

 

@Autowired

private Destination destination;

 

@Autowired

private JmsTemplate jmsTemplate;

 

@Test

public void test() {

System.out.println("我发消息了!");

this.jmsTemplate.convertAndSend(destination, "Hello ActiveMQ!");

}

 

}

SpringRunner SpringJUnit4ClassRunner 是继承关系,但是没有不同的地方,只是看起来子类SpringRunner要短一些而已。

 

@SpringBootTest 注解的class 属性要指定引导类的class

 

1.5. 整合FreeMarker

1.5.1. 加入依赖

org.springframework.boot

spring-boot-starter-freemarker

 

1.5.2. 编写测试类

import java.util.Date;

import java.util.Map;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

 

@Controller

@RequestMapping("fm")

public class FreeMarkerController {

 

@RequestMapping

public String fm(Map root) {

root.put("name", "张三");

root.put("date", new Date());

 

return "template";

}

}

 

1.5.3. 编写模板

src\main\resources\templates路径下创建template.ftl模板,内容如下:

Hello  ${name} !

 

当前时间是

${date?datetime}

 

启动引导类测试效果:

 

 

1.1. 整合Solr

1.5.4. 加入依赖

org.springframework.boot

spring-boot-starter-data-solr

 

1.5.5. 修改配置文件

application.properties添加配置

#solr配置

spring.data.solr.host=http://127.0.0.1:8081/solr

 

1.5.6. 编写Controller

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

 

import org.apache.solr.client.solrj.SolrClient;

import org.apache.solr.client.solrj.SolrQuery;

import org.apache.solr.client.solrj.response.QueryResponse;

import org.apache.solr.common.SolrDocument;

import org.apache.solr.common.SolrDocumentList;

import org.apache.solr.common.SolrInputDocument;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

 

@Controller

@RequestMapping("solr")

public class SolrController {

 

@Autowired

private SolrClient solrClient;

 

@RequestMapping("query/{data}")

public String query(@PathVariable String data, Map root) throws Exception {

// 查询solr

SolrQuery solrQuery = new SolrQuery("title:" + data);

QueryResponse response = this.solrClient.query(solrQuery);

SolrDocumentList results = response.getResults();

 

// 解析查询结果

List list = new ArrayList();

for (SolrDocument solrDocument : results) {

list.add(solrDocument.get("title").toString());

}

 

// 传递数据

root.put("total", results.getNumFound());

root.put("list", list);

 

return "solr";

 

}

 

@RequestMapping("save/{id}/{title}")

@ResponseBody

public String save(@PathVariable String id, @PathVariable String title) throws Exception {

SolrInputDocument doc = new SolrInputDocument();

doc.addField("id", id);

doc.addField("title", title);

 

this.solrClient.add(doc);

this.solrClient.commit();

 

return "保存成功";

 

}

 

}

 

1.5.7. 编写展示模板

src\main\resources\templates路径下创建solr.ftl模板,内容如下

查询到了${total}条数据


查询结果如下:

<#list list as l >


${l}

 

运行引导类

 

访问地址:http://localhost:8080/solr/query/测试,得到如下结果:

 

 

访问地址: http://localhost:8080/solr/query/save/s001/solr测试,查看索引库数据保存成功。

 

1.6. 整合dubbox

1.6.1. 环境准备

1.6.1.1. dubbox

dubbo是一个分布式的服务架构,可直接用于生产环境作为SOA服务框架。官网首页:http://dubbo.io/  

 

淘宝将这个项目开源出来以后,得到了不少同行的支持,包括:

当当网的扩展版本dubbox https://github.com/dangdangdotcom/dubbox

京东的扩展版本jd-hydra: http://www.oschina.NET/p/jd-hydra

 

不过,略有遗憾的是, dubbo由于某些原因导致dubbo团队已经解散,已经很牛没有更新了,反到是当当网的扩展版本仍在持续发展。因为dubbox支持更新的spring版本,所以我们使用dubbox

 

Dubboxmaven中央仓库并没有对应的依赖,所以我们需要自己动手将其发布到我们的本地仓库来使用。

 

使用git从码云上把dubbox的代码clone下来,

地址https://git.oschina.net/wuyu15255872976/dubbox.git

 

执行Maven命令把工程安装到本地仓库

命令:clean install -Dmaven.test.skip

 

课程资料提供的仓库已经安装好了,可以直接使用

 

1.6.1.2. spring-boot-starter-dubbo

我们以前在使用dubbo的时候都是用的xml配置。而在整合Spring Boot的时候可以使用@ImportResource注解来引入的dubboxml配置。

但是Spring Boot本身并不推荐xml配置。怎么解决这个矛盾,我们可以自己准备一个Spring Boot Starter dubbo的项目来引导Spring BootDubbo的自动化配置。已经有人开发好了这个自动化配置项目,我们直接使用就行了

 

使用git从码云上把spring-boot-starter-dubbo的代码clone下来,

地址https://git.oschina.net/wuyu15255872976/spring-boot-starter-dubbo.git

 

执行Maven命令把工程安装到本地仓库

命令:clean install -Dmaven.test.skip

 

为了统一管理,pom.xml修改为如下:

"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

1.4.4.RELEASE

spring-boot-starter-dubbo

1.4.4.RELEASE

Spring Boot Dubbo Rpc

Spring Boot Dubbo Rpc

http://projects.spring.io/spring-boot/

Pivotal Software, Inc.

http://www.spring.io

UTF-8

1.7

 

    

org.springframework.boot

spring-boot-actuator

org.springframework.boot

spring-boot-configuration-processor

com.alibaba

dubbo

2.8.5-SNAPSHOT

spring

org.springframework

com.github.sgroschupf

zkclient

0.1

org.springframework.boot

spring-boot-dependencies

1.4.4.RELEASE

pom

import

 

maven-source-plugin

true

compile

jar

 

课程资料提供的仓库已经安装好了,可以直接使用

 

## Dubbo 应用配置

# 应用名称

spring.dubbo.application.name=xxx

 

# 模块版本

spring.dubbo.application.version=xxx

 

# 应用负责人

spring.dubbo.application.owner=xxx

 

# 组织名(BU或部门)

spring.dubbo.application.organization=xxx

 

# 分层

spring.dubbo.application.architecture=xxx

 

# 环境,如:dev/test/run

spring.dubbo.application.environment=xxx

# Java代码编译器

spring.dubbo.application.compiler=xxx

 

# 日志输出方式

spring.dubbo.application.logger=xxx

 

# 注册中心 0

spring.dubbo.application.registries[0].address=zookeeper:#127.0.0.1:2181=xxx

# 注册中心 1

spring.dubbo.application.registries[1].address=zookeeper:#127.0.0.1:2181=xxx

# 服务监控

spring.dubbo.application.monitor.address=xxx

## Dubbo 注册中心配置类

# 注册中心地址

spring.dubbo.application.registries.address=xxx

 

# 注册中心登录用户名

spring.dubbo.application.registries.username=xxx

 

# 注册中心登录密码

spring.dubbo.application.registries.password=xxx

 

# 注册中心缺省端口

spring.dubbo.application.registries.port=xxx

 

# 注册中心协议

spring.dubbo.application.registries.protocol=xxx

 

# 客户端实现

spring.dubbo.application.registries.transporter=xxx

spring.dubbo.application.registries.server=xxx

 

spring.dubbo.application.registries.client=xxx

 

spring.dubbo.application.registries.cluster=xxx

 

spring.dubbo.application.registries.group=xxx

 

spring.dubbo.application.registries.version=xxx

 

# 注册中心请求超时时间(毫秒)

spring.dubbo.application.registries.timeout=xxx

# 注册中心会话超时时间(毫秒)

spring.dubbo.application.registries.session=xxx

 

# 动态注册中心列表存储文件

spring.dubbo.application.registries.file=xxx

 

# 停止时等候完成通知时间

spring.dubbo.application.registries.wait=xxx

 

# 启动时检查注册中心是否存在

spring.dubbo.application.registries.check=xxx

 

# 在该注册中心上注册是动态的还是静态的服务

spring.dubbo.application.registries.dynamic=xxx

 

# 在该注册中心上服务是否暴露

spring.dubbo.application.registries.register=xxx

 

# 在该注册中心上服务是否引用

spring.dubbo.application.registries.subscribe=xxx

 

# 服务协议

spring.dubbo.application.protocol.name=xxx

 

# 服务IP地址(多网卡时使用)

spring.dubbo.application.protocol.host=xxx

 

# 服务端口

spring.dubbo.application.protocol.port=xxx

 

# 上下文路径

spring.dubbo.application.protocol.contextpath=xxx

 

# 线程池类型

spring.dubbo.application.protocol.threadpool=xxx

 

# 线程池大小(固定大小)

spring.dubbo.application.protocol.threads=xxx

# IO线程池大小(固定大小)

spring.dubbo.application.protocol.iothreads=xxx

 

# 线程池队列大小

spring.dubbo.application.protocol.queues=xxx

 

# 最大接收连接数

spring.dubbo.application.protocol.accepts=xxx

 

# 协议编码

spring.dubbo.application.protocol.codec=xxx

 

# 序列化方式

spring.dubbo.application.protocol.serializatio

# 字符集

spring.dubbo.application.protocol.charset=xxx

 

# 最大请求数据长度

spring.dubbo.application.protocol.payload=xxx

 

# 缓存区大小

spring.dubbo.application.protocol.buffer=xxx

 

# 心跳间隔

spring.dubbo.application.protocol.heartbeat=xxx

# 访问日志

spring.dubbo.application.protocol.accesslog=xxx

 

# 网络传输方式

spring.dubbo.application.protocol.transporter=xxx

 

# 信息交换方式

spring.dubbo.application.protocol.exchanger=xxx

 

# 信息线程模型派发方式

spring.dubbo.application.protocol.dispatcher=xxx

 

# 对称网络组网方式

spring.dubbo.application.protocol.networker=xxx

 

# 服务器端实现

spring.dubbo.application.protocol.server=xxx

 

# 客户端实现

spring.dubbo.application.protocol.client=xxx

 

# 支持的telnet命令,多个命令用逗号分隔

spring.dubbo.application.protocol.telnet=xxx

 

# 命令行提示符

spring.dubbo.application.protocol.prompt=xxx

 

# status检查

spring.dubbo.application.protocol.status=xxx

 

# 是否注册

spring.dubbo.application.protocol.status=xxx

 

1.6.1.3. zookeeper注册中心

我们使用zookeeper作为dubbo的注册中心。

这里使用的zookeeper注册中心地址是:192.168.37.161:2181

 

1.6.2. 搭建项目

huiyang-parent作为所有工程的父工程

huiyang- interface作为提供pojo和抽取服务接口的

huiyang-provider作为服务提供者

huiyang-consumer作为服务消费者

 

1.6.2.1. 搭建huiyang-parent

创建huiyang-parentpom包,这里配置公共使用的依赖。

修改pom.xml为如下

"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

1.4.4.RELEASE

com.huiyang

huiyang-parent

0.0.1-SNAPSHOT

pom

 

1.7

 

org.springframework.boot

spring-boot-starter-test

test

 

org.springframework.boot

spring-boot-starter-web

true

 

org.springframework.boot

spring-boot-starter-dubbo

1.4.4.RELEASE

true

 

1.6.2.2. 搭建huiyang-interface

创建huiyang-interface并打jar包。

修改pom.xml为如下,几乎不用配置

"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.huiyang

huiyang-parent

0.0.1-SNAPSHOT

com.huiyang

huiyang-interface

0.0.1-SNAPSHOT

 

1.6.2.3. 搭建huiyang-provider

创建huiyang-provider并打jar包。

修改pom.xml为如下

"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.huiyang

huiyang-parent

0.0.1-SNAPSHOT

com.huiyang

huiyang-provider

0.0.1-SNAPSHOT

 

com.huiyang

huiyang-interface

0.0.1-SNAPSHOT

 

org.mybatis.spring.boot

mybatis-spring-boot-starter

1.1.1

 

mysql

mysql-connector-java

 

1.6.2.4. 搭建huiyang-consumer

创建huiyang-consumer并打jar包。

修改pom.xml为如下

"http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

com.huiyang

huiyang-parent

0.0.1-SNAPSHOT

com.huiyang

huiyang-consumer

0.0.1-SNAPSHOT

 

com.huiyang

huiyang-interface

0.0.1-SNAPSHOT

 

1.7. 实现功能

1.7.1. 实现huiyang-interface

编写pojo

import java.io.Serializable;

 

public class User implements Serializable {

private Long id;

private String userName;

private String password;

private String name;

get/set方法

}

 

编写Service接口

import com.huiyang.pojo.User;

 

public interface UserService {

public User queryUserById(Long id);

}

 

1.7.2. 实现huiyang-provider

编写UserMapper

import org.apache.ibatis.annotations.Mapper;

import org.apache.ibatis.annotations.Select;

import com.huiyang.common.pojo.User;

 

@Mapper

public interface UserMapper {

 

@Select("select * from user where id=#{id}")

public User queryUserById(Long id);

 

}

 

编写UserServiceImpl实现类

import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.dubbo.config.annotation.Service;

import com.huiyang.common.consumer.UserService;

import com.huiyang.common.pojo.User;

import com.huiyang.mapper.UserMapper;

 

@Service

public class UserServiceImpl implements UserService {

 

@Autowired

private UserMapper userMapper;

 

@Override

public User queryUserById(Long id) {

User user = this.userMapper.queryUserById(id);

return user;

}

}

 

编写引导类

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.alibaba.boot.dubbo.EnableDubboAutoConfiguration;

 

@SpringBootApplication

@EnableDubboAutoConfiguration

public class ProviderApplication {

public static void main(String[] args) {

SpringApplication.run(ProviderApplication.class, args);

}

}

 

src/main/resources加入配置文件application.properties

#DB Configuration:

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/huiyang

spring.datasource.username=root

spring.datasource.password=root

 

#配置服务器访问端口号

server.port=8081

 

#配置dubbo信息

#配置服务名称

spring.dubbo.application.name=huiyang-provider

#注册中心类型

spring.dubbo.registry.protocol=zookeeper

#注册中心连接方式

spring.dubbo.registry.address=192.168.37.161:2181

#配置服务调用所使用的协议

spring.dubbo.protocol.name=dubbo

#配置服务端口号

spring.dubbo.protocol.port=20880

#配置服务访问地址

spring.dubbo.protocol.host=localhost

#配置dubbo扫描

spring.dubbo.scan=com.huiyang.provider

 

 

1.7.3. 实现huiyang-consumer

编写Controller

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import com.alibaba.dubbo.config.annotation.Reference;

import com.huiyang.common.consumer.UserService;

import com.huiyang.common.pojo.User;

 

@RestController

@RequestMapping("user")

public class UserController {

 

@Reference

private UserService userService;

 

@RequestMapping("{id}")

public User queryUserById(@PathVariable Long id) {

User user = this.userService.queryUserById(id);

return user;

}

}

 

编写引导类

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.alibaba.boot.dubbo.EnableDubboAutoConfiguration;

 

@SpringBootApplication

@EnableDubboAutoConfiguration

public class ConsumerApplication {

public static void main(String[] args) {

SpringApplication.run(ConsumerApplication.class, args);

}

}

 

src/main/resources加入配置文件application.properties

#配置服务器访问端口号

server.port=8080

 

#配置dubbo信息

#配置服务名称

spring.dubbo.application.name=huiyang-consumer

#注册中心类型

spring.dubbo.registry.protocol=zookeeper

#注册中心连接方式

spring.dubbo.registry.address=192.168.37.161:2181

#配置服务调用所使用的协议

spring.dubbo.protocol.name=dubbo

#配置服务端口号

spring.dubbo.protocol.port=20880

#配置服务访问地址

spring.dubbo.protocol.host=localhost

#配置dubbo扫描

spring.dubbo.scan=com.huiyang.consumer

 

1. Springboot整合quartz

spring支持多种定时任务的实现。我们来介绍下使用spring的定时器和使用quartz定时器

  1.我们使用spring-boot作为基础框架,其理念为零配置文件,所有的配置都是基于注解和暴露bean的方式。

  2.使用spring的定时器:

    spring自带支持定时器的任务实现。其可通过简单配置来使用到简单的定时任务。

 

@Component

@Configurable

@EnableSchedulingpublic class ScheduledTasks{

 

    @Scheduled(fixedRate = 1000 * 30)

    public void reportCurrentTime(){

        System.out.println ("Scheduling Tasks Examples: The time is now " + dateFormat ().format (new Date ()));

    }

 

    //每1分钟执行一次

    @Scheduled(cron = "0 */1 *  * * * ")

    public void reportCurrentByCron(){

        System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));

    }

 

    private SimpleDateFormat dateFormat(){

        return new SimpleDateFormat ("HH:mm:ss");

    }

    

}

 

          没了,没错,使用spring的定时任务就这么简单,其中有几个比较重要的注解:

   @EnableScheduling:标注启动定时任务。

          @Scheduled(fixedRate = 1000 * 30)  定义某个定时任务。

  3.使用quartz实现定时任务。
    Quartz设计者做了一个设计选择来从调度分离开作业。Quartz中的触发器用来告诉调度程序作业什么时候触发。框架提供了一把触发器类型,但两个最常用的是SimpleTrigger和CronTrigger。SimpleTrigger为需要简单打火调度而设计。典型地,如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,如果你有许多复杂的作业调度,那么或许需要CronTrigger。
    CronTrigger是基于Calendar-like调度的。当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。

    使用quartz说使用的maven依赖。

    

    org.quartz-scheduler

    quartz

    1.8.4

    由于我们使用的是spring-boot框架,其目的是做到零配置文件,所以我们不使用xml文件的配置文件来定义一个定时器,而是使用向spring容器暴露bean的方式。

@Configuration

public class SchedledConfiguration {

 

    // 配置中设定了

    // ① targetMethod: 指定需要定时执行scheduleInfoAction中的simpleJobTest()方法

    // ② concurrent:对于相同的JobDetail,当指定多个Trigger时, 很可能第一个job完成之前,

    // 第二个job就开始了。指定concurrent设为false,多个job不会并发运行,第二个job将不会在第一个job完成之前开始。

    // ③ cronExpression:0/10 * * * * ?表示每10秒执行一次,具体可参考附表。

    // ④ triggers:通过再添加其他的ref元素可在list中放置多个触发器。 scheduleInfoAction中的simpleJobTest()方法

    @Bean(name = "detailFactoryBean")

    public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduledTasks scheduledTasks){

        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean ();

        bean.setTargetObject (scheduledTasks);

        bean.setTargetMethod ("reportCurrentByCron");

        bean.setConcurrent (false);

        return bean;

    }

 

    @Bean(name = "cronTriggerBean")

    public CronTriggerBean cronTriggerBean(MethodInvokingJobDetailFactoryBean detailFactoryBean){

        CronTriggerBean tigger = new CronTriggerBean ();

        tigger.setJobDetail (detailFactoryBean.getObject ());

        try {

            tigger.setCronExpression ("0/5 * * * * ? ");//每5秒执行一次

        } catch (ParseException e) {

            e.printStackTrace ();

        }

        return tigger;

 

    }

 

    @Bean

    public SchedulerFactoryBean schedulerFactory(CronTriggerBean[] cronTriggerBean){

        SchedulerFactoryBean bean = new SchedulerFactoryBean ();

        System.err.println (cronTriggerBean[0]);

        bean.setTriggers (cronTriggerBean);

        return bean;

    }
}

 

    MethodInvokingJobDetailFactoryBean:此工厂主要用来制作一个jobDetail,即制作一个任务。由于我们所做的定时任务根本上讲其实就是执行一个方法。所以用这个工厂比较方便。

      注意:其setTargetObject所设置的是一个对象而不是一个类。

    CronTriggerBean:定义一个触发器。

      注意:setCronExpression:是一个表达式,如果此表达式不合规范,即会抛出异常。

    SchedulerFactoryBean:主要的管理的工厂,这是最主要的一个bean。quartz通过这个工厂来进行对各触发器的管理。

  4.对quartz的封装

    由上面代码可以看出来,此处我们设置的是一个固定的cronExpression,那么,做为项目中使用的话,我们一般是需要其动态设置比如从数据库中取出来。

    其实做法也很简单,我们只需要定义一个Trigger来继承CronTriggerBean。顶用其setCronExpression方法即可。

    那么另外一个问题,如果我们要定义两个定时任务则会比较麻烦,需要先注入一个任务工厂,在注入一个触发器。

       为了减少这样的配置,我们定义了一个抽象的超类来继承CronTriggerBean

    具体代码如下:

    

 

public abstract class BaseCronTrigger extends CronTriggerBean implements Serializable {

 

    private static final long serialVersionUID = 1L;

 

    public void init(){

        // 得到任务

        JobDetail jobdetail = new JobDetail (this.getClass ().getSimpleName (),this.getMyTargetObject ().getClass ());

        this.setJobDetail (jobdetail);

        this.setJobName (jobdetail.getName ());

        this.setName (this.getClass ().getSimpleName ());

        try {

            this.setCronExpression (this.getMyCronExpression ());

        } catch (java.text.ParseException e) {

            e.printStackTrace ();

        }

 

    }

 

    public abstract String getMyCronExpression();

 

    public abstract Job getMyTargetObject();

 

}

 

    其init()方法,来为这个触发器绑定任务。其任务为一个Job类型的,也就是说其执行的任务为实现了Job接口的类,这个任务会有一个execute()方法,来执行任务题。

    

 

public class ScheduledTasks implements Job {

   

    @Override

    public void execute(JobExecutionContext context) throws JobExecutionException{

        System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));

    }

 

   private SimpleDateFormat dateFormat(){

        return new SimpleDateFormat ("HH:mm:ss");

    }

}

 

    为了给触发器添加任务,我们需要在子类中调用init()方法,由于spring容器注入时是使用的空参的构造函数,所以我们在此构造函数中调用init()方法。

    

 

@Componentpublic class InitializingCronTrigger extends BaseCronTrigger implements Serializable {

 

    private static final long    serialVersionUID = 1L;

 

    @Autowired

    private SchedulerFactoryBean schedulerFactoryBean;

 

    public InitializingCronTrigger() {

        init ();

    }

 

    @Override

    public String getMyCronExpression(){

        return "0/5 * * * * ?";

    }

 

    @Override

    public Job getMyTargetObject(){

        return new ScheduledTasks ();

    }

 

    public void parse(){

        try {

            schedulerFactoryBean.getObject ().pauseAll ();

        } catch (SchedulerException e) {

            e.printStackTrace ();

        }

    }

 

}

 

    此时我们只需要在配置类中加入一个配置就可以了。

    

 

  @Bean

    public SchedulerFactoryBean schedulerFactory(CronTriggerBean[] cronTriggerBean){

        SchedulerFactoryBean bean = new SchedulerFactoryBean ();

        System.err.println (cronTriggerBean[0]);

        bean.setTriggers (cronTriggerBean);

 

        return bean;

    }

 

转载于:https://www.cnblogs.com/lihuiyang/p/7297937.html

你可能感兴趣的:(SpringBoot实战总汇--详解)