Spring-Cloud爬坑

spring-cloud爬坑

标签(空格分隔): GE


\10.189.131.249 temp/pwd

[TOC]

1. Feign 做客户端,Hystrix 熔断,Fallback不回调的原因

原因很简单 在版本快速的迭代
Feign在新版本中默认是没有开启Hystrix的功能
官方文档都没来得及更新 更何况那些一笔带过的简单教程
解决方式在配置文件(application)中加上 feign.hystrix.enabled=true

2. 注册中心监听事件

@Configuration
@Slf4j
@EnableScheduling
public class EcgCenterEvent implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if(applicationEvent instanceof EurekaInstanceCanceledEvent){
            //服务断开连接时
            log.info("服务断开连接了!");
        }
        if(applicationEvent instanceof EurekaInstanceRegisteredEvent){
            log.info("服务注册了!");
        }
        if(applicationEvent instanceof EurekaInstanceRenewedEvent){
            log.info("服务Renewed了!这个是什么状态我暂时还不懂!");
        }
        if(applicationEvent instanceof EurekaServerStartedEvent){
            log.info("中策中心服务Started!!");
        }
        if(applicationEvent instanceof EurekaRegistryAvailableEvent){
            //服务可用
            log.info("注册中心服务可用!");
        }
    }
}

3. ConditionalOnProperty注解

根据配置文件,有条件的生成bean,只创建被标记的bean

@Configuration
@EnableConfigurationProperties(RateLimitProperties.class)
@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true")
@SuppressWarnings("all")
public class RateLimitAutoConfiguration {

    @Bean
    public RateLimitFilter rateLimiterFilter(final RateLimiter rateLimiter,
                                             final RateLimitProperties rateLimitProperties,
                                             final RouteLocator routeLocator, final IUserPrincipal userPrincipal) {
        return new RateLimitFilter(rateLimiter, rateLimitProperties, routeLocator,userPrincipal);
    }

    @ConditionalOnClass(RedisTemplate.class)
    @ConditionalOnMissingBean(RateLimiter.class)
    @ConditionalOnProperty(prefix = PREFIX, name = "repository", havingValue = "REDIS")
    public static class RedisConfiguration {

        @Bean("rateLimiterRedisTemplate")
        public StringRedisTemplate redisTemplate(final RedisConnectionFactory connectionFactory) {
            return new StringRedisTemplate(connectionFactory);
        }

        @Bean
        public RateLimiter redisRateLimiter(@Qualifier("rateLimiterRedisTemplate") final RedisTemplate redisTemplate) {
            return new RedisRateLimiter(redisTemplate);
        }
    }

    @EntityScan
    @EnableJpaRepositories
    @ConditionalOnMissingBean(RateLimiter.class)
    @ConditionalOnProperty(prefix = PREFIX, name = "repository", havingValue = "JPA")
    public static class SpringDataConfiguration {

        @Bean
        public RateLimiter springDataRateLimiter(IRateLimiterRepository rateLimiterRepository) {
            return new SpringDataRateLimiter(rateLimiterRepository);
        }

    }

    @ConditionalOnMissingBean(RateLimiter.class)
    @ConditionalOnProperty(prefix = PREFIX, name = "repository", havingValue = "IN_MEMORY", matchIfMissing = true)
    public static class InMemoryConfiguration {

        @Bean
        public RateLimiter inMemoryRateLimiter() {
            return new InMemoryRateLimiter();
        }
    }

}

4. Feign配置

#请求和响应GZIP压缩支持
feign:
  compression:
    request:
      enabled: true
      mime-types: text/xml,application/xml,application/json
      min-request-size: 2048
    response:
      enabled: true
  #启动熔断
  hystrix:
    enabled: true

##5. spring-admin Loglevel 管理

当前日志级别管理仅限 Logback,通过 JMX 实现,所以需要依赖 jolokia 。同时,还需要配置 Logback 的 JMXConfigurator: 

logback.xml

<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <jmxConfigurator/>
</configuration>
这个 logback.xml 放在与 application.properties 同级的目录就可以了,如果不配置 Logback,那么 Spring Boot Admin 就无法管理应用的日志级别

##6. zipkin 存储方式

<!--保存到数据库需要如下依赖-->
    <!-- 添加 spring-data-elasticsearch的依赖 -->
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-storage-elasticsearch-http</artifactId>
        <version>1.24.0</version>
        <optional>true</optional>
    </dependency>



默认存储是在内存中,重启后数据消失

mysql的脚本在zipkin包里已经提供了,只需要执行一下就可以了
spring:
  application:
    name: sleuth-zipkin-http
  datasource:
    schema: classpath:/mysql.sql
    url: jdbc:mysql://192.168.3.3:2222/zipkin
    driverClassName: com.mysql.jdbc.Driver
    username: app
    password: %jdbc-1.password%
    # Switch this on to create the schema on startup:
    initialize: true
    continueOnError: true
  sleuth:
    enabled: false

# default is mem (in-memory)
zipkin:
	storage:
	   type: mysql

es存储方式

zipkin:
  storage:
    type: elasticsearch
    elasticsearch:
      cluster: ${ES_CLUSTER:elasticsearch}
      hosts: ${ES_HOSTS:localhost:9300}
      index: ${ES_INDEX:zipkin}
      index-shards: ${ES_INDEX_SHARDS:5}
      index-replicas: ${ES_INDEX_REPLICAS:1}
      username: xxxx
      password: xxxx

要分析依赖关系还需要spark job 感觉好麻烦,不如存储在mysql里面

7.Hystrix

运行时间统计。我们只需要在我们的某一个方法上加上@HystrixCommand的标签,这个方法的执行就能够被统计,包括运行测试、时间等。

8. Hystrix fallback

我们在用@HystrixCommand的时候,可以加fallback方法,这样,Hystrix断路器会监控这个方法的执行,在超时、发生异常等情况下就会调用相应的fallback设置的方法。例如
@RestController
@RequestMapping("/api/order")
public class OrderResource {
  @HystrixCommand(fallbackMethod = "createFallback")
  @PostMapping(value = "/")
  public Order buyTicket(@RequestBody Order order) {
    return orderService.create(order);
  }
  private Order createFallback(Order order) {
    return orderService.createFallback(order);
  }
}

