hutools使用

官网:https://hutool.cn/docs/

简单生成验证码

使用hutools的http服务器发送验证码

 private static void writeToServlet(){ICaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);// captcha.write(response.getOutputStream());//Servlet的OutputStream记得自行关闭哦!HttpUtil.createServer(8088).addAction("/", (request,response)->{captcha.write(response.getOut());}).start();}

如果是通过HttpServletResponse发送,修改为:

 private static void writeToServlet(HttpServletResponse response){ICaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);captcha.write(response.getOutputStream());//Servlet的OutputStream记得自行关闭哦!}

实现简单http服务

写一个简单的登录验证

public class SimpleHttpServer
{public static void main( String[] args ){HttpUtil.createServer(8085)//根据url跳转页面.addAction("/", (request,response)->{response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();String url=request.getPath();if(url.equals("/login")){ListValueMap<String, String> params = request.getParams();if(!replace(params.get("name").toString()).equals("lwf")) {response.getHttpExchange().setAttribute("auth", null);writer.write(message(300, "用户名不存在"));}else {if(!replace(params.get("password").toString()).equals("123")){response.getHttpExchange().setAttribute("auth", null);writer.write(message(300, "密码错误"));}else {response.getHttpExchange().setAttribute("auth", "lwf");writer.write(message(200, "登录成功"));}}}else {if (request.getHttpExchange().getAttribute("auth")!=null&&request.getHttpExchange().getAttribute("auth").equals("lwf")) {Map<String,Object> msg=new HashMap<>();msg.put("code", 200);msg.put("msg", "已登录用户"+request.getHttpExchange().getAttribute("auth"));writer.write(JSONUtil.toJsonPrettyStr(msg));}else {writer.write(message(300, "用户未登录"));}}writer.flush();writer.close();}).start();}private static String message(Integer code,String msg){Map<String,Object> response=new HashMap<>();response.put("code", code);response.put("msg", msg);return JSONUtil.parse(response).toStringPretty();}public static String replace(String value){return value.substring(1, value.lastIndexOf(']'));}
}

上面的代码是:在8085端口监听,如果url是login就检查用户名密码,否则去首页(需要检查登录凭证)。这个小demo就是用来玩的,因为这个东西是单线程的而且多次访问共享一个凭证(相当于session),只要有一个地方登录成功,其他地方都拥有凭证;

正确密码登录:

首页

换个浏览器,访问首页(不用登录,但是首页会通过,和上面的共享了自定义的凭证;

而且这个action封装的request,response并不是servlet的HttpServletRequest和HttpServletResponse,而是hutools自己弄得,我没有发现可以发cookie的地方,所有要模仿session;

还有实现简单的文件服务器

作为文件服务器根路径

public class FileServer {public static void main(String[] args) {//根据url获取文件HttpUtil.createServer(8889)// 设置默认根目录,该文件夹下文件访问路径为   localhost:8888/文件名.setRoot("G:\\Dockerfile\\nginx\\html\\baidu").start();//上传文件到根路径HttpUtil.createServer(8888)// 设置默认根目录,该文件夹下文件访问路径为   localhost:8888/文件名// .setRoot("G:\\Dockerfile\\nginx\\html\\baidu").addAction("/file", (request, response) -> {final UploadFile file = request.getMultipart().getFile("file");// 传入目录,默认读取HTTP头中的文件名然后创建文件file.write("G:\\Dockerfile\\nginx\\html\\baidu");response.write("OK!", ContentType.TEXT_PLAIN.toString());}).start();}
}

8889端口映射本地路径:G:\\Dockerfile\\nginx\\html\\baidu ,该目录下的文件,全路径将G:\\Dockerfile\\nginx\\html\\baidu替换为http://localhost:8889

上传文件端口为8888,上传url为file,且表单提交文件name属性为file

上传成功,访问该图片http://localhost:8889/img1.jfif,可以看到请求图片成功

http请求

spring boot使用的是RestTemplate

这里演示hutools的Http请求;

public class HttpRequest {public static void main(String[] args) {
//        //链式构建请求,表单数据提交
//        String result2 = HttpRequest.post(url)
//                .header(Header.USER_AGENT, "Hutool http")//头信息,多个头信息多次调用此方法即可
//                .form(paramMap)//表单内容
//                .timeout(20000)//超时,毫秒
//                .execute().body();
//        Console.log(result2);Panda panda=new Panda();panda.setName("大熊猫");panda.setPlace("四川");String result2 = cn.hutool.http.HttpRequest.post("http://localhost:8091/test/post").body(JSONUtil.parse(panda).toStringPretty()).execute().body();System.out.println("响应数据");System.out.println(result2);Reciver bean = JSONUtil.toBean(result2, Reciver.class);System.out.println(bean.getData());}
}

控制器:http://localhost:8091/test/post,并接收json数据

@RestController
@RequestMapping("/test")
public class TestController {@PostMapping("/post")public Map<String,Object> test(@RequestBody Panda panda){Map<String,Object> map=new HashMap<>();map.put("type", "json");map.put("data", panda);map.put("msg", "接受到数据");return map;}
}

这里接收到响应,并且将响应的json转为对象。

DFA关键搜索和布隆过滤

DFA

import cn.hutool.dfa.WordTree;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;import java.util.List;/*** DFA检索关键字*/
public class AppTest
{WordTree tree=new WordTree();@Beforepublic void before(){tree.addWord("大");tree.addWord("大土豆");tree.addWord("土豆");tree.addWord("刚出锅");tree.addWord("出锅");}/*** 情况一:标准匹配,匹配到最短关键词,并跳过已经匹配的关键词*/@Testpublic void shouldAnswerWithTrue(){//正文String text = "我有一颗大土豆,刚出锅的";// 匹配到【大】,就不再继续匹配了,因此【大土豆】不匹配// 匹配到【刚出锅】,就跳过这三个字了,因此【出锅】不匹配(由于刚首先被匹配,因此长的被匹配,最短匹配只针对第一个字相同选最短)List<String> matchAll = tree.matchAll(text, -1, false, false);Assert.assertEquals(matchAll.toString(), "[大, 土豆, 刚出锅]");}/*** 情况二:匹配到最短关键词,不跳过已经匹配的关键词*/@Testpublic void two(){//正文String text = "我有一颗大土豆,刚出锅的";// 【大】被匹配,最短匹配原则【大土豆】被跳过,【土豆继续被匹配】
// 【刚出锅】被匹配,由于不跳过已经匹配的词,【出锅】被匹配List<String> matchAll = tree.matchAll(text, -1, true, false);Assert.assertEquals(matchAll.toString(), "[大, 土豆, 刚出锅, 出锅]");}/*** 情况三:匹配到最长关键词,跳过已经匹配的关键词*/@Testpublic void three(){//正文String text = "我有一颗大土豆,刚出锅的";// 匹配到【大】,由于到最长匹配,因此【大土豆】接着被匹配
// 由于【大土豆】被匹配,【土豆】被跳过,由于【刚出锅】被匹配,【出锅】被跳过List<String> matchAll = tree.matchAll(text, -1, false, true);Assert.assertEquals(matchAll.toString(), "[大, 大土豆, 刚出锅]");}/*** 情况四:匹配到最长关键词,不跳过已经匹配的关键词(最全关键词)*/@Testpublic void four(){//正文String text = "我有一颗大土豆,刚出锅的";// 匹配到【大】,由于到最长匹配,因此【大土豆】接着被匹配,由于不跳过已经匹配的关键词,土豆继续被匹配
// 【刚出锅】被匹配,由于不跳过已经匹配的词,【出锅】被匹配List<String>   matchAll = tree.matchAll(text, -1, true, true);Assert.assertEquals(matchAll.toString(), "[大, 大土豆, 土豆, 刚出锅, 出锅]");}
}

我们在before里初始化WrodTree;

tree.addWord(“大”);
tree.addWord(“大土豆”);
tree.addWord(“土豆”);
tree.addWord(“刚出锅”);
tree.addWord(“出锅”);

对应的DFA:

布隆过滤

public class BloomFilter {public static void main(String[] args) {// 初始化BitMapBloomFilter filter = new BitMapBloomFilter(10);filter.add("123");filter.add("abc");filter.add("ddd");// 查找System.out.println(filter.contains("abc"));}
}

布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。

Bloom Filter跟单哈希函数Bit-Map不同之处在于:Bloom Filter使用了k个哈希函数,每个字符串跟k个bit对应。从而降低了冲突的概率。

下面这张图是我在网上找的,这张图的模式可能存在

这里出现的构造方法:

 public BitMapBloomFilter(int m) {long mNum = NumberUtil.div(String.valueOf(m), String.valueOf(5)).longValue();long size = mNum * 1024L * 1024L * 8L;this.filters = new BloomFilter[]{new DefaultFilter(size), new ELFFilter(size), new JSFilter(size), new PJWFilter(size), new SDBMFilter(size)};}

这里传入了5个hash处理类,并且使用10*223位bit数组记录hash。布隆过滤器会使用这5个类的hash()方法对加入的每个元素分别求值(作为下标),然后把bit数组相应下标的bit位置为1。(有几个过滤器就有几个这样的数据)

传入元素:filter.add("123");

new DefaultFilter(size):

该类的核心

public long hash(String str) {return (long)HashUtil.javaDefaultHash(str) % this.size;}

调用了:

public static int javaDefaultHash(String str) {int h = 0;int off = 0;int len = str.length();for(int i = 0; i < len; ++i) {h = 31 * h + str.charAt(off++);}return h;}
HashUtil.javaDefaultHash("abc") % 10 * 1024 * 1024 * 8

结果为:33554432

每个过滤器都维护了一个BitMap

这里的BitMap是用int数组存的,而且默认数组长度很大,并且多个过滤器还不是共享同一个BitMap的(避免多个过滤器间在不同元素的hash碰撞,使用空间弥补准确率,和布隆过滤器原始的模型有优有劣吧。),所以可以见得空间耗费极为巨大,但是与运算很快,效率很高:

public class IntMap implements BitMap, Serializable {private static final long serialVersionUID = 1L;private final int[] ints;public IntMap() {this.ints = new int[93750000];}public IntMap(int size) {this.ints = new int[size];}public void add(long i) {int r = (int)(i / 32L);int c = (int)(i % 32L);this.ints[r] |= 1 << c;}public boolean contains(long i) {int r = (int)(i / 32L);int c = (int)(i % 32L);return (this.ints[r] >>> c & 1) == 1;}public void remove(long i) {int r = (int)(i / 32L);int c = (int)(i % 32L);int[] var10000 = this.ints;var10000[r] &= ~(1 << c);}
}

excel表格从对象数组的导入导出

这个东西对应数据库数据表的导入导出简单了许多;

比如上星期写的数据库表通过控制器导入导出的,开始使用了opi,从网上找的代码,改啊改,表的字段有28个,写了100多行,步骤冗余,每个字段操作差不多却要重复28次。写的代码有臭又长。

EasyPoi(个人觉得并不Easy,很容易出问题)

改进时使用了EasyPoi对表导出,但是导入却一直空指针异常,而且数据库表对应pojo类要在类上和属性上加注解ExcelTarget,Excel。代码如下:

依赖:

<dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.0.0</version></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-web</artifactId><version>4.0.0</version></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-annotation</artifactId><version>4.0.0</version></dependency>

pojo类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_employee")
@ApiModel(value="Employee对象", description="")
@ExcelTarget("employee")
public class Employee implements Serializable {@ApiModelProperty(value = "员工编号")@TableId(value = "id", type = IdType.AUTO)private Integer id;@Excel(name = "员工姓名")@ApiModelProperty(value = "员工姓名")private String name;@Excel(name="性别")@ApiModelProperty(value = "性别")private String gender;@Excel(name="出生日期")@ApiModelProperty(value = "出生日期")private LocalDate birthday;@Excel(name="身份证号")@ApiModelProperty(value = "身份证号")private String idCard;@Excel(name="婚姻状况")@ApiModelProperty(value = "婚姻状况")private String wedlock;@Excel(name="民族")@ApiModelProperty(value = "民族")private Integer nationId;@Excel(name="籍贯")@ApiModelProperty(value = "籍贯")private String nativePlace;@Excel(name="政治面貌")@ApiModelProperty(value = "政治面貌")private Integer politicId;@Excel(name="邮箱")@ApiModelProperty(value = "邮箱")private String email;@Excel(name="电话号码")@ApiModelProperty(value = "电话号码")private String phone;@Excel(name="联系地址")@ApiModelProperty(value = "联系地址")private String address;@Excel(name="所属部门")@ApiModelProperty(value = "所属部门")private Integer departmentId;@Excel(name="职称ID")@ApiModelProperty(value = "职称ID")private Integer jobLevelId;@Excel(name="职位ID")@ApiModelProperty(value = "职位ID")private Integer posId;@Excel(name="聘用形式")@ApiModelProperty(value = "聘用形式")private String engageForm;@Excel(name="最高学历")@ApiModelProperty(value = "最高学历")private String tiptopDegree;@Excel(name="所属专业")@ApiModelProperty(value = "所属专业")private String specialty;@Excel(name="毕业院校")@ApiModelProperty(value = "毕业院校")private String school;@Excel(name="入职日期")@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")@ApiModelProperty(value = "入职日期")private LocalDate beginDate;@Excel(name="在职状态")@ApiModelProperty(value = "在职状态")private String workState;@Excel(name="工号")@ApiModelProperty(value = "工号")private String workID;@Excel(name="合同期限")@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")@ApiModelProperty(value = "合同期限")private Double contractTerm;@Excel(name="转正日期")@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")@ApiModelProperty(value = "转正日期")private LocalDate conversionTime;@Excel(name="离职日期")@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")@ApiModelProperty(value = "离职日期")private LocalDate notWorkDate;@Excel(name="合同起始日期")@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")@ApiModelProperty(value = "合同起始日期")private LocalDate beginContract;@Excel(name="合同终止日期")@JsonFormat(pattern="yyyy-MM-dd",timezone = "GMT+8")@ApiModelProperty(value = "合同终止日期")private LocalDate endContract;@Excel(name = "工龄")@ApiModelProperty(value = "工龄")private Integer workAge;@Excel(name = "工资账套ID")@ApiModelProperty(value = "工资账套ID")private Integer salaryId;@ApiModelProperty(value = "工资套账")@TableField(exist = false)private Salary salary;@ApiModelProperty(value = "部门")@TableField(exist = false)private  Department department;}

控制层:

@ApiOperation("导出表格")@RequestMapping(value = "/basic/export")@ResponseBodypublic void export(HttpServletResponse response) throws IOException {List<Employee> employees=employeeService.list();//参数:(一级标题,二级标题,表名),实体类类对象,导出的集合Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("员工列表", "632宿舍", "计算机学院宿舍信息表"),Employee.class, employees);response.setContentType("application/vnd.ms-excel;charset=utf-8");OutputStream os = response.getOutputStream();response.setHeader("Content-disposition", "attachment;filename=employee.xls");//默认Excel名称workbook.write(os);os.flush();os.close();}

很麻烦是不是;

ExcelUtil

这是utools给我们封装的表格工具:

导出

这个方法可以放到工具类里,在控制器中调用,传入数据库传入的对象列表,注入HttpServletResponse就可以了。

 /*** 通过网络导出* @param list* @param response*/private static void writerToNet(List<?> list, HttpServletResponse response){// 通过工具类创建writer,默认创建xls格式ExcelWriter writer = ExcelUtil.getWriter();// 一次性写出内容,使用默认样式,强制输出标题writer.write(list, true);//out为OutputStream,需要写出到的目标流//response为HttpServletResponse对象response.setContentType("application/vnd.ms-excel;charset=utf-8");//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码response.setHeader("Content-Disposition","attachment;filename=test.xls");ServletOutputStream out= null;try {out = response.getOutputStream();} catch (IOException e) {e.printStackTrace();}writer.flush(out, true);// 关闭writer,释放内存writer.close();
//此处记得关闭输出Servlet流IoUtil.close(out);}

我这里测试使用的hutools的httpServer的写法,懒得导入servlet或者使用springboot 的控制器(这个模块是maven的quackStart,懒得导入那么多依赖);

 public static void main(String[] args) throws Exception {//要写入excel的对象列表List<Panda> list= CollUtil.list(true);for(int i=0;i<100;i++){Panda panda=new Panda();panda.setName("熊猫"+i);panda.setPlace("成都");list.add(panda);}//模拟servlet发送表格HttpUtil.createServer(8088).addAction("/", (request,response)->{// 通过工具类创建writer,默认创建xls格式ExcelWriter writer = ExcelUtil.getWriter();// 一次性写出内容,使用默认样式,强制输出标题writer.write(list, true);//out为OutputStream,需要写出到的目标流//response为HttpServletResponse对象response.setContentType("application/vnd.ms-excel;charset=utf-8");//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码response.setHeader("Content-Disposition","attachment;filename=test.xls");OutputStream out= null;try {out = response.getOut();} catch (Exception e) {e.printStackTrace();}writer.flush(out, true);// 关闭writer,释放内存writer.close();//此处记得关闭输出Servlet流IoUtil.close(out);}).start();}

访问http://localhost:8088/

下面就是对象列表导出的excel

我们可以看出,在导出非常多字段的表时,EasyPoi需要写非常多注解,而hutools则以不变应万变,只要传入对象数据和HttpServletResponse就可以导出;

导入

public class ImportTable
{public static void main( String[] args ){HttpUtil.createServer(8088).addAction("/file", (request, response) -> {final UploadFile file = request.getMultipart().getFile("file");//关键代码,就两行ExcelReader reader = ExcelUtil.getReader(file.getFileInputStream());reader.readAll(Panda.class).forEach(System.out::println);}).start();}
}

是不是很简单,传入一个excel文件的MultiFile就可以了;

 //前端文件input传过来的Multipart文件ExcelReader reader = ExcelUtil.getReader(file.getFileInputStream());//读出Panda.class的List列表,这里我直接forEach打印了reader.readAll(Panda.class).forEach(System.out::println);

前端:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title></head><body><form action="http://localhost:8088/file" enctype="multipart/form-data" method="post">选择文件:<input name="file" type="file" /><br><input type="submit"  value="提交文件"/></form></body>
</html>

时钟调度(spring quartz 和CronUtil)

hutools也写了一套时钟调度;

spring quartZ

配置类:这是固定的,可以定义多个Job和多个触发器

任务执行时间(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *"))格式:秒 分 时 星期 日 月 年

*:所有

1,12 :1和12

1-5: 1到5

星期:*表示所有 ,可以用“MON-FRI”,“MON,WED,FRI”或甚至“MON-WED,SAT”代替前一个

import com.lwf.quartz.job.MyFirstJob;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class QuartzConfig {@Beanpublic JobDetail jobDetail1(){return JobBuilder.newJob(MyFirstJob.class).storeDurably().build();}// 每5秒触发⼀次任务@Beanpublic Trigger trigger2(){return TriggerBuilder.newTrigger().withIdentity("trigger2", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ? *")).forJob(jobDetail1()).build();}
}

具体调度要执行的任务(类),在excute里写要定时执行的代码;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.text.SimpleDateFormat;
import java.util.Date;public class MyFirstJob implements Job {private Logger log = LoggerFactory.getLogger(MyFirstJob.class);@Overridepublic void execute(JobExecutionContext context) throwsJobExecutionException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");log.info(sdf.format(new Date()) + "-->" + "Hello Spring BootQuartz...");}
}

启动spring boot启动程序,任务就开始执行。

CronUtil

写要执行的任务:继承extends 或者实现Runable,在run里写任务:

我试过上面两种,官方文档没有说清楚,我后来试过,是个方法能用,方法名不是run也可以,只要配置文件中方法全限定路径对了就可以。当然任务方法要非静态的。如果任务方法为静态方法,程序不会报错,但是任务不能执行。

/*** @author lwf* @title: ShowTime* @projectName hutoolstest* @description: 打印农历* @date 2020/12/2719:07*/
public class ShowTime implements Runnable{public static  void  showTime(){ChineseDate date=new ChineseDate(new Date());System.out.println(date);}@Overridepublic void run() {showTime();}
}

配置文件 resources\config\cron.setting里指定要执行的任务:

下面的写法等同:com.lwf.quartz.job.ShowTime.run= */10 * * * * * *

# 类(任务方法所在类)全限定路径
[com.lwf.quartz.job]
#每10秒执行,支持Quarzy  要加CronUtil.setMatchSecond(true);   秒 分 时 星期  日 月 年
ShowTime.run= */10 * * * * * *

任务执行时间:QuartZ的时间写法;

@SpringBootApplication
public class QuartzApplication {public static void main(String[] args) {SpringApplication.run(QuartzApplication.class, args);//hutools时钟任务CronUtil.start();//默认使用 分 秒 时 日 月 年//要使用Quartz格式使用下面代码开启CronUtil.setMatchSecond(true);}}

hutools简单使用和与一些工具的比较相关推荐

  1. 拨测工具_您可以拨多少钱? 快速简单地介绍有用的工具。

    拨测工具 by Miguel Bustamante 通过Miguel Bustamante 您可以卷曲多少? 快速简单地介绍有用的工具. (How much can you cURL? A quick ...

  2. 如何玩转PDF?5款简单好用的PDF工具推荐

    在办公中会经常遇到PDF文件,也需要将PDF文件进行编辑和转换,但是对PDF直接编辑和转换是不行的,为了高效办公就需要借助工具来完成,很多人想问如何玩转PDF?今天就来给大家推荐5款简单好用的PDF工 ...

  3. 简单的网络图片加载工具类

    简单的网络图片加载工具类 根据图片url网址解生成图片,首先解析图片的流信息,然后通过bitmapfactory工具类生成bitmap图片,设置到图片控件上即可,详情看代码 import androi ...

  4. 利用Bing翻译API简单的实现一个翻译工具

    常见的翻译服务提供商有Google和微软,它们的在线翻译地址如下: Bing翻译: http://www.microsofttranslator.com/?FORM=R5FD Google翻译: ht ...

  5. 使用Blazor做个简单的时间戳在线转换工具

    时间戳转换 时间戳转换,关键点在于双向绑定@bind-Value,就简单贴源码吧 TimestampTool.razor @page "/timestamp" @using Bla ...

  6. 免费发布一个简单而有趣的计算工具

    Jef Raskin 在 The Humance Interface: New Directions for Designing Interactive Systems 一书中提到,好的用户界面应当把 ...

  7. git上传代码简单方法 简单git上传代码工具

    简单git上传代码工具 肯定有很多人和我一样,git上传时候搞不懂拉取,合并等一系列的代码冲突问题,往往可能覆盖掉自己今天写的代码,或者覆盖掉别人的代码. 下面给大家简单介绍一款操作比较简单的上传代码 ...

  8. 简单易用的OKR工具——源目标OKR

    有效**推行OKR**需要一些必备的前提,比如:平等包容的企业环境.高层的理解和支持.简单易用的OKR目标管理工具. 最近几年,OKR真的火了! 前有谷歌布道,后有无数大佬站台,2014年,OKR传入 ...

  9. XYWi-Fi v2.0 简单的笔记本无线热点分享工具【Win】

    [软件名称]XYWi-Fi [版本]v2.0 [适用系统]Windows 7/8/8.1/10 [功能特性]简单的笔记本无线热点分享工具 [下载地址]pan.baidu.com/s/1mgmOpJi ...

最新文章

  1. Python基础11-函数式编程与内置函数
  2. ASP.NET MVC 3拥抱动态类型,徐汇区网站设计
  3. Cocoapods警告 - CocoaPods没有设置项目的基本配置,因为您的项目已经有自定义配置集
  4. 正则 实现等长度的分割字符串
  5. 字符串换行截取_textwrap 文本自动换行与填充
  6. android开发之bitmap转数组的方法
  7. C#~异步编程续~.net4.5主推的awaitasync应用
  8. 如何维持手机电池寿命_延长手机电池寿命终极技巧教学,iPhone和安卓手机皆适合...
  9. Java千百问_06数据结构(014)_java数组如何存储在内存中
  10. 算法面试_怎么简单高效的理解递归?//TODO
  11. POJ 3168 Barn Expansion (几何+排序)
  12. python中文聊天_GitHub - 116pythonZS/chinese_chatbot_corpus: 中文公开聊天语料库
  13. 20191004每日一句
  14. 个人对于封装继承多态的理解
  15. 自己制做python3.6精简绿色版
  16. 密西根州立大学计算机qs分数,密歇根州立大学2021年QS世界大学排名第157
  17. Synergy问题收录
  18. 数据结构课程设计[2023-01-19]
  19. linux卸载nginx(更新)
  20. 手机app开发需要哪些技术?

热门文章

  1. HAP框架学习之——LOV使用
  2. 动态网站设计与开发总结
  3. Verycd网站中不能显示下载网址的解决办法
  4. 【焕新升级】百度大脑EasyMonitor视频监控开发平台2.0
  5. 第一章:Getting Started
  6. 三星笔记本-星曜系列上手体验:简约时尚、轻薄便携
  7. PyQt5中的窗口显示控制
  8. 芯片组的相关概念描述
  9. P2242公路维修问题题解
  10. 2021年最新微信JS-SDK的使用