spring-cloud爬坑
标签(空格分隔): GE
\10.189.131.249 temp/pwd
[TOC]
1. Feign 做客户端,Hystrix 熔断,Fallback不回调的原因
原因很简单 在版本快速的迭代Feign在新版本中默认是没有开启Hystrix的功能官方文档都没来得及更新 更何况那些一笔带过的简单教程解决方式在配置文件(application)中加上 feign.hystrix.enabled=true
2. 注册中心监听事件
@Configuration@Slf4j@EnableSchedulingpublic 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
这个 logback.xml 放在与 application.properties 同级的目录就可以了,如果不配置 Logback,那么 Spring Boot Admin 就无法管理应用的日志级别
##6. zipkin 存储方式
默认存储是在内存中,重启后数据消失mysql的脚本在zipkin包里已经提供了,只需要执行一下就可以了 io.zipkin.java zipkin-autoconfigure-storage-elasticsearch-http 1.24.0 true
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 后来换成文档里提到的解决,供参考。 * @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实现日志配置而且必须使用
${bluk}
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浏览器提示下载的解决方案
@Beanpublic HttpMessageConverters fastJsonHttpMessageConverters(){ //1.需要定义一个convert转换消息的对象; FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //2处理ie浏览器保存数据时出现下载json数据问题 ListfastMediaTypes = 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
@Configurationpublic 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
23 上传UT000036: Connection terminated parsing multipart data
https://stackoverflow.com/questions/39049381/react-native-file-upload-to-spring-undertow-server-get-error-java-io-ioexceptiohttps://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 = ""; ListfilePaths = 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 接入第三方接口
4.0.0 com.ge.hcd ecg-sidecar 1.0-SNAPSHOT ecg-sidecar-broker Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent 1.5.8.RELEASE UTF-8 UTF-8 1.8 Dalston.SR4 org.springframework.cloud spring-cloud-starter-eureka org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-netflix-sidecar com.internetitem logback-elasticsearch-appender 1.6 org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import releases ECG-Release http://10.189.131.248:8080/archiva/repository/releases/ snapshots ECG-SNAPSHOTS http://10.189.131.248:8080/archiva/repository/snapshots/ archiva.default archiva.mirror http://10.189.131.248:8080/archiva/repository/snapshots/ true true org.springframework.boot spring-boot-maven-plugin
server: port: 10109 #启动端口spring: application: name: ecg-sidecar-serversidecar: port: 9200 #非java语言接口 health: uri: http://10.189.131.211:${sidecar.port}/health ## 这必须是localhosteureka: 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: cloudecges: elasticsearch: bluk: http://10.189.131.211:1597/_bulkhystrix: 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> headers = sidecarResponse.headers(); HttpHeaders httpHeaders = new HttpHeaders(); response.reset(); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); headers.forEach((key, values) -> { List 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: 20Mbserver: tomcat: uri-encoding: UTF-8
29 URL设置代理
git config --global https.proxy
System.setProperty("proxySet", "true"); System.setProperty("proxyHost", "3.20.128.6"); System.setProperty("proxyPort", "88");
30 springboot windows 做微服务
31 properties 配置写法
@Component@ConfigurationProperties(prefix = "write.datasource")
32 git设置代理
git config --global http.proxy git config --global https.proxy
撤销代理
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] 或 ^
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服务
37 消息路径有 /user 的问题
这个坑是关于路径的问题,小伙伴可能会比较疑问为什么我的订阅里面有/user的前缀,这个其实是因为我们要用的SimpMessagingTemplate的convertAndSendToUser源码实现,默认的前缀是user,所以才会加/user前缀,这也是发给特定用户消息的核心
38 springboot- websocket 问题
39 nginx配置,避免跨域
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@EnableWebSocketMessageBrokerpublic 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@Componentpublic class ConnectEventListener implements ApplicationListener{ @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(); Listreceivers = message.getReceiver(); if(receivers.size() == 0){ //遍历所有的session ConcurrentMap > allSessionIds = webAgentSessionRegistry.getAllSessionIds(); for(Map.Entry > entry : allSessionIds.entrySet()){ Set 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; }
访问 访问 访问 也就是说,地址栏里"/"后的路径是直接匹配目录data/www/下的路径
而对于配置
location /images/ { root /data/www; }
访问 也就是说,地址栏里/images,直接匹配了/data/www的子目录. 经常出问题的是,location里的url随意配了一个名字,如/xxx,但是对应的/data/www目录 下并没有该/data/www/xxx子目录,一访问就404
2、重复路径匹配规则
对于如下配置:
server { location / { root /data/www; } location /images/ { root /data; } }
访问URL 虽然也可以匹配location /规则,但nginx默认会选择最长前缀去匹配当前URL,也就是 第二个配置会生效,访问/data/images/目录,而不是/data/www/images/目录
42 windows安装docker
43 docker部署
44 docker容器之间通讯
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": [""] }
列出所有容器
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-netdocker run --name angel-admin sha256:70d155bb1237a307f035cd099d6f852e13a0a9efbafe4e1601bcb3b3ba43f66f --network angel-netdocker run -d -p 3306:3306 --name angel-mysql --network angel-net -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7 --lower_case_table_names=1docker run -d -p 1600:1600 --name angel-auth --network angel-net sha256:f1312d68def79a321bbe4d67f90ec877eb7260da8e76f57faa7ae64676b554fadocker run -d -p 1666:1666 --name angel-gate --network angel-net sha256:560e5f96d64544b2cf9ecac19b7effa8743970c5f4484f4014267c9822a66d91docker run -d -p 6379:6379 --name ecg-redis --network ecg-net sha256:c5355f8853e4174a55144edfec23ac37f5bb2200ed838dab53c13c7cc835ab15docker run -d -p 15672:15672 --name ecg-rabbit --network ecg-net -e RABBITMQ_DEFAULT_USER=cloudecg -e RABBITMQ_DEFAULT_PASS=cloudecg rabbitmq:3-managementdocker run --name ecg-nginx --network ecg-net -p 80:80 -v /opt/nginx/nginx.conf:/etc/nginx/nginx.conf:ro -d nginxdocker run -d -p 15672:15672 --name angel-rabbit --network angel-net -e RABBITMQ_DEFAULT_USER=angel -e RABBITMQ_DEFAULT_PASS=angel sha256:df0ee1f2343b349f830e1602a712dc12ce047aad6e1b052798b3e07bebe724cddocker 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=1docker 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-managementdocker run -d -p 6379:6379 --name ecg-redis --restart=always redisdocker run -d -p 9200:9200 -p 9300:9300 --name ecg-elasticsearch --restart=always elasticsearch:5.6.4docker 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 经过网关上传文件
使用zuul servlet去上传文件,而不是默认的spring mvc。使用 zuul servlet之需要在请求uri,前面加上”/zuul”即可
55 elasticsearch 索引
curl -XGET '' curl -XDELETE
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 或者 ""字段
@Configurationpublic 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
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接口地址为 '' 代理后请求的地址为 : '/api/admin/user/page'
会把请求转发到代理地址,并且把/api 替换为 /angel60 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 8ENV UPDATE 111ENV BUILD 14ENV JAVA_HOME /usr/lib/jvm/java-${VERSION}-oracleENV JRE_HOME ${JAVA_HOME}/jreRUN 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.gzRUN 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*.soFROM centos:latestMAINTAINER 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-completeENV JEXUS_VERSION 5.8.3RUN 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/siteconfRUN yum -y install openssh-serverRUN 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 /wwwRUN mkdir /jdkCOPY ./jre1.8.0_181 /jdkENV JAVA_HOME /jdkENV PATH ${PATH}:${JAVA_HOME}/binRUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeRUN 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/bashnohup mono HCD.ECG.Broker.Test.exe &tail -fn 1 -s3600 /etc/hosts
FROM mono:5.14RUN mkdir -p /dataWORKDIR /dataRUN mkdir -p /data/ConfigCOPY . .COPY Config /data/data/ConfigRUN 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文件上设置archiva.default archiva.mirror http://10.189.131.248:8080/archiva/repository/snapshots/ true true
这个再maven的配置未见中加nexus-aliyun *,!archiva.default Nexus aliyun http://maven.aliyun.com/nexus/content/groups/public
69 BeanPropertyRowMapper
使用jdbctemple 可以用这个类自动生成rowmapper
70 jenkins 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免密码登录
ssh-keygen -t rsa ssh-copy-id -i ~/.ssh/id_rsa.pub -p 2222
73 为npm设置代理
RUN npm config set proxy && npm config set https-proxy
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定时清理任务
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| +------+--------------------+