9. 解决spring-boot & spring-cloud zuul 跨域的问题

    @Bean
    public CorsFilter corsFilterDev() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }

10. 解决通用mapper配置的问题

/**
     * 我下午也出现了这个问题,因为重构项目,需要把工程是从原来的spring-boot工中,把配置文件分离出来的。最开始还是用的
     org.mybatis.spring.mapper.MapperScannerConfigurer
     后来换成文档里提到的
     <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
     <property name="basePackage" value="your mapper package"/>
     <property name="markerInterface" value="tk.mybatis.mapper.common.Mapper"/>
     </bean>
     解决,供参考。
     * @return
     */
    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.ge.hcd.ecg.**.mapper");
        mapperScannerConfigurer.setMarkerInterface(tk.mybatis.mapper.common.Mapper.class);
        return mapperScannerConfigurer;
    }

11. 加载其他工程或者依赖工程里面的配置

    @Bean
    public GlobalExceptionHandler getGlobalExceptionHandler(){
        return new GlobalExceptionHandler();
    }

12 logback使用配置文件中的信息

logback.xml加载早于application.yml,需改用logback-spring.xml实现日志配置
而且必须使用
<springProperty scope="context" name="logLevel" source="log.level"/>
<springProperty scope="context" name="bluk" source="es.elasticsearch.bluk"/>

    <appender name="ELASTIC" class="com.internetitem.logback.elasticsearch.ElasticsearchAppender">
        <url>${bluk}</url>

13 upload location [/tmp/tomcat.7986646121236549874.8090/work/Tomcat/localhost/ROOT] is not valid

/**
     * @Author: Haibo.Mei [Haibo.Mei@ge.com]
     * @Description: 上传文件大小设置
     * @Date: 11:25 2017/12/20
     */
    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        //单个文件最大
        //KB,MB
        factory.setMaxFileSize("102400KB");
        /**
         * 设置临时上传文件路径
         */
        factory.setLocation("D:/temp");
        /// 设置总上传数据总大小
        factory.setMaxRequestSize("102400KB");
        return factory.createMultipartConfig();
    }

14. nginx 代理网关及nginx

        location / {
			proxy_set_header  Host $host;  
            proxy_set_header  X-Real-IP  $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://localhost:5601/;
        }
		
		location /ecgapi/ {
			proxy_set_header  Host $host:$server_port;  
            proxy_set_header  X-Real-IP  $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Cookie $http_cookie;
            proxy_pass http://106.75.8.121:8084/ecgapi/;
        }

还有一个地方 由于对nginx和网络都不熟悉,所以弄了很长时间,后来无意之间把localhost换成了127.0.0.1,发现访问URL时的速度变快了。再次换成localhost又变的非常慢。如下: 使用127.0.0.1速度很快:

    location / {
        proxy_pass http://127.0.0.1:8080/;
        rewrite ^/$    /index.do;
    }

使用localhost非常慢:

    location / {
        proxy_pass http://localhost:8080/;
        rewrite ^/$    /index.do;
    }

问题找到了,不过为什么会出现这个问题还是不清楚,没有去深究localhsot和127.0.0.1。

15 spring-boot 启动内存

-Xmx512m -Xms128m

16 设置环境文件

--spring.profiles.active=test211

17 spring-boot 返回JSON IE浏览器提示下载的解决方案

@Bean
public HttpMessageConverters fastJsonHttpMessageConverters(){
        //1.需要定义一个convert转换消息的对象;
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        //2处理ie浏览器保存数据时出现下载json数据问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.valueOf("text/html;charset=utf-8"));
        //fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        //3.在convert中添加配置信息.
        fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
        HttpMessageConverter<?> converter = fastJsonHttpMessageConverter;
        return new HttpMessageConverters(converter);
    }

18 nginx 代理后访问慢的问题

http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html

语法:	proxy_buffering on | off;
默认值:	
proxy_buffering on;
上下文:	http, server, location
代理的时候,开启或关闭缓冲后端服务器的响应。

当开启缓冲时,nginx尽可能快地从被代理的服务器接收响应,再将它存入proxy_buffer_size和proxy_buffers指令设置的缓冲区中。如果响应无法整个纳入内存,那么其中一部分将存入磁盘上的临时文件。proxy_max_temp_file_size和proxy_temp_file_write_size指令可以控制临时文件的写入。

当关闭缓冲时,收到响应后,nginx立即将其同步传给客户端。nginx不会尝试从被代理的服务器读取整个请求,而是将proxy_buffer_size指令设定的大小作为一次读取的最大长度

将localhost替换为 127.0.0.1

19 服务追踪及性能监控

ziplin及 skywalking

20 tk.mapper返回主键

以上方式即可生成UUID,但是不能回显,就是保存之后不会返回id
 @Configuration
public class TkMapperConfig {

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("com.xxxx.dao");
        Properties propertiesMapper = new Properties();
        //通用mapper位置,不要和其他mapper、dao放在同一个目录
        propertiesMapper.setProperty("mappers", "com.xxxx.Mapper");
        propertiesMapper.setProperty("notEmpty", "false");
        //主键UUID回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
        propertiesMapper.setProperty("ORDER","BEFORE");
        mapperScannerConfigurer.setProperties(propertiesMapper);
        return mapperScannerConfigurer;
    }

}
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY,generator = "select uuid()")
        private String id;
