首页
归档
留言
友链
广告合作
壁纸
更多
美女主播
Search
1
博瑞GE车机升级/降级
5,603 阅读
2
Mac打印机设置黑白打印
4,931 阅读
3
修改elementUI中el-table树形结构图标
4,892 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,670 阅读
5
intelliJ Idea 2022.2.X破解
4,352 阅读
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Vue
Spring Cloud
Mac
MyBatis
WordPress
MacOS
asp.net
Element UI
Nacos
.Net
Spring Cloud Alibaba
MySQL
Mybatis-Plus
Typecho
jQuery
Java Script
微信小程序
Oracle
Laughing
累计撰写
626
篇文章
累计收到
1,421
条评论
首页
栏目
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
友链
广告合作
壁纸
美女主播
搜索到
626
篇与
的结果
2021-09-05
angular内置指令
ngIf用来决定显示或隐藏元素,指令条件可以是表达式。app.component.html代码<nz-card style="width:300px;" nzTitle="Card title" [nzExtra]="extraTemplate"> <p *ngIf=false>1</p> <p *ngIf="doNotDisplay">2</p> <p *ngIf="display()">3</p> </nz-card> <ng-template #extraTemplate> <a>More</a> </ng-template>app.component.ts代码import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { doNotDisplay: boolean = false display(): boolean { return true } } 隐藏的元素不会创建。ngSwitchngSwitch指令可以通过ngSwitchCase、ngSwitchDefault走不通的分支。app.component.html代码<nz-card style="width:300px;" nzTitle="Card title" [nzExtra]="extraTemplate" [ngSwitch]="choice"> <p *ngSwitchCase="1">1</p> <p *ngSwitchCase="2">2</p> <p *ngSwitchCase="3">3</p> <p *ngSwitchDefault>default</p> </nz-card> <ng-template #extraTemplate> <a>More</a> </ng-template>app.component.ts代码import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { choice: string = "4" }ngStyle给DOM元素设置CSS属性。最简单的用法[style.property]=valueapp.component.html代码<nz-card style="width:300px;" nzTitle="Card title" [nzExtra]="extraTemplate"> <p *ngIf=false>1</p> <p *ngIf="doNotDisplay">2</p> <p *ngIf="display()" [style.background-color]="backgroundColor">3</p> </nz-card> <ng-template #extraTemplate> <a>More</a> </ng-template>app.component.ts代码import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { doNotDisplay: boolean = false backgroundColor: string = 'red' display(): boolean { return true } }另外一种方式是使用键值对<nz-card style="width:300px;" nzTitle="Card title" [nzExtra]="extraTemplate"> <p *ngIf=false>1</p> <p *ngIf="doNotDisplay">2</p> <p *ngIf="display()" [ngStyle]="{'background-color':backgroundColor}">3</p> </nz-card> <ng-template #extraTemplate> <a>More</a> </ng-template>ngClassapp.component.css中定义一个类.bordered{ border: 1px dashed royalblue; }app.component.html代码<div [ngClass]="'bordered'" style="height: 400px;"></div>也可以通过如下代码<div [ngClass]="{bordered:false}" style="height: 400px;"></div>ngFor用于循环app.component.html代码<ul> <li *ngFor="let color of colors" [ngStyle]="{color:color}">{{color}}</li> </ul>app.component.ts代码import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { colors:Array<String> constructor(){ this.colors=[ 'red','blue','green' ] } }循环时,我们也可以获取索引<ul> <li *ngFor="let color of colors;let index=index" [ngStyle]="{color:color}">{{index}}--{{color}}</li> </ul>ngNonBindable指定不编译或者绑定页面中的某个特殊部分。app.component.html代码<p ngNonBindable> {{content}} </p> <p> {{content}} </p>app.component.ts代码import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { content:string="<div>content</div>" }innerHTML、innerText通过{{}}输出内容,会强制转换成文本。我们可以通过[innerHTML]输出html。[innerText]可以将html代码强制输出文本。app.component.html代码<div [innerHTML]="content"> </div> <div [innerText]="content"> </div>app.component.ts代码import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { content:string="<div>测试</div>" }
2021年09月05日
1,091 阅读
0 评论
25 点赞
2021-09-05
angular组件的输入与输出
所谓组件的输入与输出,其实就是给组件传值或者组件往外传值。类似于父组件向子组件传值或者子组件回调父组件的方法(也可以回调传值)。angular在模板上,通过[]实现组件的输入,()实现组件的输出。组件的输入比如有一个test的组件,其中有一个name属性,我们需要通过app组件将name传递给test组件。方式一:通过@Input()注解@Input()注解适合数据比较少的情况。首先,我们需要在TestComponent类中增加一个name属性,然后导入Input,然后在name属性前增加@Input()注解。import { Component, EventEmitter, OnInit,Input } from '@angular/core'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.component.css'] }) export class TestComponent implements OnInit { @Input('newName') name: string; constructor() { this.name = "" } ngOnInit(): void { } } @Input('newName')中的newName代表我们起的一个别名,也就是说在传值的时候,我们是通过[newName]将值传递到组件的name属性。然后我们在模板文件test.component.html增加输出,以便测试值是否传递。<p>{{name}}</p>我们在app.component.html中调用app-test组件,并通过[]传值。<app-test [newName]='"test"'></app-test>测试方式二:通过Inputs[]配置项首先,我们需要在TestComponent类中增加一个name属性,然后在@Component注解中,增加Inputs[]配置项。import { Component, EventEmitter, OnInit } from '@angular/core'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.component.css'], inputs: ['name:newName'] }) export class TestComponent implements OnInit { name: string; constructor() { this.name = "" } ngOnInit(): void { } } inputs: ['name:newName']中,name代表当前类的属性,冒号后面的newName代表别名,也就是说在传值的时候,我们是通过[newName]将值传递到组件的name属性。然后我们在模板文件test.component.html增加输出,以便测试值是否传递。<p>{{name}}</p>我们在app.component.html中调用app-test组件,并通过[]传值。<app-test [newName]='"test"'></app-test>组件的输出angular中通过()实现组件的输出。比如我们在app-test组件中,定义了一个like方法,此方法执行时,回调父组件的ringWasPlace方法,并传递一个字符串。在app.component.ts代码如下import { Component, EventEmitter, OnInit,Input } from '@angular/core'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.component.css'], outputs: ['putRingOnIt'] }) export class TestComponent implements OnInit { putRingOnIt: EventEmitter<string> @Input('newName') name: string; constructor() { this.name = "" this.putRingOnIt = new EventEmitter(); } ngOnInit(): void { } liked(): void { this.putRingOnIt.emit('oh oh oh') } }父组件模板文件app.component.html<app-test [newName]='"test"' (putRingOnIt)="ringWasPlace($event)"></app-test> <h1> {{message}} </h1>父组件类app.component.ts如下import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { message: string; constructor() { this.message = "" } ringWasPlace(message: string):void { this.message = message; } } 测试,点击一下like按钮,看到输出如下
2021年09月05日
990 阅读
0 评论
0 点赞
2021-09-05
开启angular之旅
前言这年头,作为新生代的农民工真的太难了。虽说活到老,学到老,但是学习的速度永远跟不上技术的迭代。细数一下,做过的东西真不少了。angular开发环境打开安装nodejs进入nodejs官网,找到自己对应版本,下载安装即可安装完成后,输入node -v npm -vnpm替换淘宝源npm config set registry https://registry.npm.taobao.org安装angular/cliangular/cli是一个类似工具的东西,具体的我也没有深究,根据我使用一次的直观感受,它的作用就是,安装它后,我们可以通过各种不同的命令行来实现angular项目的创建,运行,调试等等npm install -g @angular/cli输入ng version输出以上页面,代表安装成功。创建angular项目ng new 项目名称创建angular项目,如下示例:创建名为 angular的项目ng new angular生成项目如下运行angular项目在项目文件夹下,输入ng serve打包运行项目,然后我们可以通过默认的4200端口访问http://localhost:4200/查看项目
2021年09月05日
1,093 阅读
0 评论
0 点赞
2021-09-04
关于node的一些默认配置
作为一个后端高企前端真的非常费劲。其实,之前也接触过Node,但是基本属于能用但是不会用的地步。最近在开发时,将一个angular的前端项目从windows迁移到linux继续开发,中间遇到了很多问题,借此记录一下。Linux默认配置可以通过npm config list查看Node的配置列表。也可以通过一下命令,通过可编辑文件的方式编辑配置文件。npm config edit配置文件位于登录用户(我这里使用root登录)的目录下,是个隐藏文件,可以通过以下命令查看cd /root ls -aWin默认配置可以通过npm config list查看Node的配置列表。在windows系统中,npm全局包下载位置在'C:\用户\AppData\Roaming\npm\node_modules'中。修改全局包存储位置可以通过npm config set命令修改默认全局包的存储路径比如npm config set prefix /usr/lib/node_modules将全局包存储路径改到/usr/lib/node_modules也可以通过npm config delete命令删除某个配置项比如npm config delete prefix删除配置的全局包信息。
2021年09月04日
886 阅读
0 评论
0 点赞
2021-08-30
一文撸清楚Java中的枚举enum
Java Enum类型的语法结构尽管和java类的语法不一样,应该说差别比较大。但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>。定义一个枚举定义一个枚举,最简单的方式可能向下面这样public enum Size{ SMALL, MEDIUM, LARGE, EXTRA_LARGE };枚举的构造函数枚举可以定义构造函数,但是必须是private类型。public enum DishType { Fish("FISH"), Chiken("CHIKEN"), Meat("MEAT"); private String type; private DishType(String type) { this.type = type; } public String getType() { return type; } public void setType(String type) { this.type = type; } }你可以向上面这样添加private修饰符或者啥都不添加,但是不能添加public或protect。重写方法与类一样,可以重写枚举的方法,比如toString()方法。public enum DishType { Fish("FISH"), Chiken("CHIKEN"), Meat("MEAT"); private String type; private DishType(String type) { this.type = type; } public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return type; } }获取枚举值可以通过.语法获取枚举值。如果想获取所有的值,可以通过values()方法 for(DishType dishType:DishType.values()){ System.out.println(dishType); }获取原始值可以通过ordinal()方法获取枚举的原始值,也就是1、2、3System.out.println(fish.ordinal());控制台输出0,因为Fish是我们在枚举值第一个定义的,从0开始。反向获取枚举可以通过valueOf()反向获取枚举值DishType.valueOf("Fish");枚举中定义方法比如在枚举中定义一个sayHello方法public void sayHello() { System.out.println("hello,i am " + type); }然后调用 DishType fish = DishType.valueOf("Fish"); fish.sayHello();枚举中的匿名内部类枚举实例后有花括号时,该枚举实例是枚举类匿名内部之类定义性别枚举类package com.company.enumpackage; public enum Gender { //枚举值调用对应构造器创建 MALE("男") { public void info() { System.out.println("这个枚举代表男"); } }, FEMALE("女") { public void info() { System.out.println("这个枚举代表女"); } }, UNKNOWN("UNKNOWN"); private final String name; //枚举类的构造器只能使用private修饰 private Gender(String name) { this.name = name; } public String getName() { return this.name; } public void info() { System.out.println("这是第一个用于定义性别的枚举类"); } }调用Gender male = Gender.MALE; Gender female = Gender.FEMALE; Gender unKnown = Gender.UNKNOWN; male.info(); female.info(); unKnown.info();
2021年08月30日
875 阅读
0 评论
24 点赞
2021-08-29
java8 Optional<T>简介
Optional<T>是Java8增加的一个用于处理NullPointException异常的类。Optional<T>是一个容器类,代表一个值存在或不存在。如果用过Spring Boot Data Jpa,会发现里面好多返回值都是Optional<T>类型的。下面我们介绍一下Optional<T>类的常见使用方法。作为演示,我们创建了一个Dish类,代码如下:public class Dish { /** * 构造函数 * @param name 名称 * @param isVegetarian 是否蔬菜 */ public Dish(String name, boolean isVegetarian) { this.name = name; this.isVegetarian = isVegetarian; } /** * 名称 */ private String name; /** * 是否蔬菜 */ private boolean isVegetarian; @Override public String toString(){ return name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isVegetarian() { return isVegetarian; } public void setVegetarian(boolean isVegetarian) { this.isVegetarian = isVegetarian; } } 创建一个Optional<T>实例创建Optional<T>实例,有两个方法,分别是of、ofNullable,ofNullable与是of的区别在于,如果传递的参数是null,那么会创建一个空的(empty)Optional<T>实例。 Optional<Dish> dishOptionalofNullable = Optional.ofNullable(null); dishOptionalofNullable.ifPresent(System.out::println); System.out.println("准备输出of方法的值"); Optional<Dish> dishOptionalof = Optional.of(null); dishOptionalof.ifPresent(System.out::println);运行代码,我们可以看到如下输出我们可以看到ofNullable创建的实例,即使传递的参数是null调用实例方法时,系统也会抛出异常,而of传递null值时,创建的Optional<T>实例也是null。判断是否为空通过isPresent()方法可以判断Optional<T>包含的类是否是null。返回true代表不是null,返回false代表是null。 Optional<Dish> emptyOptional = Optional.empty(); if (emptyOptional.isPresent()) { System.out.println(emptyOptional.get()); } else { System.out.println("empty optional"); }还有一个方法是ifPresent(Consumer<? super T> action)可以传递一个Consumer接口,当类不是null。 Optional<Dish> emptyOptional = Optional.empty(); emptyOptional.ifPresent(System.out::println);还有一个方法 ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction),当类不是null时,调用action接口,否则调用emptyAction接口。 List<Dish> menu = new ArrayList<>(); Dish fish = new Dish("鱼", false); Dish tomato = new Dish("西红柿", true); menu.add(fish); menu.add(tomato); menu.stream().filter(Dish::isVegetarian).findAny().ifPresentOrElse(System.out::println, () -> { System.out.println("没找到呢"); });获取值获取值比较简单,通过get()方法即可。 Optional<Dish> fishOptional = Optional.ofNullable(new Dish("鱼", false)); if(fishOptional.isPresent()){ System.out.println(fishOptional.get()); }通过orElse(T other)可以设置默认值。 Optional<Dish> fishOptional = Optional.ofNullable(new Dish("鱼", false)); Dish defaultDish = new Dish("default", false); if (fishOptional.isPresent()) { System.out.println(fishOptional.orElse(defaultDish)); } Optional<Dish> emptyOptional = Optional.empty(); System.out.println(emptyOptional.orElse(defaultDish));上面emptyOptional是空的,那么我们可以返回一个默认的Dish实例,下面看下控制台输出。orElse(T other)还有一些变种方法,大家可以试一下。
2021年08月29日
1,013 阅读
0 评论
0 点赞
2021-08-25
java中对象和Map的相互转换
实体对象转map集合private static Map<String, String> obj2Map(Object obj) { Map<String, String> map = new HashMap<String, String>(); // System.out.println(obj.getClass()); // 获取f对象对应类中的所有属性域 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { String varName = field.getName(); varName = varName.toLowerCase();//将key置为小写,默认为对象的属性 try { // 获取原来的访问控制权限 boolean accessFlag = field.isAccessible(); // 修改访问控制权限 field.setAccessible(true); // 获取在对象f中属性fields[i]对应的对象中的变量 Object o = field.get(obj); if (o != null) map.put(varName, o.toString()); // System.out.println("传入的对象中包含一个如下的变量:" + varName + " = " + o); // 恢复访问控制权限 field.setAccessible(accessFlag); } catch (IllegalArgumentException | IllegalAccessException ex) { ex.printStackTrace(); } } return map; }将map集合转化成实体对象利用反射实现/** * Map转成实体对象 * @param map map实体对象包含属性 * @param clazz 实体对象类型 * @return */ public static <T> T map2Object(Map<String, Object> map, Class<T> clazz) { if (map == null) { return null; } T obj = null; try { obj = clazz.newInstance(); Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { int mod = field.getModifiers(); if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) { continue; } field.setAccessible(true); field.set(obj, map.get(field.getName())); } } catch (Exception e) { e.printStackTrace(); } return obj; }
2021年08月25日
918 阅读
0 评论
0 点赞
2021-08-21
java8谓词复合和函数复合
谓词及功能复合,就是在通过组合已有的谓词或功能,形成更加复杂的谓词或功能。谓词复合谓词(Predicate)接口包含三个方法:negate、and和or,通过这三个方法,我们可以在已有谓词的基础上,组合形成更加复杂的谓词。negate代表非,and代表和,or代表或。举个例子,我们有一个苹果(Apple)类,包含颜色(color)和重量(weight)两个属性。class Apple { public Apple(String color, double weight) { this.color = color; this.weight = weight; } private String color; private double weight; @Override public String toString() { return "color:" + color + "---------" + "weight:" + weight; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } } 然后我们创建一个苹果的列表,存储几条测试数据。List<Apple> appleList = new ArrayList<>(); appleList.add(new Apple("red", 2)); appleList.add(new Apple("red", 6)); appleList.add(new Apple("green", 2)); appleList.add(new Apple("green", 6));negate测试我们创建一个查找红色苹果的谓词Predicate<Apple> redApple = apple -> "red".equals(apple.getColor());然后创建一个查找不是红色苹果的谓词List<Apple> notRedAppleList = appleList.stream().filter(notRedApple).collect(Collectors.toList()); for (Apple apple : notRedAppleList) { System.out.println(apple); }and测试我们首先创建一个查找重量大于5的谓词Predicate<Apple> weightThan5Apple = apple -> apple.getWeight() > 5;然后组合红苹果及重量大于5的两个谓词Predicate<Apple> redAndWeightThan5Apple = redApple.and(weightThan5Apple);测试 List<Apple> redAndWeightThan5AppleList = appleList.stream().filter(redAndWeightThan5Apple).collect(Collectors.toList()); for (Apple apple : redAndWeightThan5AppleList) { System.out.println(apple); }or测试还是利用刚才的谓词,这次我们测试重量大于5或者颜色是红色的苹果Predicate<Apple> redOrWeightThan5Apple = redApple.or(weightThan5Apple);测试 List<Apple> redOrWeightThan5AppleList = appleList.stream().filter(redOrWeightThan5Apple).collect(Collectors.toList()); for (Apple apple : redOrWeightThan5AppleList) { System.out.println(apple); }函数复合函数复合跟谓词复合类似,函数复合提供了两个接口方法:andThen和compose,通过字面含义我们可以知道andThen代表先执行第一个函数,然后在执行第二个函数,compose与之相反,先执行第二个函数,在执行第一个函数。 Function<Integer, Integer> funcPlus = x -> x + 1; Function<Integer, Integer> funcMul = y -> y * 2; Function<Integer, Integer> funcAndThen = funcPlus.andThen(funcMul); Function<Integer, Integer> funcCompose = funcPlus.compose(funcMul); System.out.println("andThen:" + funcAndThen.apply(1)); System.out.println("compose:" + funcCompose.apply(1));通过测试,我们发现andThen先执行了第一个函数,也就是1+1=2,然后执行2*2=4,所以最终结果就是4。compose限制性1*2=2,然后执行1+2=3,所以结果是3。
2021年08月21日
989 阅读
0 评论
0 点赞
2021-08-21
java8函数式接口Predicate、Consumer、Function
java8在java.util.function包中给我们预留了几个泛型函数式接口。Predicate、Consumer、Function。Predicate接口里面有一个test方法,接口一个泛型T对象并返回一个boolean值。 static <T> List<T> filter(List<T> list, Predicate<T> predicate) { List<T> result = new ArrayList<>(); for (T t : list) { if (predicate.test(t)) { result.add(t); } } return result; }传递一个String类型的列表,过滤掉其中为空的元素。 List<String> list = new ArrayList<>(); list.add(""); list.add("one"); List<String> result = filter(list,s->s.length()>0); for(String s:result){ System.out.println(s); }Consumer接口里面定义了一个accept方法,接受一个泛型T对象,没有返回值。 static <T> void consumer(List<T> list, Consumer<T> consumer) { for (T t : list) { consumer.accept(t); } }输出列表元素。 consumer(list, System.out::println);Function接口里面定义了一个apply方法,接受一个泛型T,并返回泛型R。static <T,R> List<R> func(List<T> list, Function<T,R> fun){ List<R> result = new ArrayList<>(); for(T t:list){ result.add(fun.apply(t)); } return result; }获取列表每个元素的长度。List<Integer> lengthList=func(list, String::length); for(Integer integer:lengthList){ System.out.println(integer); }
2021年08月21日
1,042 阅读
0 评论
2 点赞
2021-07-31
JVM故障诊断与性能优化之常用虚拟机参数
类加载子系统负责从文件系统或网络中加载Class信息。方法区存放类加载子系统加载的Class信息及运行时常量池信息,包括字符串的字面量和数字常量Java堆在虚拟机启动时建立,是Java程序最主要的内存工作区域,几乎所有的Java对象实例都放于Java堆中。堆空间是线程共享的。直接内存直接内存是在Java堆外直接向系统申请的内存空间,通常,访问直接内存的速度会优于Java堆。因此出于性能考虑,读写频繁的场合可能会考虑使用直接内存。直接内存在Java堆外,因此它的大小不会直接首先与Xmx指定的最大堆大小。垃圾回收系统垃圾回收器可以堆方法区、Java堆和直接内存进行回收。Java栈每个一Java虚拟机线程都有一个私有的Java栈,一个线程的Java栈在线程创建的时候被创建,Java栈中保存着局部变量、方法参数,同时和Java方法的调用、返回密切相关。本地方法栈与Java栈类似,最大的不同在于Java栈用于Java方法的调用,而本地方法栈用于本地方法的调用。作为Java虚拟机的重要扩展,Java虚拟机允许Java直接调用本地的方法(通常使用C编写)PC寄存器寄存器也是每个线程私有的空间,Java虚拟机会为每一个Java线程创建PC寄存器,在任意时刻,一个Java线程总是在执行一个方法,这个正在被执行的方法称为当前方法。如果当前方法不是本地方法,PC寄存器就会只想当前正在被执行的指令,如果当前方法是本地方法,那么PC寄存器的值就是undefined执行引擎负责执行虚拟机的字节码。常见Java虚拟机参数要诊断虚拟机,我们就要学习如何对Java虚拟机进行最基本的配置和跟踪。跟踪垃圾回收可以通过-XX:+PrintGC参数启动Java虚拟机,只要遇到GC,就会打印日志。System.out.println("##########准备申请1m内存#########"); byte[] bytes = new byte[1 * 1024 * 1024]; System.gc();GC和Full GC是垃圾回收的停顿类型,而不是区分是新生代还是年老代,如果有Full说明发生了Stop-The-World。如果是调用 System.gc()触发的,那么将显示的是Full GC (System) 4878K->1576K(249344K)表示GC 前该区域已使用容量 -> GC 后该区域已使用容量 (该区域内存总容量)0.0013118 secs表示GC所用时间,单位为秒。可以通过-XX:+PrintGCDetails参数来输出更加详细的参数。PSYoungGen:代表新生代。total 75776K, used 1951K代表新生代大小及已使用大小。[0x000000076b800000, 0x0000000770c80000, 0x00000007c0000000)代表新生代的下界、当前上界和上届。eden、from、to代表新生代的三个区,当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳( 上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数-XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。ParOldGen代表老年代
2021年07月31日
608 阅读
0 评论
0 点赞
2021-07-29
Spring Cloud集成Gateway
一、SpringCloud Gateway 简介SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。二、SpringCloud Gateway 特征SpringCloud官方,对SpringCloud Gateway 特征介绍如下:基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0集成 Hystrix 断路器集成 Spring Cloud DiscoveryClientPredicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters具备一些网关的高级功能:动态路由、限流、路径重写从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。简单说明一下上文中的三个术语:Filter(过滤器):和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。Route(路由):网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个ID,一个目标URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。Predicate(断言):这是一个 Java 8 的Predicate,可以使用它来匹配来自HTTP请求的任何内容,例如headers或参数。断言的输入类型是一个 ServerWebExchange。三、Spring Cloud Gateway的处理流程客户端向 Spring Cloud Gateway 发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或之后(post)执行业务逻辑。四、路由匹配规则对于这种配置类的,我们一般情况都会放到配置文件中去配置。Spring Cloud Gateway 的功能很强大,我们仅仅通过 Predicates 的设计就可以看出来,前面我们只是使用了 predicates 进行了简单的条件匹配,其实 Spring Cloud Gataway 帮我们内置了很多 Predicates 功能。Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping 做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。代码Demo父工程依赖<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.3.12.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR12</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <!-- <version>2.1.0.RELEASE</version>--> <version>2.2.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> </dependencies> </dependencyManagement>当前模块依赖 <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies>配置文件server: port: 9527 spring: application: name: cloud-gateway-service cloud: nacos: discovery: server-addr: 192.168.120.180:8848 gateway: discovery: locator: enabled: true routes: - id: payment-routh uri: lb://nacos-provider-payment # 服务名称 predicates: - Path=/app/** - Header=username,laughing可以看到gateway的路由匹配规格主要是包含id、uri、predicates。id随意指定,唯一即可。uri代表配置的路径,可以匹配URL或者服务名称,如果是服务名称,以lb:打头。predicates代表断言,条件为true时才能进入对应的路径。说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。假定转发uri都设定为lb://nacos-provider-payment规则实例说明Path- Path=/gate/,/rule/当请求的路径为gate、rule开头的时,转发到nacos-provider-payment服务Before- Before=2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之前的请求才会被转发到nacos-provider-payment服务After- After=2017-01-20T17:42:47.789-07:00[America/Denver]在某个时间之后的请求才会被转发到nacos-provider-payment服务Between- Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver]在某个时间段之间的才会被转发Cookie- Cookie=chocolate, ch.p名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发Header- Header=X-Request-Id, \d+携带参数X-Request-Id或者满足\d+的请求头才会匹配Host- Host=lisen.cc当主机名为lisen.cc的时候直接转发到nacos-provider-payment服务Method- Method=GET只有GET方法才会匹配转发请求,还可以限定POST、PUT等请求方式测试我们上面代码的匹配规则如果我们访问的路径是/echo开头,并且Header中username=laughing就转发到nacos-provider-payment服务。第一次正常访问第二次,我们配置Header可以看到报404第三次,我们配置Header但是参数值设置为test,可以看到也是报404其他参数配置我们不再测试。五、过滤器规则(Filter)过滤规则实例说明PrefixPath- PrefixPath=/app在请求路径前加上appRewritePath- RewritePath=/test, /app/test访问localhost:9022/test,请求会转发到localhost:8001/app/testSetPathSetPath=/app/{path}通过模板设置路径,转发的规则时会在路径前增加app,{path}表示原请求路径RedirectTo 重定向RemoveRequestHeader 去掉某个请求头信息测试Demo我们只测试一个PrefixPath服务提供者 @GetMapping(value = "app/echo/{string}") public String echo1(@PathVariable("string") String string) { return "app/echo/{string} " + string+"\t当前服务端口:"+serverPort; }配置文件server: port: 9527 spring: application: name: cloud-gateway-service cloud: nacos: discovery: server-addr: 192.168.120.180:8848 gateway: discovery: locator: enabled: true routes: - id: payment-routh uri: lb://nacos-provider-payment # 服务名称 predicates: - Path=/** filters: PrefixPath=/app
2021年07月29日
1,361 阅读
0 评论
1 点赞
2021-07-29
Spring Cloud集成Sentinel之使用OpenFein实现服务调用
在Spring Cloud使用OpenFeign调用Nacos服务提供者中,我们介绍了OpenFeign调用Nacos的方式。在Spring Cloud集成Sentinel之@SentinelResource注解使用一文中,我们也介绍了@SentinelResource注解,但是注解的方式。本文我们更进一步,介绍以下OpenFeign如何与Setinel集成。添加依赖<?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"> <parent> <artifactId>Cloud2020</artifactId> <groupId>cc.lisen</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloudalibaba-consumer-order9003</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.5</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> </dependencies> </project>修改配置文件server: port: 8888 spring: application: name: nacos-consumer-order cloud: nacos: discovery: server-addr: 192.168.120.180:1111 sentinel: transport: dashboard: 192.168.120.180:9000 port: 8719 management: endpoints: web: exposure: include: "*" logging: level: cc.lisen.springcloud.alibaba.service.NacosPaymentService: debug #设置feign客户端超时时间(OpenFeign默认支持ribbon) nacos-provider-payment: ribbon: #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间 ReadTimeout: 5000 #指的是建立连接后从服务器读取到可用资源所用的时间 ConnectTimeout: 5000 NFLoadBalancerRuleClassName: cc.lisen.springcloud.alibaba.config.CustomerBalancerRule sentinel: enabled: true修改启动类@SpringBootApplication //@EnableDiscoveryClient @EnableFeignClients public class NacosConsumerOrderMain8888 { public static void main(String[] args) { SpringApplication.run(NacosConsumerOrderMain8888.class, args); } }定义Feign接口@FeignClient(value = "nacos-provider-payment", fallback = NacosPaymentServiceFallback.class) public interface NacosPaymentService { @GetMapping(value = "/echo/{string}") String echo(@PathVariable("string") String string); } class NacosPaymentServiceFallback implements NacosPaymentService { @Override public String echo(String string) { return "进入feignClient fallback了"; } }定义测试接口 @GetMapping("/echo/{id}") public String echo(@PathVariable("id") String id) { log.info("******************输出:" + id); return nacosPaymentService.echo(id); }
2021年07月29日
1,087 阅读
0 评论
0 点赞
1
...
19
20
21
...
53