项目改造接入Spring Cloud流程

首先,项目先改造为spring boot工程

建议,采用下列方式引入spring boot依赖

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.2.RELEASEversion>
        <relativePath /> 
    parent>

相关的依赖通过spring boot的pom.xml内置的版本进行管理,最大化保证jar相互兼容。

建议配置采用yml进行管理

通过yml的方式声明的方式,原本的注入@value或者通过springEL语法${} 都是可以兼容使用。
除此之外,可以新增一种以对象注入的方式

约定配置

公共配置application.yml存放/src/main/resources/
各个环境配置application-${profile}.yml存放/src/main/resources/profiles
建议配置都写在同一个yml中,方便维护

加载特定环境配置

默认情况下,spring boot只会加载application.yml,如果想加载application-${profile}.yml,必须指定spring.profiles.active属性

方式一

在supervisor启动脚本新增java -jar xxx.jar --spring.profiles.active=${profile},profile变量是所指定的环境名

方式二

在system-config.properties中配置spring.profiles.active属性。在spring boot启动前加载system-config.properties,即可获取spring.profiles.active属性,从而让spring boot加载各个环境的配置

启动模板类
@SpringBootApplication
@ImportResource("classpath:spring-application.xml")
public class Application {

    public static void main(String[] args) throws IOException {
        Properties props = PropertiesLoaderUtils.loadProperties(new ClassPathResource("system-config.properties"));
        SpringApplication app = new SpringApplication(Application.class);
        app.setDefaultProperties(props);
        app.run(args);
    }
}

接入spring cloud

pom.xml引入依赖

新增dependency节点

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>

新增dependencyManagement节点

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>Brixton.SR7version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

启动类加入@EnableEurekaClient

配置eureka服务地址

提供rest服务

可以参考spring mvc的写法
有3个建议:

  1. http协议中,GET请求是有长度限制,建议采用POST请求。
  2. 在post请求中,参数应该放在http body中。因为在body中传递的是json参数对象,要加@RequestBody 注解。
  3. url名称和方法名一致。
@RestController
public class SmsStatController {

    private final Logger logger = Logger.getLogger(getClass());

    @Autowired
    private SmsStatServiceImpl smsStatServiceImpl;

    @PostMapping(value = "/getSmsMoneyTarget")
    public List getSmsMoneyTarget(@RequestBody SmsStatQueryParam param) {
        return smsStatServiceImpl.getSmsMoneyTarget(param);
    }
}

调用方

参照提供方提供的接口编写。
调用方可以参照dubbo的方式写在api工程中,避免参数对象和结果对象重复定义。可读性较好,但是缺点是引入了强依赖。

@FeignClient(value = "sms-stat-server")
public interface SmsStatClient {

    /**
     * 获取累计概要指标的数据列表
     * @param param
     * @return
     */
    @RequestMapping(value = "/getSmsMoneyTarget", method = RequestMethod.POST)
    List getSmsMoneyTarget(SmsStatQueryParam param);
}

调用方可以实现HystrixCallBack接口,可以在调用失败的时候进行操作,比如服务降级或者返回一个默认值,避免远程方法报错。类似dubbo框架中的mock。

幂等问题

因为目前工程中很多接口未实现幂等,所以不可以超时重试。
spring cloud默认会尝试5次调用。在每一次调用中,尝试对某一提供方发起调用,若连接拒绝,则会进行下一个提供方的尝试。

提供方配置自定义超时时间及重试次数

@Configuration
public class FeignConfig {

    @Bean
    public Feign.Builder feignBuilder() {
        Feign.Builder fb = Feign.builder();
        fb.logLevel(Logger.Level.FULL);
        fb.retryer(new Retryer.Default(100, SECONDS.toMillis(1), 1));
        return fb;
    }

    @Bean
    public Options feignOptions() {
        return new Options(2 * 1000, 10 * 1000);
    }
}

目前的问题

结果对象

在dubbo中,提供方返回的对象为Map等泛型,提供方在拿到这个Map后是可以得到里面的对象的。
而spring cloud采用的是json编码、解码,返回值如果不是特定的对象模型,解析出来是获取不到数据的。
建议,接口参数采用特定的模型对象。

参数对象

调用参数存在多个的情况。
如果都是基本类型,可以使用@requestParam注解进行传参,参数附在url上。
或者定义一个对象,将全部的参数都放在其中,通过http body进行传参。(提供方要提供POST请求)

已改造项目

可以进行参考

iportal-developer
sms-stat

你可能感兴趣的:(Spring)