. 整形自增方式
在主键上增加注解

    [@Id](https://my.oschina.net/u/3451001)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

bug—以上方式可生成ID自增,但是批量插入数据的时候,生成的主键都是同一个序列(比如2027),导致id重复
解决方法:修改注解
    [@Id](https://my.oschina.net/u/3451001)
    @GeneratedValue(generator = "JDBC")             
    private Long id;

21 IE浏览器上传文件时代路径处理方式

org.apache.commons.io.FilenameUtils.getName();

22 hystrix传递threadlocal

主线程与子线程之间传递变量

 public static ThreadLocal<Map<String, Object>> threadLocal = new InheritableThreadLocal<Map<String, Object>>();

23 上传UT000036: Connection terminated parsing multipart data

https://stackoverflow.com/questions/39049381/react-native-file-upload-to-spring-undertow-server-get-error-java-io-ioexceptio
https://github.com/SoftInstigate/restheart/issues/111
上传时没有加boundry 参数

24 fegin

http://blog.csdn.net/jeffleo/article/details/71493208

json格式化

 spring:
    jackson:
        serialization:
            indent_output: true

25 'itemsCustom' on field 'createtime': rejected value [2015-02-03 13:22:53]

@InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); }

26 文件下载

public void downLoadFile(String ids, HttpServletRequest request, HttpServletResponse response) {
        if(StrUtil.isEmpty(ids)){
            throw new ECGFileException(CommonConstants.JSON_DATA_ERROR);
        }
        response.reset();
        response.setContentType("application/octet-stream; charset=UTF-8");
        Integer[] fileIds  = Convert.toIntArray(StrUtil.splitToArray(ids,','));
        if(fileIds.length == 1){
            //下载单个文件、
            try {
                FileInfo fileInfo = fileInfoService.selectById(fileIds[0]);
                response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileInfo.getOriginalName().getBytes(), "ISO8859-1"));
                response.addHeader("Content-Length", "" + fileInfo.getFileLength());

                FileUtil.writeToStream(new File(fileInfo.getPath()+fileInfo.getSaveName()),response.getOutputStream());
            } catch (IOException e) {
                throw new ECGFileException(RestConstant.ECG_FILE_DOWN_ERROR);
            }
        }else {
            //下载压缩文件
            String downLoadFileName = "";
            List<File> filePaths = new ArrayList<>();
            for (Integer fileId : fileIds) {
                if(fileId == null){
                    throw new ECGFileException(CommonConstants.JSON_DATA_ERROR);
                }
                FileInfo fileInfo = fileInfoService.selectById(fileId);
                filePaths.add(new File(fileInfo.getPath()+fileInfo.getSaveName()));
                //这里取最后一个吧
                downLoadFileName = fileInfo.getOriginalName();
            }
            //生成压缩文件
            com.ge.hcd.ecg.common.util.ZipUtil.zipFile(LibraryConstant.FILE_TEMP+downLoadFileName+".zip",filePaths);
            //下载压缩文件
            downLoadFileName = downLoadFileName + ".zip";
            try {
                File downLoadZip = new File(LibraryConstant.FILE_TEMP+downLoadFileName);
                response.addHeader("Content-Disposition", "attachment;fileName=" + new String(downLoadFileName.getBytes(), "ISO8859-1"));
                response.addHeader("Content-Length", "" + downLoadZip.length());

                FileUtil.writeToStream(downLoadZip,response.getOutputStream());
            } catch (IOException e) {
                throw new ECGFileException(RestConstant.ECG_FILE_DOWN_ERROR);
            }
        }





    }
    
    public void eoFileDown(String objectKey, HttpServletRequest request, HttpServletResponse response){
        InputStream in = null;
        OSSObject ossObject = null;
        // 设置强制下载不打开
        response.setContentType("application/force-download");
        // 设置文件名
        try {
            ossObject = ossClient.getObject(ossProperties.getBucketName(), objectKey);
            response.addHeader("Content-Disposition", "attachment;fileName=" + new String(objectKey.getBytes(), "ISO8859-1"));
            OutputStream os = response.getOutputStream();
            byte[] buf = new byte[1024];
            in = ossObject.getObjectContent();
            for (int n = 0; n != -1; ) {
                n = in.read(buf, 0, buf.length);
                os.write(buf, 0, n);
            }

        }catch(Exception e){
            throw new ECGFileException(RestConstant.ECG_FILE_DOWN_ERROR);
        } finally {
            try {
                if(null != in){
                    in.close();
                }
                if(null != ossObject){

                    ossObject.getObjectContent().close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw new ECGFileException(RestConstant.ECG_FILE_DOWN_ERROR);
            }

        }

    }
    
    

27 spring-cloud 接入第三方接口


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ge.hcd</groupId>
    <artifactId>ecg-sidecar</artifactId>
    <version>1.0-SNAPSHOT</version>


    <name>ecg-sidecar-broker</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR4</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-sidecar</artifactId>
        </dependency>
        <dependency>
            <groupId>com.internetitem</groupId>
            <artifactId>logback-elasticsearch-appender</artifactId>
            <version>1.6</version>
        </dependency>
    </dependencies>

    <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>

    <distributionManagement>
        <repository>
            <id>releases</id>
            <name>ECG-Release</name>
            <url>http://10.189.131.248:8080/archiva/repository/releases/</url>
        </repository>

        <snapshotRepository>
            <id>snapshots</id>
            <name>ECG-SNAPSHOTS</name>
            <url>http://10.189.131.248:8080/archiva/repository/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

    <repositories>
        <repository>
            <id>archiva.default</id>
            <name>archiva.mirror</name>
            <url>http://10.189.131.248:8080/archiva/repository/snapshots/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
server:
    port: 10109 #启动端口

spring:
    application:
        name: ecg-sidecar-server

sidecar:
    port: 9200 #非java语言接口
    health:
        uri: http://10.189.131.211:${sidecar.port}/health
        ## 这必须是localhost

eureka:
  instance:
    prefer-ip-address: true
    #ip-address: 127.0.0.1
    hostname: 10.189.131.211
    metadata-map:
      user.name: ${security.user.name}
      user.password: ${security.user.password}
  client:
    service-url:
      registerWithEureka: true
      fetchRegistry: true
      ##defaultZone: http://${security.user.name}:${security.user.password}@111.231.222.99:8761/eureka/
      defaultZone: http://${security.user.name}:${security.user.password}@10.189.131.211:1599/eureka/


security:
  user:
    name: cloudecg
    password: cloudecg


es:
  elasticsearch:
    bluk: http://10.189.131.211:1597/_bulk
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: false
import com.ge.hcd.ecg.beans.admin.User;
import com.ge.hcd.ecg.common.msg.ObjectRestResponse;
import feign.Response;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @Author: Haibo.Mei [Haibo.Mei@ge.com]
 * @Description:
 * @Date: 15:39 2018/1/15
 */
@FeignClient(name = "ecg-sidecar-server")
public interface ISidecarServer {


    @RequestMapping(value = "/ecgapi/broker/ReportMaker")
    Response reportMaker(@RequestParam(value = "jsonPatientInfo") String jsonPatientInfo,
                         @RequestParam("institudeId") String institudeId,
                         @RequestParam("repJianPin") String repJianPin);
    

}

public void reportMaker(String jsonPatientInfo,
                                      String institudeId,
                                      String repJianPin,
                                      HttpServletRequest request,
                                      HttpServletResponse response){
        try {
            log.info("开始请求第三方接口 /ecgapi/broker/ReportMaker ");
            Response sidecarResponse = sidecarServer.reportMaker(jsonPatientInfo,institudeId,repJianPin);
            log.info("请求成功{}",sidecarResponse);



            Map<String, Collection<String>> headers = sidecarResponse.headers();
            HttpHeaders httpHeaders = new HttpHeaders();

            response.reset();
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

            headers.forEach((key, values) -> {
                List<String> headerValues = new LinkedList<>();
                headerValues.addAll(values);
                httpHeaders.put(key, headerValues);
                log.info("header-key:{},value:{}",key,headerValues.get(0));
                response.setHeader(key,headerValues.get(0));

            });

            Response.Body body = sidecarResponse.body();
            InputStream inputStream = body.asInputStream();

            OutputStream os = response.getOutputStream();
            byte[] buf = new byte[1024];

            for (int n = 0; n != -1; ) {
                n = inputStream.read(buf, 0, buf.length);
                os.write(buf, 0, n);
            }


        } catch (IOException e) {
            e.printStackTrace();
            throw new BaseException(RestConstant.ECG_SIDECAR_ERROR);
        }



    }

28 springcloud 上传文件中文乱码

spring:
  http:
    encoding:
      charset: UTF-8
      force: true
      enabled: true
    multipart:
      max-file-size: 20Mb
      max-request-size: 20Mb
server:
  tomcat:
    uri-encoding: UTF-8

29 URL设置代理

git config --global https.proxy https://3.20.128.6:88

            System.setProperty("proxySet", "true");
            System.setProperty("proxyHost", "3.20.128.6");
            System.setProperty("proxyPort", "88");

30 springboot windows 做微服务

https://github.com/JoyLau/joylau-springboot-daemon-windows

31 properties 配置写法

@Component
@ConfigurationProperties(prefix = "write.datasource")

32 git设置代理

git config --global http.proxy http://3.20.128.6:88 git config --global https.proxy http://3.20.128.6:88

撤销代理

git config --global --unset http.proxy git config --global --unset https.proxy

检查当前代理 git config --global --get http.proxy git config --global --get https.proxy

33 一、校验数字的表达式

1 数字:^[0-9]*$

2 n位的数字:^\d{n}$

3 至少n位的数字:^\d{n,}$

4 m-n位的数字:^\d{m,n}$

5 零和非零开头的数字:^(0|[1-9][0-9]*)$

6 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$

7 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$

8 正数、负数、和小数:^(-|+)?\d+(.\d+)?$

9 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$

10 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$

11 非零的正整数:^[1-9]\d$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]*$

