类似之前dubbo的小例子,本文接着对SSM与SpringCloud、SpringBoot进行整合,并集成Eureka、Feign与Hystrix,这些都是SpringCloud中的套件,使用起来非常方便。
服务端的项目结构如下:
服务端包括Eureka注册中心以及登录服务loginserver,分开放完全也是可以的。
服务注册中心的核心代码包括以下两个部分:
package com.jhz.cloudserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class CloudserverApplication {
public static void main(String[] args) {
SpringApplication.run(CloudserverApplication.class, args);
}
}
只需要加个@EnableEurekaServer注解,即可标记为服务中心的启动类(对比zookeeper实在方便太多了)
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: eurka-server
在applcation.yml中配置下端口号和地址就搞定了,接着启动服务注册中心,输入localhost:8671,
如图,登录服务主要负责对登录信息的验证以及与数据库的交互,整合了SSM框架,与之前的dubbo一样,但是可以发现,使用SpringBoot来管理这些框架,基本不需要什么配置文件,只需要一个application.yml即可:
server:
port: 8762
spring:
application:
name: service-login
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
#mybatis配置
spring.datasource.url: "jdbc:mysql://localhost:3306/chatmarket?useSSL=false"
spring.datasource.username: "root"
spring.datasource.password: "root"
spring.datasource.driver-class-name: com.mysql.jdbc.Driver
mybatis.type-aliases-package: "com.jhz.pojo"
mybatis.mapper-locations: "classpath*:/mappers/**Mapper.xml"
这里定义的暴露服务的端口、服务名、服务治理中心以及mybatis的配置,spring的配置都可以通过注解完成,因此配置的工作量极小,这也是springboot的目的,为懒人开发定制。接着看一下登录服务的启动类:
package com.jhz.loginserver;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableEurekaClient
@ComponentScan(basePackages = {"com.jhz.*"})
@MapperScan(value = {"com.jhz.dao"})
public class LoginserverApplication {
public static void main(String[] args) {
SpringApplication.run(LoginserverApplication.class, args);
}
}
这里需要注意的是包的扫描路径,默认是扫描启动类所在包的所有文件,因此要注意启动类的位置,也可以通过图中的方式手动添加,消费者通过rest调用的url访问的controller实现如下:
package com.jhz.controller;
import com.jhz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author jhz
* @date 18-9-9 下午5:24
*/
@RestController
public class LoginController {
@Autowired
UserService userService;
@RequestMapping("/login")
public String login(@RequestParam(value = "userName") String userName, @RequestParam(value = "passWord") String passWord){
return userService.loginVerify(userName,passWord);
}
}
使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容,在我们的服务端使用RestController即可完成与消费者的通信,即使不加responsebody,也能返回json数据。登录服务的依赖如下:
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
}
ext {
springCloudVersion = 'Finchley.SR1'
}
dependencies {
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
testCompile('org.springframework.boot:spring-boot-starter-test')
compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6'
compile group: 'org.mybatis', name: 'mybatis', version: '3.4.1'
compile group: 'com.alibaba', name: 'druid', version: '1.1.10'
compile group: 'org.mybatis', name: 'mybatis-spring', version: '1.3.2'
compile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '1.3.2'
compile group: 'org.springframework', name: 'spring-jdbc', version: '5.0.8.RELEASE'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
首先看下项目结构:
config包下是自定义配置类,在这里配置启动后的首页:
package com.jhz.cloudclient.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @author jhz
* @date 18-9-9 上午1:08
*/
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/").setViewName("forward:templates/index.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers(registry);
}
}
hystrix则是熔断之后的处理类,springboot默认不支持jsp(正好也没啥好用的),但是如果需要的话,可以在yaml中配置,首先看启动类:
package com.jhz.cloudclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients
public class CloudclientApplication {
public static void main(String[] args) {
SpringApplication.run(CloudclientApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
声明需要的套件Fegin和Hystrix(Hystrix默认是关闭的),如果不使用Fegin,也可以使用图中的RestTemplate灵活的使用REST资源(https://blog.csdn.net/itguangit/article/details/78825505),使用Fegin的话,默认实现了Ribbon的客户端负载均衡,将远程的URL,封装成纯接口SDK,供其他用户或系统使用,用户服务接口如下:
package com.jhz.cloudclient.service;
import com.jhz.cloudclient.hystrix.Fail;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "service-login",fallback = Fail.class)
@Service
public interface UserService {
@RequestMapping(value = "/login",method = RequestMethod.GET)
String loginVerify(@RequestParam(value = "userName") String username, @RequestParam(value = "passWord")String password);
}
个人觉得Rest调用的方式比rpc更为直观,容易理解,fallback指定熔断后的错误返回类:
package com.jhz.cloudclient.hystrix;
import com.jhz.cloudclient.service.UserService;
import org.springframework.stereotype.Controller;
/**
* @author jhz
* @date 18-9-14 下午9:47
*/
@Controller
public class Fail implements UserService {
@Override
public String loginVerify(String username, String password) {
return "fail";
}
}
application.yml配置如下:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8764
spring:
application:
name: service-client
#指定日志输出文件
logging:
file: "logs/config.log"
info:
name : "配置中心"
主要是服务治理中心的配置以及消费者注册的端口,消费者搭建的是一个web项目,使用SpringBoot,可以直接使用内嵌的tomcat直接启动而不需要部署,消费端需要配置的依赖如下:
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.jhz'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client', version: '2.0.0.RELEASE'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-ribbon', version: '2.0.1.RELEASE'
compile group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'
compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2'
compile group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.10'
compile group: 'org.apache.tomcat', name: 'tomcat-jsp-api', version: '9.0.11'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf', version: '2.0.4.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.0.4.RELEASE'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-hystrix', version: '1.3.5.RELEASE'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-feign', version: '1.4.4.RELEASE'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-openfeign', version: '2.0.1.RELEASE'
}
首先启动服务治理中心以及登录服务,并访问服务治理中心localhost:8671查看:
可以看到登录服务service-login已经在服务中心注册了,接着启动消费者客户端:
登录成功的页面:
输入密码错误熔断后返回的页面:
Spring Cloud发扬了Spring Source整合一切的作风,以标准化的姿态将一些微服务架构的成熟产品与框架揉为一体,并继承了Spring Boot简单配置、快速开发、轻松部署的特点,让原本复杂的架构工作变得相对容易上手一些。