spring boot 2.2.* 项目搭建 创建spring_boot项目,创建module (二)
1,我们创建第一个spring_boot 项目 ,放到 git 数据库中。
我们删除 src 目录:
目录文件最后:
2 我们在 maven 项目上开始创建 module 。
因为我们要学习整个项目的过程。
所以我们创建 module 为:
spring_boot_eureka
spring_boot_admin
spring_boot_config
spring_boot_servicea
spring_boot_ribbon
spring_boot_consumer
spring_boot_hystrix
spring_boot_zuul
spring_boot_bus
现在开始创建第一个项目:
spring_boot_eureka
开启 eureka server :
增加两个文件.
application.yml 配置如下:
server:
port: 9000
spring:
application:
name: spring-boot-eureka
bootstrap.yml 配置如下:
server:
port: 9000
spring:
application:
name: spring-boot-eureka
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 60000
启动应用: 如下页面完成。eureka 启动正常。
2 创建 spring_boot_admin module
增加如下引用:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-server-ui</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
增加如下引用
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
修改引用:
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
创建 config 包。增加 SecuritySecureConfig.java
package com.ylz.spring_boot.admin.spring_admin.config;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(adminContextPath + "/");
http.authorizeRequests()
.antMatchers(adminContextPath + "/assets/**").permitAll()//Grants public access to all static assets and the login page.
.antMatchers(adminContextPath + "/login").permitAll()
.anyRequest().authenticated()// Every other request must be authenticated.
.and()
.formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()//Configures login and logout.
.logout().logoutUrl(adminContextPath + "/logout").and()
.httpBasic().and()//Enables HTTP-Basic support. This is needed for the Spring Boot Admin Client to register.
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())// Enables CSRF-Protection using Cookies
.ignoringAntMatchers(
adminContextPath + "/instances",// Disables CRSF-Protection the endpoint the Spring Boot Admin Client uses to register.
adminContextPath + "/actuator/**"//Disables CRSF-Protection for the actuator endpoints.
);
}
}
增加 bootstrap.yml
server:
port: 9001
spring:
application:
name: spring-boot-admin
cloud:
discovery:
enabled: true
service-id: spring-boot-admin
security:
user:
name: ysuylz
password: ysuylz
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
增加 logback.yml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="INFO"/>
<jmxConfigurator/>
</configuration>
增加 application.yml
server:
port: 9001
spring:
application:
name: spring-boot-admin
启动项目:
用户名密码配置到 bootstrap 的 spring.security.user.name spring.security.user.password 里面。
3 创建 module spring_boot_config 统一配置 配置文件,交给 git管理
修改
增加 application.yml
server:
port: 9002
spring:
application:
name: spring-boot-config
增加 bootstrap.yml
server:
port: 9002
spring:
application:
name: spring-boot-config
boot:
admin:
client:
url: http://localhost:9001
username: ysuylz
password: ysuylz
instance:
server-base-url: http://localhost:9002
cloud:
config:
server:
git:
uri: https://gitee.com/ysuylz_2604389154/config_repo.git
search-paths: config_repo
default-label: master
username:
password:
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
management:
endpoints:
web:
exposure:
include: "*"
security:
enabled: false
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-client -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
启动服务:
spring admin 发现配置文件:
4 创建 module spring_boot_servicea 用来应用config 的配置文件。直接从git上读取配置文件,注册到 eureka 服务中心 被 admin 发现监控。
这里我们可以配置多例模式,让一个服务开启多个端口提供多个服务。
pom.xml 配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-client -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- freemarker -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!-- druid log4j -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- kaptcha -->
<dependency>
<groupId>com.github.axet</groupId>
<artifactId>kaptcha</artifactId>
<version>0.0.9</version>
</dependency>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
application.yml
bootstrap.yml
spring:
cloud:
config:
uri: http://localhost:9002/
profile: dev
name: spring-boot-servera
label: master
package com.ylz.spring_boot.servera.spring_boot_servera.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().build();
}
}
跨域请求:
package com.ylz.spring_boot.servera.spring_boot_servera.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域访问的路径
.allowedOrigins("*") // 允许跨域访问的源
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 允许请求方法
.maxAge(168000) // 预检间隔时间
.allowedHeaders("*") // 允许头部设置
.allowCredentials(true); // 是否发送cookie
}
}
集成 druid
package com.ylz.spring_boot.servera.spring_boot_servera.config;
import java.sql.SQLException;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
@Configuration
@EnableConfigurationProperties({DruidDataSourceProperties.class})
public class DruidConfig {
@Autowired
private DruidDataSourceProperties properties;
@Bean
@ConditionalOnMissingBean
public DataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(properties.getDriverClassName());
druidDataSource.setUrl(properties.getUrl());
druidDataSource.setUsername(properties.getUsername());
druidDataSource.setPassword(properties.getPassword());
druidDataSource.setInitialSize(properties.getInitialSize());
druidDataSource.setMinIdle(properties.getMinIdle());
druidDataSource.setMaxActive(properties.getMaxActive());
druidDataSource.setMaxWait(properties.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(properties.getValidationQuery());
druidDataSource.setTestWhileIdle(properties.isTestWhileIdle());
druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
druidDataSource.setTestOnReturn(properties.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(properties.getMaxPoolPreparedStatementPerConnectionSize());
try {
druidDataSource.setFilters(properties.getFilters());
druidDataSource.init();
} catch (SQLException e) {
e.printStackTrace();
}
return druidDataSource;
}
/**
* 注册Servlet信息, 配置监控视图
*
* @return
*/
@Bean
@ConditionalOnMissingBean
public ServletRegistrationBean<Servlet> druidServlet() {
ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<Servlet>(new StatViewServlet(), "/druid/*");
//白名单:
// servletRegistrationBean.addInitParameter("allow","127.0.0.1,139.196.87.48");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny","192.168.1.119");
//登录查看信息的账号密码, 用于登录Druid监控后台
servletRegistrationBean.addInitParameter("loginUsername", "ysuylz");
servletRegistrationBean.addInitParameter("loginPassword", "123qwe");
//是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable", "true");
return servletRegistrationBean;
}
/**
* 注册Filter信息, 监控拦截器
*
* @return
*/
@Bean
@ConditionalOnMissingBean
public FilterRegistrationBean<Filter> filterRegistrationBean() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<Filter>();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
修改mybatis 的扫描文件。指定mapper文件的目录。
4.2 解决手动刷新微服务 配置文件。
controller 文件顶部应用 @RefreshScope
修改controller文件:
@Value("${ylz.server.name}")
String ylz_server_name;
@RequestMapping(value = "/getemail")
public String getemail(){
return ylz_server_name + "——";
}
package com.ylz.spring_boot.servera.spring_boot_servera.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope
@RestController
public class ConfigController {
@Value("${spring.boot.admin.client.url}")
String client_url;
@Value("${ylz.server.name}")
String ylz_server_name;
@RequestMapping(value = "/server")
public String client_url(){
return client_url + "——";
}
@RequestMapping(value = "/getemail")
public String getemail(){
return ylz_server_name + "——";
}
}
因为 cloud.context.config 中包含了 actutor 了,所以不需要修改pom.xml文件。
修改配置文件,增加以下配置
ylz:
server:
name: ysuylz@ysu.edu.cn
http://localhost:9003/getemail
修改配置文件,提交git .
请求:
http://localhost:9003/actuatoer/refresh
5 spring_boot_ribbon 我们模拟负载均衡
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
新增 application.yml
server:
port: 9011
spring:
application:
name: spring-boot-ribbon
新增: bootstrap.yml
spring:
cloud:
config:
uri: http://localhost:9002/
label: master
profile: dev
name: spring-boot-ribbon
修改 app 的启动文件:增加:
@EnableHystrix
@EnableEurekaClient
package com.ylz.spring_boot.ribbon.spring_boot_ribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@EnableHystrix
@EnableEurekaClient
@SpringBootApplication
public class SpringBootRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRibbonApplication.class, args);
}
}
创建 pageage config
创建 bibbon 配置文件:
@Configuration
public class RibbonConfig()
{
@Bean
@LoadBalanced
RestTemplate restemplate()
{
return new RestTemplate();
}
}
package com.ylz.spring_boot.ribbon.spring_boot_ribbon.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate(){ return new RestTemplate();}
}
创建一个 service 一个 controller
创建service ServeraService.java
@Service
public class ServeraService()
{
@Autowired
RestTemplate resttemplate ;
@AutoWired
@HystrixCommand(fallbackMethord=“hiError”)
private LoadBalancedClient loadBalancedclient ;
public String servericehellow(String name)
{
BalanceInstance balanceinstance = loadBalanceclient.choose(“spring-boot-servera”);
System.out.println(""+ balanceinstance.getUri());
System.out.pritnln(""+ balanceinstance.getServiceID());
return resttemplate.getForOjbect(“http://spring-boot-servera/server?name=”+name,string.class);
}
public String hiError(String name )
{
return name+" system is error !";
}
}
package com.ylz.spring_boot.ribbon.spring_boot_ribbon.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class ServeaService {
@Autowired
RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@HystrixCommand(fallbackMethod = "hiError")
public String getserver_client(String name)
{
ServiceInstance serviceInstance =loadBalancerClient.choose("spring-boot-servera");
System.out.println(""+serviceInstance.getUri());
System.out.println(""+serviceInstance.getServiceId());
return restTemplate.getForObject("http://SPRING-BOOT-SERVERA?server"+name,String.class);
}
public String hiError(String name)
{
return name+"=server is error !";
}
}
6 spring_boot_consumer 创建服务消费者。
也就是 第三方的程序通过以服务调用的模式调用其他的服务。
spring_boot_consumer 可以调用 spring_boot_servera 里面的函数和方法。
创建 module spring_boot_consumer :
修改启动程序,增加
@Bean
@Loadbance
RestTemplate resttemplate()
{
return new RestTemplate();
}
增加:
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
pom.xml 引用:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
我们创建 service 和 controller
我们通过 service 调用 服务
我们通过 controller 调用 servcie。
演示效果:
显示项目配置文件中引用的地址: 服务调用成功。
6 现在服务有, 客户调用服务有了。 如果我们出现某个服务因为网络或者代码原因宕机了。 还有其他的客户调用服务。就会导致系统瘫痪。 因此我们需要增加熔断功能,当服务宕机后我们做处理,告知客户服务宕机或者其他提示。
我们创建 module spring_boot_hystrix
测试 hystrix
我们修改服务类 spring_boot_consumer
集成 feign
pom.xml
<!--feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
package com.ylz.spring_boot.consumer.spring_boot_consumer.services;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String server_client(String name) {
return restTemplate.getForObject("http://SPRING-BOOT-SERVERA/server?name="+name,String.class);
}
public String hiError(String name){
return ""+name+",sorry,error!";
}
}
我们暂停: spring-boot-servera 访问 spring-boot-consumer
提示如下:
熔断成功。
如果配置了多服务:servera: 8003 serverb:8013 那么我们访问的请求如下。自动负载均衡。
package com.ylz.spring_boot.consumer.spring_boot_consumer.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
package com.ylz.spring_boot.consumer.spring_boot_consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableHystrix
@EnableSwagger2
@EnableEurekaClient
@SpringBootApplication
public class SpringBootConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootConsumerApplication.class, args);
}
}
package com.ylz.spring_boot.consumer.spring_boot_consumer.services;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancer;
@HystrixCommand(fallbackMethod = "hiError")
public String server_client(String name) {
ServiceInstance serviceInstance = loadBalancer.choose("mango-producer");
System.out.println("服务地址:" + serviceInstance.getUri());
System.out.println("服务名称:" + serviceInstance.getServiceId());
return restTemplate.getForObject("http://SPRING-BOOT-SERVERA/server?name="+name,String.class);
}
public String hiError(String name){
return ""+name+",sorry,error!";
}
}
server:
port: 9004
spring:
boot:
admin:
client:
url: "http://localhost:9001"
username: ysuylz #对应server端的账号密码,不配置就监控不到这个client。
password: ysuylz
instance:
service-base-url: http://localhost:9004 #client地址 #不配置的情况下,在打包的时候会有提示。不影响运行。
datasource:
name: druidDataSource
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/spring_boot_database?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=true&serverTimezone=UTC
username: root
password: qhdswchzh
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j,config
# 连接池的配置信息
# 初始化大小,最小等待连接数量,最大等待连接数量,最大连接数
min-idle: 1
max_idle: 100
max-active: 1000
initial-size: 1
# 配置获取连接等待超时的时间
max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 300000
validation-query: select 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
max-open-prepared-statements: 50
max-pool-prepared-statement-per-connection-size: 20
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
management:
endpoints:
web:
exposure:
include: "*"
security:
enabled: false
feign:
httpclient:
enabled: true
hystrix:
enabled: true
配置 feign
package com.ylz.spring_boot.consumer_feigon.spring_boot_feigon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@EnableHystrix
@EnableFeignClients
@EnableSwagger2
@EnableEurekaClient
@SpringBootApplication
public class SpringBootFeigonApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootFeigonApplication.class, args);
}
}
server:
port: 9008
spring:
boot:
admin:
client:
url: "http://localhost:9001"
username: ysuylz #对应server端的账号密码,不配置就监控不到这个client。
password: ysuylz
instance:
service-base-url: http://localhost:9008 #client地址 #不配置的情况下,在打包的时候会有提示。不影响运行。
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
management:
endpoints:
web:
exposure:
include: "*"
security:
enabled: false
feign:
httpclient:
enabled: true #启用httpclient
connection-timeout: 3000
hystrix:
enabled: true
okhttp:
enabled: true
ribbon:
eureka:
enabled: true
package com.ylz.spring_boot.consumer_feigon.spring_boot_feigon.service;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name="spring-boot-servera")
public interface StudentService extends StudentFacade {
}
package com.ylz.spring_boot.consumer_feigon.spring_boot_feigon.controller;
import com.ylz.spring_boot.consumer_feigon.spring_boot_feigon.model.Student;
import com.ylz.spring_boot.consumer_feigon.spring_boot_feigon.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class StudentController {
@Autowired
private StudentService studentService;
/**
* GET无参调用
* @return
*/
@GetMapping("list")
public List<Student> list(){
return studentService.list();
}
/**
* GET参数调用
* @param id
* @return
*/
@GetMapping("get")
public Student get(@RequestParam("id") int id){
return studentService.get(id);
}
/**
* POST调用
* @param student
* @return
*/
@GetMapping("add")
public Student add(){
Student student = new Student("JAVA",12);
return studentService.add(student);
}
}
调用服务完成。
我们需要监控 服务的熔断情况: spring_boot_hystrix
我们创建 module spring_boot_hystrix
server:
port: 9005
spring:
boot:
admin:
client:
url: "http://localhost:9001"
username: ysuylz #对应server端的账号密码,不配置就监控不到这个client。
password: ysuylz
instance:
service-base-url: http://localhost:9005 #client地址 #不配置的情况下,在打包的时候会有提示。不影响运行。
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
management:
endpoints:
web:
exposure:
include: "*"
security:
enabled: false
这里需要调试和配置。
8 spring_boot_zuul 配置服务网关
我们创建module spring_boot_zuul
package com.ylz.spring_boot.zuul.spring_boot_zuul;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class SpringBootZuulApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootZuulApplication.class, args);
}
}
package com.ylz.spring_boot.zuul.spring_boot_zuul.filter;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
@Component
public class MyFilter extends ZuulFilter {
private static Logger log=LoggerFactory.getLogger(MyFilter.class);
@Override
public String filterType() {
return "pre"; // 定义filter的类型,有pre、route、post、error四种
}
@Override
public int filterOrder() {
return 0; // 定义filter的顺序,数字越小表示顺序越高,越先执行
}
@Override
public boolean shouldFilter() {
return true; // 表示是否需要执行该filter,true表示执行,false表示不执行
}
@Override
public Object run() throws ZuulException {
// filter需要执行的具体操作
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
System.out.println(token);
if(token==null){
log.warn("there is no request token");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("there is no request token");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
log.info("ok");
return null;
}
}
package com.ylz.spring_boot.zuul.spring_boot_zuul.filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
@Component
public class MyFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
return "spring-boot-consumer";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
System.out.println("route:"+route);
System.out.println("exception:"+cause.getMessage());
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return 200;
}
@Override
public String getStatusText() throws IOException {
return "ok";
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("Sorry, the service is unavailable now.".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
server:
port: 9009
spring:
boot:
admin:
client:
url: "http://localhost:9001"
username: ysuylz #对应server端的账号密码,不配置就监控不到这个client。
password: ysuylz
instance:
service-base-url: http://localhost:9009 #client地址 #不配置的情况下,在打包的时候会有提示。不影响运行。
zuul:
routes:
ribbon:
path: /ribbon/**
serviceId: spring-boot-consumer # 转发到消费者 /ribbon/
feign:
path: /feign/**
serviceId: spring-boot-consumer # 转发到消费者 /feign/
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
management:
endpoints:
web:
exposure:
include: "*"
security:
enabled: false
10 创建 module spring_boot_bus 配置消息总线。统一更新config
安装 RabbitMQ
https://blog.csdn.net/yulizi0215/article/details/104395257
安装 Docker
https://blog.csdn.net/yulizi0215/article/details/104397232
我们需要在 原有的项目中引入依赖:
spring-boot-consumer
<!-- bus-amqp -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件:
rabbitmq:
host: localhost
port: 5672
username: username
password: password
spring-boot-config
<!-- bus-amqp -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件:
rabbitmq:
host: localhost
port: 5672
username: username
password: password
启动各自服务,关闭 docker服务器的防火墙。可以监控到服务。完成。
我们修改配置文件中的内容:
ylz:
server:
name: ysuylz@ysu.edu.cn,4979353@qq.com,yulizi0405@sina.comm 20200219,20200220,202002201058
后面增加当前日期和时间。
post 请求连接地址:
测试 postman:
http://localhost:9002/actuator/bus-refresh
输出地址如下: 自动刷新文件。 这里注意,我测试更换数据库连接池,发现无用。只能修改配置文件。 数据库连接池无法更换。