12 非零的负整数:^-[1-9][]0-9"$ 或 ^-[1-9]\d$

13 非负整数:^\d+$ 或 ^[1-9]\d*|0$

14 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$

15 非负浮点数:^\d+(.\d+)?$ 或 ^[1-9]\d.\d|0.\d[1-9]\d|0?.0+|0$

16 非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d.\d|0.\d[1-9]\d))|0?.0+|0$

17 正浮点数:^[1-9]\d.\d|0.\d[1-9]\d$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$

18 负浮点数:^-([1-9]\d.\d|0.\d[1-9]\d)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$

19 浮点数:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d.\d|0.\d[1-9]\d|0?.0+|0)$

34 二、校验字符的表达式

1 汉字:^[\u4e00-\u9fa5]{0,}$

2 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$

3 长度为3-20的所有字符:^.{3,20}$

4 由26个英文字母组成的字符串:^[A-Za-z]+$

5 由26个大写英文字母组成的字符串:^[A-Z]+$

6 由26个小写英文字母组成的字符串:^[a-z]+$

7 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$

8 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$

9 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$

10 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$

11 可以输入含有^%&',;=?$"等字符:[^%&',;=?$\x22]+

12 禁止输入含有~的字符:[^~\x22]+

35 三、特殊需求表达式

1 Email地址:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$

2 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?

3 InternetURL:[a-zA-z]+://[^\s] 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=])?$

4 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

5 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^((\d{3,4}-)|\d{3.4}-)?\d{7,8}$

6 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}

7 身份证号(15位、18位数字):^\d{15}|\d{18}$

8 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$

9 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

10 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$

11 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$

12 日期格式:^\d{4}-\d{1,2}-\d{1,2}

13 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$

14 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$

15 钱的输入格式:

16 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$

17 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$

18 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$

19 4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$

20 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$

21 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$

22 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$

23 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

24 备注:这就是最终结果了,别忘了"+"可以用"*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里

25 xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+.[x|X][m|M][l|L]$

26 中文字符的正则表达式:[\u4e00-\u9fa5]

27 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))

28 空白行的正则表达式:\n\s*\r (可以用来删除空白行)

29 HTML标记的正则表达式:<(\S?)[^>]>.?</\1>|<.? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)

30 首尾空白字符的正则表达式:^\s|\s$或(^\s)|(\s$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)

31 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)

32 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)

