spring boot 2.2.* 项目搭建 创建spring_boot maven 项目,创建module (二)

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 启动正常。

http://localhost:9000/
在这里插入图片描述

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

输出地址如下: 自动刷新文件。 这里注意,我测试更换数据库连接池,发现无用。只能修改配置文件。 数据库连接池无法更换。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值