33 IP地址:\d+.\d+.\d+.\d+ (提取IP地址时有用)

34 IP地址:((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d).){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))

36 windows安装服务

将bat配置成windows服务

https://segmentfault.com/a/1190000010752320

37 消息路径有 /user 的问题

这个坑是关于路径的问题,小伙伴可能会比较疑问为什么我的订阅里面有/user的前缀,这个其实是因为我们要用的SimpMessagingTemplate的convertAndSendToUser源码实现,默认的前缀是user,所以才会加/user前缀,这也是发给特定用户消息的核心

38 springboot- websocket 问题

39 nginx配置,避免跨域

https://get233.com/archives/connect-to-websocket-failed-in-spring-boot-with-nginx-proxy.html

        location /ecg-websocket/ {  
		
	        proxy_set_header Host $Host;
			
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Port $Server_port;
			proxy_set_header X-Forwarded-Proto $scheme;

			proxy_http_version 1.1;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "upgrade";
			proxy_pass http://106.75.8.121:1595/ecg-websocket/; 		
		}

##40 java配置 websocket配置 "/queue" 是点对点推送 "/topic" 是广播推送

@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        //解决浏览器跨域的问题
        stompEndpointRegistry.addEndpoint("/ecg-websocket").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {

        registry.setApplicationDestinationPrefixes("/ecgapp");
        //配置消息代理(MessageBroker)。
        registry.enableSimpleBroker("/queue","/topic");
    }
}

监听事件

@Slf4j
@Component
public class ConnectEventListener implements ApplicationListener<SessionConnectedEvent> {

	@Autowired
	private SocketSessionRegistry webAgentSessionRegistry;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private UserAuthUtil userAuthUtil;

	@Override
	public void onApplicationEvent(SessionConnectedEvent sessionConnectedEvent) {


		StompHeaderAccessor sha = StompHeaderAccessor.wrap(sessionConnectedEvent.getMessage());
		//login get from browser
		MessageHeaderAccessor accessor = NativeMessageHeaderAccessor.getAccessor(sessionConnectedEvent.getMessage(), SimpMessageHeaderAccessor.class);
		accessor.getMessageHeaders();
		Object header = accessor.getHeader("simpConnectMessage");
		GenericMessage<?> generic = (GenericMessage<?>) accessor.getHeader("simpConnectMessage");
		Object nativeHeaders = generic.getHeaders().get("nativeHeaders");


		log.info(JsonUtil.toJson(nativeHeaders));
		String sessionId = sha.getSessionId();
		String token = ((Map)generic.getHeaders().get("nativeHeaders")).get("Authorization").toString();
		token = token.substring(1,token.length()-1);

		//验证token的有效性
		//先去redis里查找token信息
        String redistoken = redisTemplate.opsForValue().get(token)+"";
        if(  !(StringUtils.isBlank(redistoken) || "null".equals(redistoken) ) ){
            token = redistoken;
        }

		IJWTInfo user = null;
		try {
			user = userAuthUtil.getInfoFromToken(token);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		webAgentSessionRegistry.registerSessionId(user.getUniqueName(), sessionId);
		log.info("{}-{}加入连接",user.getUniqueName(),sessionId);
	}
}
/**
     * @param message
     * @Author: Haibo.Mei [Haibo.Mei@ge.com]
     * @Description: 发送消息
     * @Date: 13:24 2018/3/1
     */
    @Override
    public ObjectRestResponse sendMessage(Message message) {
        ObjectRestResponse response = new ObjectRestResponse();

        List<String> receivers = message.getReceiver();
        if(receivers.size() == 0){

            //遍历所有的session
            ConcurrentMap<String, Set<String>> allSessionIds = webAgentSessionRegistry.getAllSessionIds();
            for(Map.Entry<String, Set<String>> entry : allSessionIds.entrySet()){
                Set<String> sessionIds = entry.getValue();
                for (String session : sessionIds) {
                    messagingTemplate.convertAndSendToUser(session,"/queue/receive",JsonUtil.toJson(message),createHeaders(session));
                }
            }

        }

        for (String receiver : receivers) {
            String sessionId = StringUtils.join(webAgentSessionRegistry.getSessionIds(receiver).toArray());
            log.info("发送给{},sessionId:{}",receiver,sessionId );
            if(sessionId != null){
                messagingTemplate.convertAndSendToUser(sessionId,"/queue/receive",JsonUtil.toJson(message),createHeaders(sessionId));
            }
        }
        response.setMessage("发送成功");
        return response;
    }

    private MessageHeaders createHeaders(String sessionId) {
        SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
        headerAccessor.setSessionId(sessionId);
        headerAccessor.setLeaveMutable(true);
        return headerAccessor.getMessageHeaders();
    }

41 nginx代理静态资源

经常配了nginx静态目录,死活访问不了,每次访问404.查看文档后,发现nginx配置静态目录使 用以下规则

假如nginx是在本机,静态目录也是在本机,

1、子目录匹配 如下配置

location / {  
    root /data/www;  
}  

访问http://127.0.0.1/时,配匹配/data/www 访问http://127.0.0.1/images时,配匹配/data/www/images 访问http://127.0.0.1/images/1.jpg时,配匹配/data/www/images/1.jpg 也就是说,地址栏里"/"后的路径是直接匹配目录data/www/下的路径

而对于配置

location /images/ {  
    root /data/www;  
}  

访问http://127.0.0.1/images时,配匹配/data/www/images 也就是说,地址栏里/images,直接匹配了/data/www的子目录. 经常出问题的是,location里的url随意配了一个名字,如/xxx,但是对应的/data/www目录 下并没有该/data/www/xxx子目录,一访问就404

2、重复路径匹配规则

对于如下配置:

server {  
    location / {  
        root /data/www;  
    }  
  
    location /images/ {  
        root /data;  
    }  
}  

访问URL http://localhost/images/example.png,将会匹配第二个/images/规则, 虽然也可以匹配location /规则,但nginx默认会选择最长前缀去匹配当前URL,也就是 第二个配置会生效,访问/data/images/目录,而不是/data/www/images/目录

image_1c93mtasg1501h0k1oaf1goqbp719.png-19.8kBimage_1c93mtqigev21vau1qaa1fe1o3i1m.png-13.7kB

42 windows安装docker

43 docker部署

44 docker容器之间通讯

https://blog.csdn.net/zhangyifei216/article/details/50921215

45 使用 --link

同一个宿主机上的多个docker容器之间如果想进行通信,可以通过使用容器的ip地址来通信,也可以通过宿主机的ip加上容器暴露出的端口号来通信,前者会导致ip地址的硬编码,不方便迁移,并且容器重启后ip地址会改变,除非使用固定的ip,后者的通信方式比较单一,只能依靠监听在暴露出的端口的进程来进行有限的通信。通过docker的link机制可以通过一个name来和另一个容器通信,link机制方便了容器去发现其它的容器并且可以安全的传递一些连接信息给其它的容器。其使用方式如下:

1.运行一个容器,通过–name指定一个便于记忆的名字,这个容器被称为source container,也就是要连接的容器

docker run --name db -e MYSQL_ROOT_PASSWORD=server -d mysql 1 上面通过传递环境变量MYSQL_ROOT_PASSWORD=server,来设置mysql服务的密码为server

2.运行另外一个容器,并link到上面启动的容器,这个容器被称为received container

sudo docker run -d --name web --link db:aliasdb nginx 1 上面通过--link连接名为db的容器,并为其设置了别名aliasdb 完成了上面的两个步骤后,在nginx的容器中就可以使用db或者aliasdb作为连接地址来连接mysql服务,即使容器重启了,地址发生了变化,不会影响两个容器之间的连接。

docker镜像加速地址

{ "registry-mirrors": ["https://znun8b60.mirror.aliyuncs.com"] }

image_1ch06kn4610n31g1okk019v21eem.png-21.4kB

image_1ch06tvhc1qv218nelp91ljg8k813.png-25.8kB

image_1ch076qee1bjj1ri61v3v1g4c140d1g.png-100.3kB

列出所有容器

docker ps -a

[root@bogon HCD.ECG.Broker]# docker run --name broker -i -t -v /opt/broker/HCD.ECG.Broker/:/data broker bash

48 清除所有终止的容器

docker container prune

49 清楚虚悬镜像

docker image prune

50 自己的docker命令

docker run --name angel-center sha256:221f0bd729499e05d177540216b80d8dbef925e5c4228d1e7e05e30991ce3fd4 --network angel-net

docker run --name angel-admin  sha256:70d155bb1237a307f035cd099d6f852e13a0a9efbafe4e1601bcb3b3ba43f66f --network angel-net

docker run -d -p 3306:3306 --name angel-mysql --network angel-net -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 --lower_case_table_names=1

docker run -d -p 1600:1600 --name angel-auth --network angel-net sha256:f1312d68def79a321bbe4d67f90ec877eb7260da8e76f57faa7ae64676b554fa

docker run -d -p 1666:1666 --name angel-gate --network angel-net sha256:560e5f96d64544b2cf9ecac19b7effa8743970c5f4484f4014267c9822a66d91

docker run -d -p 6379:6379 --name ecg-redis --network ecg-net sha256:c5355f8853e4174a55144edfec23ac37f5bb2200ed838dab53c13c7cc835ab15

docker run -d -p 15672:15672 --name ecg-rabbit --network ecg-net -e RABBITMQ_DEFAULT_USER=cloudecg -e RABBITMQ_DEFAULT_PASS=cloudecg rabbitmq:3-management

docker run --name ecg-nginx --network ecg-net -p 80:80 -v /opt/nginx/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx

docker run -d -p 15672:15672 --name angel-rabbit --network angel-net -e RABBITMQ_DEFAULT_USER=angel -e RABBITMQ_DEFAULT_PASS=angel  sha256:df0ee1f2343b349f830e1602a712dc12ce047aad6e1b052798b3e07bebe724cd



docker run -d -p 3306:3306 --restart=always --name ecg-mysql --network cloudecg -v /opt/mysql/data:/var/lib/mysql -v /etc/localtime:/etc/localtime:ro -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_PASSWORD=123456 mysql:5.7 --lower_case_table_names=1

docker run -d -p 15672:15672 -p 25672:25672 -p 5671:5671 -p 5672:5672 -p 4369:4369 --restart=always  --name ecg-rabbit -e RABBITMQ_DEFAULT_USER=cloudecg -e RABBITMQ_DEFAULT_PASS=cloudecg rabbitmq:3-management

docker run -d -p 6379:6379 --name ecg-redis  --restart=always redis

docker run -d  -p 9200:9200 -p 9300:9300 --name ecg-elasticsearch --restart=always elasticsearch:5.6.4

docker run --name ecg-kibana  --restart=always --link ecg-elasticsearch:elasticsearch -p 5601:5601 -d kibana:5.6.4

docker stop angelbo_angel-kibana_1 docker stop angelbo_angel-rabbit_1 docker stop angelbo_angel-elasticsearch_1 docker stop angelbo_angel-redis_1 docker stop angelbo_angel-center_1 docker stop angelbo_angel-mysql_1 docker stop angelbo_angel-gate_1 docker stop angelbo_angel-admin_1 docker stop angelbo_angel-auth_1

docker start angelbo_angel-kibana_1 docker start angelbo_angel-rabbit_1 docker start angelbo_angel-elasticsearch_1 docker start angelbo_angel-redis_1 docker start angelbo_angel-center_1 docker start angelbo_angel-mysql_1 docker start angelbo_angel-gate_1 docker start angelbo_angel-admin_1 docker start angelbo_angel-auth_1

51 解决docker容器中文乱码问题

.永久修改:修改Dockerfile

  在Dockerfile中添加一行

  ENV LANG C.UTF-8

52 UCloud上传

配置

String bucketName = "lcs20180402";
		String key = "angel_admin";
		String filePath = "C:\\MeiHB-TEMP\\angel_admin.sql";
		String saveAsPath = "C:\\MeiHB-TEMP\\bbb.sql";
		String configPath = "config.properties";
		
		//UFileConfig.getInstance().loadConfig(configPath);
		UFileConfig.getInstance().setUcloudPublicKey("WrKwG1V6fco0KPhlJy6iSGK8xlvl5FUAMyXC4p0516RP/sRPc3OgcA==");
		UFileConfig.getInstance().setUcloudPrivateKey("95bdda90d9be3528e15604df2e1f68fef96927ef");
		UFileConfig.getInstance().setProxySuffix(".cn-bj.ufileos.com");
		UFileConfig.getInstance().setDownloadProxySuffix(".cn-bj.ufileos.com");

53 nodejs 项目,请求返回Invalid Host header问题

devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    disableHostCheck: true,
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    }
  },

54 经过网关上传文件 http://192.168.0.1/zuul/file/upload

使用zuul servlet去上传文件,而不是默认的spring mvc。使用 zuul servlet之需要在请求uri,前面加上”/zuul”即可

55 elasticsearch 索引

curl -XGET 'http://localhost:9200/_cat/indices/?v' curl -XDELETE http://localhost:9200/ecg-center-logs-2018-03-*

56 docker 开启远程API

/usr/lib/systemd/system docker.service文件 修改

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:5555

1、关闭firewall: systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewall开机启动 firewall-cmd --state #查看默认防火墙状态(关闭后显示notrunning,开启后显示running)

docker run --rm --name ecg-center --network ecg-net -p 1599:1599 com.ge.hcd/ecg-center:0.0.1-SNAPSHOT

##57 springboot json排除null 或者 ""字段


@Configuration
public class JacksonConfig {
    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        // 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
        // Include.Include.ALWAYS 默认
        // Include.NON_DEFAULT 属性为默认值不序列化
        // Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
        // Include.NON_NULL 属性为NULL 不序列化,就是为null的字段不参加序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
       /* objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
                jsonGenerator.writeString("");
            }
        });*/
        return objectMapper;
    }
}

58 echarts datazoon

/*myChart.on('dataZoom', function (params) {

                        setTimeout(() => {
                            console.log(myChart.getOption().xAxis[0].data[Math.round(params.start)] + ":" + myChart.getOption().xAxis[0].data[Math.round(params.end)]);
                            let startDate = myChart.getOption().xAxis[0].data[Math.round(params.start)];
                            let endDate = myChart.getOption().xAxis[0].data[Math.round(params.end)];
                            let aaa = {startDate,endDate};
                            Bus.$emit('updateOrgSourceTec', aaa);
                        }, 1000);

                    });*/

59 vue 代理

 // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        target: 'http://localhost:1666',
        secure: false,
        changeOrigin: false,
        pathRewrite: {
          '^/api': '/angel'   //这里是将请求的 '/api'替换为angel
        }
      }
    },

如果请求的API接口地址为 'http://localhost:1666/angel/admin/user/page' 代理后请求的地址为 : '/api/admin/user/page'
会把请求转发到代理地址,并且把/api 替换为 /angel

60 haddop docker

docker run -itd --net=hadoop -p 50070:50070 -p 8088:8088 -p 9000:9000 --name hadoop-master --hostname hadoop-master kiwenlau/hadoop:1.0

docker run -itd --net=hadoop --name hadoop-slave2 --hostname hadoop-slave2 kiwenlau/hadoop:1.0

61 将.net app 和 asp.net程序部署在docker中

使用mono 
https://www.bbsmax.com/A/ZOJPKrDlzv/

62 spirngboot中使用docker的环境变量

当docker启动SpringBoot打包的服务时,且一些参数需要从外界获取而非写死在properties文件里,通过以下两步完成此需求: 1.在配置文件中配置环境变量

spring.redis.host=${REDIS_HOST:127.0.0.1} spring.redis.port=6379 spring.redis.timeout=30000 以上表是REDIS_HOST在系统环境变量中获取,如果获取不到默认值为127.0.0.1

2.在启动docker容器时传入环境参数

docker run -d --name test2 {镜像名} -e REDIS_HOST=192.168.0.1 完成程序配置。

63 docker构建java环境

ENV VERSION 8
ENV UPDATE 111
ENV BUILD 14

ENV JAVA_HOME /usr/lib/jvm/java-${VERSION}-oracle
ENV JRE_HOME ${JAVA_HOME}/jre

RUN wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" \
    -P /tmp \
    http://download.oracle.com/otn-pub/java/jdk/"${VERSION}"u"${UPDATE}"-b"${BUILD}"/jdk-"${VERSION}"u"${UPDATE}"-linux-x64.tar.gz

RUN cd /tmp && tar -zxvf jdk-"${VERSION}"u"${UPDATE}"-linux-x64.tar.gz && \
    mkdir -p /usr/lib/jvm && mv /tmp/jdk1.${VERSION}.0_${UPDATE} "${JAVA_HOME}" && \
    rm -rf /tmp/*

RUN update-alternatives --install "/usr/bin/java" "java" "${JRE_HOME}/bin/java" 1 && \
    update-alternatives --install "/usr/bin/javac" "javac" "${JAVA_HOME}/bin/javac" 1 && \
    update-alternatives --set java "${JRE_HOME}/bin/java" && \
    update-alternatives --set javac "${JAVA_HOME}/bin/javac"

64 创建.net 和 java运行环境

先下载相应版本的JRE

####解压 tar xvcf jre-8u161-linux-x64.tar.gz ####进入目录 cd jre1.8.0_161/ ####删除文本文件 rm -rf COPYRIGHT LICENSE README release THIRDPARTYLICENSEREADME-JAVAFX.txtTHIRDPARTYLICENSEREADME.txt Welcome.html ####删除其他无用文件 rm -rf lib/plugin.jar
lib/ext/jfxrt.jar
bin/javaws
lib/javaws.jar
lib/desktop
plugin
lib/deploy*
lib/javafx
lib/jfx
lib/amd64/libdecora_sse.so
lib/amd64/libprism_.so
lib/amd64/libfxplugins.so
lib/amd64/libglass.so
lib/amd64/libgstreamer-lite.so
lib/amd64/libjavafx
.so
lib/amd64/libjfx*.so

https://hub.docker.com/r/jexus/mono/

FROM centos:latest
MAINTAINER feiin(http://github.com/feiin)

RUN rpm --import "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF" && \
    yum-config-manager --add-repo http://download.mono-project.com/repo/centos/ 

RUN yum -y install mono-complete

ENV JEXUS_VERSION 5.8.3

RUN curl -O -k -L http://www.linuxdot.net/down/jexus-$JEXUS_VERSION.tar.gz && \
    tar -zxvf jexus-$JEXUS_VERSION.tar.gz && \
    cd jexus-$JEXUS_VERSION && \
    ./install 

COPY config /usr/jexus/siteconf

RUN yum -y install openssh-server

RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -C '' -N '' && \
    ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -C '' -N ''  && \
    ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -C '' -N ''

RUN mkdir /www

RUN mkdir /jdk
COPY ./jre1.8.0_181 /jdk
ENV JAVA_HOME /jdk
ENV PATH ${PATH}:${JAVA_HOME}/bin



RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo "Asia/Shanghai" >> /etc/timezone

工程需要

string sysfont = string.Format("/www/Fonts/{0}", systt);

ip = ip == "localhost" ? System.Net.Dns.GetHostAddresses("localhost") .FirstOrDefault(p => p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)?.ToString() : ip;

BrokerServer.Instance.InitServer(); BrokerServer.Instance.StartServer(); Console.Read();

mono-java-jexus-5.8.3:latest 这个是最新版的可以运行。net的
broker 的Dockerfile

broker.sh

#!/bin/bash
nohup mono HCD.ECG.Broker.Test.exe &
tail -fn 1 -s3600 /etc/hosts
FROM mono:5.14
RUN mkdir -p /data
WORKDIR /data
RUN mkdir -p /data/Config
COPY . .
COPY Config /data/data/Config
RUN chmod +x ./broker.sh 
CMD ./broker.sh

65 windows编写shell脚本

在Windows编写的shell文件,在Linux上执行时,常常因为Windows有隐藏的一些符号,而报: /bin/bash^M: bad interpreter: No such file or directory

解决方法: vi shell文件.sh

然后用命令 : set ff? 可以看到dos或unix的字样.

再用 set ff=unix 把它强制为unix格式的, 然后存盘退出. 再运行一遍

66 jenkins安装

docker run -u root --name jenkins -d -p 18080:8080 -p 50000:50000 -v /opt/jenkins-data:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkinsci/blueocean

67 安装中文支持

安装local 插件 设置 zh_CH 即可

##68 maven使用私服和公服设置 maven、 在下在jar包的时候,先查找私服,再找公服

    这个再项目的pom文件上设置
    <repositories>
        <repository>
            <id>archiva.default</id>
            <name>archiva.mirror</name>
            <url>http://10.189.131.248:8080/archiva/repository/snapshots/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
这个再maven的配置未见中加
<mirror>
		<id>nexus-aliyun</id>
		<mirrorOf>*,!archiva.default</mirrorOf> 
		<name>Nexus aliyun</name>
		<url>http://maven.aliyun.com/nexus/content/groups/public</url>
	</mirror>

69 BeanPropertyRowMapper

使用jdbctemple 可以用这个类自动生成rowmapper

70 jenkins On building jenkins project timeout after 10 minute error happens

https://stackoverflow.com/questions/22013217/on-building-jenkins-project-timeout-after-10-minute-error-happens

Edit your job configuration, and under git plugin section:

Click "Add" Click "Advanced clone behaviours" Set the number of minutes you want in "Timeout (in minutes) for clone and fetch operation" I recommend checking also the "shallow clone" option. It fetches only the last state of the repository (without the history), so it's much faster.

71 docker配置代理访问外网

https://www.jianshu.com/p/26d0ebd86673

72 设置ssh免密码登录

https://blog.csdn.net/furzoom/article/details/79139570

ssh-keygen -t rsa ssh-copy-id -i ~/.ssh/id_rsa.pub -p 2222 root@192.168.1.100

73 为npm设置代理

RUN npm config set proxy http://3.20.128.6:88 && npm config set https-proxy http://3.20.128.6:88

74 jenkinsfile

node  {
  stage('pull') {
        checkout(scm: scm, poll: true, changelog: true)
      }

      stage('build-ecg-h5web') {

          def h5web = docker.build("ecg-h5web:jenkins", "./H5WEB")

      }

      stage('stop-ecg-h5web') {
        sh 'if docker -H 10.189.140.225:5555 ps -a| grep -i ecg-h5web; then  docker -H 10.189.140.225:5555 rm -f  ecg-h5web; fi'
      }

      stage('deploy-ecg-h5web') {
        sh 'docker -H 10.189.140.225:5555 run -d --name ecg-h5web --network ecg-net   ecg-h5web'
      }
}

73 docker容器里设置时间

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

74 docker定时清理任务

https://nickjanetakis.com/blog/docker-tip-32-automatically-clean-up-after-docker-daily

75 gate 上传文件中文乱码 /zuul

zuul: servlet-path: /

76 @PathVariable出现点号"."时导致路径参数截断获取不全的解决办法

在@RequestMapping的value中使用SpEL来表示,value中的{version}换成{version:.+}。
@RequestMapping(value="android/download/{version:.+}",method=RequestMethod.GET)
public void download(HttpSession session,HttpServletResponse response,@PathVariable("version")String version){

}

77 group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator '分隔符'] )

以id分组,把price字段的值在同一行打印出来,逗号分隔(默认)

select id, group_concat(price) from goods group by id;

+------+--------------------+ | id| group_concat(price) | +------+--------------------+ |1 | 10,20,20| |2 | 20 | |3 | 200,500| +------+--------------------+

转载于:https://my.oschina.net/angelbo/blog/3004318

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值