首页 文章 精选 留言 我的

精选列表

搜索[入门],共9586篇文章
优秀的个人博客,低调大师

guava快速入门(二)

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 guava类似Apache Commons工具集 Collection 不可变集合 不可变对象有很多优点,包括: 当对象被不可信的库调用时,不可变形式是安全的; 不可变对象被多个线程调用时,不存在竞态条件问题 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节); 不可变对象因为有固定不变,可以作为常量来安全使用。 JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但: 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景; 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的; 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。 创建不可变集合方法: copyOf方法,如ImmutableSet.copyOf(set); of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2); Builder工具 import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; public class ImmutableDemo { public static void main(String[] args) { ImmutableSet<String> set = ImmutableSet.of("a", "b", "c", "d"); ImmutableSet<String> set1 = ImmutableSet.copyOf(set); ImmutableSet<String> set2 = ImmutableSet.<String> builder().addAll(set).add("e").build(); ImmutableList<String> list = set.asList(); System.out.println("set:"+set); System.out.println("set1:"+set1); System.out.println("set2:"+set2); //set.add("f");//java.lang.UnsupportedOperationException } } 返回: set:[a, b, c, d] set1:[a, b, c, d] set2:[a, b, c, d, e] 新型集合类 Multiset Multiset可统计一个词在文档中出现了多少次 import com.google.common.collect.LinkedHashMultiset; import com.google.common.collect.Multiset; public class MultiSetDemo { public static void main(String[] args) { Multiset<String> set = LinkedHashMultiset.create(); set.add("a"); set.add("a"); set.add("lucas"); set.add("lucas"); set.setCount("a", 5); // 添加或删除指定元素使其在集合中的数量是count System.out.println(set); System.out.println(set.count("a")); // 给定元素在Multiset中的计数 System.out.println(set.size()); // 所有元素计数的总和,包括重复元素 System.out.println(set.elementSet().size()); // 所有元素计数的总和,不包括重复元素 set.clear(); // 清空集合 System.out.println(set); } } 返回: [a x 5, lucas x 2] 5 7 2 [] Multimap Multimap可以很容易地把一个键映射到多个值。换句话说,Multimap是把键映射到任意多个值的一般方式。 import java.util.Collection; import java.util.Map; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; public class MultiMapDemo { public static void main(String[] args) { Multimap<String, Integer> map = HashMultimap.create(); // Multimap是把键映射到任意多个值的一般方式 map.put("a", 1); // key相同时不会覆盖原value map.put("a", 2); map.put("a", 3); map.put("b", 1); map.put("b", 2); System.out.println(map); // {a=[1, 2, 3]} System.out.println(map.get("a")); // 返回的是集合 System.out.println(map.size()); // 返回所有”键-单个值映射”的个数,而非不同键的个数 System.out.println(map.keySet().size()); // 返回不同key的个数 Map<String, Collection<Integer>> mapView = map.asMap(); System.out.println(mapView); } } 返回: {a=[1, 2, 3], b=[1, 2]} [1, 2, 3] 5 2 {a=[1, 2, 3], b=[1, 2]} BiMap BiMap import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; public class BitMapDemo { public static void main(String[] args) { BiMap<String, String> biMap = HashBiMap.create(); biMap.put("sina", "sina.com"); biMap.put("qq", "qq.com"); biMap.put("sina", "sina.cn"); // 会覆盖原来的value /* * 在BiMap中,如果你想把键映射到已经存在的值,会抛出IllegalArgumentException异常 * 如果对特定值,你想要强制替换它的键,请使用 BiMap.forcePut(key, value) */ // 抛出异常java.lang.IllegalArgumentException: value already present: qq.com //biMap.put("tecent", "qq.com"); biMap.forcePut("tecent", "qq.com"); // 强制替换key System.out.println(biMap); System.out.println(biMap.inverse()); // 翻转value-key System.out.println(biMap.inverse().get("sina.cn")); // 通过value找key System.out.println(biMap.inverse().inverse() == biMap); // true } } 返回: {sina=sina.cn, tecent=qq.com} {sina.cn=sina, qq.com=tecent} sina true Table Table它有两个支持所有类型的键:”行”和”列”。 import java.util.Set; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; public class TableDemo { public static void main(String[] args) { // 记录学生在某门课上的成绩 Table<String, String, Integer> table = HashBasedTable.create(); table.put("jack", "java", 100); table.put("jack", "c", 90); table.put("mike", "java", 93); table.put("mike", "c", 100); Set<Table.Cell<String, String, Integer>> cells = table.cellSet(); for (Table.Cell<String, String, Integer> cell : cells) { System.out.println(cell.getRowKey() + " " + cell.getColumnKey() + " " + cell.getValue()); } System.out.println("----------------------"); System.out.println(table.row("jack")); System.out.println(table); System.out.println(table.rowKeySet()); System.out.println(table.columnKeySet()); System.out.println(table.values()); } } 返回: mike java 93 mike c 100 jack java 100 jack c 90 ---------------------- {java=100, c=90} {mike={java=93, c=100}, jack={java=100, c=90}} [mike, jack] [java, c] [93, 100, 100, 90] Collections2 filter():只保留集合中满足特定要求的元素 import java.util.Collection; import java.util.List; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; public class FilterDemo { public static void main(String[] args) { List<String> list = Lists.newArrayList("moon", "dad", "refer", "son"); Collection<String> palindromeList = Collections2.filter(list, input -> { return new StringBuilder(input).reverse().toString().equals(input); // 找回文串 }); System.out.println(palindromeList);//palindromeList 回文,也叫做镜文,正写倒写一样,如mam } } 返回: [dad, refer] transform():类型转换 import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Set; import com.google.common.base.Function; import com.google.common.collect.Collections2; import com.google.common.collect.Sets; public class TransformDemo { public static void main(String[] args) { Set<Long> times = Sets.newHashSet(); times.add(91299990701L); times.add(9320001010L); times.add(9920170621L); Collection<String> timeStrCol = Collections2.transform(times, new Function<Long, String>() { @Override public String apply( Long input) { return new SimpleDateFormat("yyyy-MM-dd").format(input); } }); System.out.println(timeStrCol); } } 返回: [1970-04-19, 1970-04-26, 1972-11-23] 多个Function组合 import java.util.Collection; import java.util.List; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; public class TransformDemo2 { public static void main(String[] args) { List<String> list = Lists.newArrayList("abcde", "good", "happiness"); // 确保容器中的字符串长度不超过5 Function<String, String> f1 = new Function<String, String>() { @Override public String apply( String input) { return input.length() > 5 ? input.substring(0, 5) : input; } }; // 转成大写 Function<String, String> f2 = new Function<String, String>() { @Override public String apply( String input) { return input.toUpperCase(); } }; Function<String, String> function = Functions.compose(f1, f2); Collection<String> results = Collections2.transform(list, function); System.out.println(results); } } 返回: [ABCDE, GOOD, HAPPI] 集合操作:交集、差集、并集 import java.util.Set; import com.google.common.collect.Sets; public class CollectionsDemo { public static void main(String[] args) { Set<Integer> set1 = Sets.newHashSet(1, 2, 3, 4, 5); Set<Integer> set2 = Sets.newHashSet(3, 4, 5, 6); Sets.SetView<Integer> inter = Sets.intersection(set1, set2); // 交集 System.out.println(inter); Sets.SetView<Integer> diff = Sets.difference(set1, set2); // 差集,在A中不在B中 System.out.println(diff); Sets.SetView<Integer> union = Sets.union(set1, set2); // 并集 System.out.println(union); } } 返回: [3, 4, 5] [1, 2] [1, 2, 3, 4, 5, 6]

优秀的个人博客,低调大师

guava快速入门(三)

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。 guava类似Apache Commons工具集 Cache 缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存。 Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。 Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。 通常来说,Guava Cache适用于: 你愿意消耗一些内存空间来提升速度。 你预料到某些键会被查询一次以上。 缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。 如果这不符合你的需求,请尝试Memcached这类工具) Guava Cache有两种创建方式: cacheLoader callable callback LoadingCache是附带CacheLoader构建而成的缓存实现 import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; public class LoadingCacheDemo { public static void main(String[] args) { LoadingCache<String, String> cache = CacheBuilder.newBuilder().maximumSize(100) // 最大缓存数目 .expireAfterAccess(2, TimeUnit.SECONDS) // 缓存1秒后过期 .build(new CacheLoader<String, String>() { @Override public String load(String key) throws Exception { return key; } }); cache.put("j", "java"); cache.put("c", "cpp"); cache.put("s", "scala"); cache.put("g", "go"); try { System.out.println(cache.get("j")); TimeUnit.SECONDS.sleep(1); System.out.println(cache.get("s")); // 1秒后 输出scala TimeUnit.SECONDS.sleep(2); System.out.println(cache.get("s")); // 2秒后 输出s } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } } } 返回: java scala s 回调: import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; public class CallbackDemo { public static void main(String[] args) { Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(100) .expireAfterAccess(1, TimeUnit.SECONDS) .build(); try { String result = cache.get("java", () -> "hello java"); System.out.println(result); } catch (ExecutionException e) { e.printStackTrace(); } } } refresh机制:- LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。- CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value- CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache 并发 ListenableFuture 传统JDK中的Future通过异步的方式计算返回结果:在多线程运算中可能或者可能在没有结束返回结果,Future是运行中的多线程的一个引用句柄,确保在服务执行返回一个Result。 ListenableFuture可以允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用, 或者在运算(多线程执行)完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent中的Future是不支持的。 import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; public class ListenableFutureDemo { public static void main(String[] args) { // 将ExecutorService装饰成ListeningExecutorService ListeningExecutorService service = MoreExecutors. listeningDecorator(Executors.newCachedThreadPool()); // 通过异步的方式计算返回结果 ListenableFuture<String> future = service.submit(() -> { System.out.println("call execute.."); return "task success!"; }); // 有两种方法可以执行此Future并执行Future完成之后的回调函数 future.addListener(() -> { // 该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行 try { System.out.println("result: " + future.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } }, service); Futures.addCallback(future, new FutureCallback<String>() { @Override public void onSuccess( String result) { System.out.println("callback result: " + result); } @Override public void onFailure(Throwable t) { System.out.println(t.getMessage()); } }, service); } } 返回: call execute.. result: task success! callback result: task success! IO import java.io.File; import java.io.IOException; import java.util.List; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.io.Files; public class FileDemo { public static void main(String[] args) { File file = new File(System.getProperty("user.dir")); System.out.println(file.getName()); System.out.println(file.getPath()); } // 写文件 private void writeFile(String content, File file) throws IOException { if (!file.exists()) { file.createNewFile(); } Files.write(content.getBytes(Charsets.UTF_8), file); } // 读文件 private List<String> readFile(File file) throws IOException { if (!file.exists()) { return ImmutableList.of(); // 避免返回null } return Files.readLines(file, Charsets.UTF_8); } // 文件复制 private void copyFile(File from, File to) throws IOException { if (!from.exists()) { return; } if (!to.exists()) { to.createNewFile(); } Files.copy(from, to); } } 返回: collection-others D:\GITHUB\java\code\test01\collection-others 参考:Google Guava官方教程(中文版)guava-importnew

优秀的个人博客,低调大师

大话RabbitMQ 基础入门

----------写在前面---------- 近些年微服务越来越火,让我也忍不住想去一窥微服务究竟,讲到微服务,就离不开分布式,而分布式,也离不开消息队列,在消息队列中,RabbitMQ可以说是比较具有代表性的一款。 这里是一篇介绍消息队列以及各种消息队列产品对比的文章,讲得很好,有兴趣的可以看一看。 https://cloud.tencent.com/developer/article/1006035 在讲RabbitMQ之前,首先需要在电脑上安装和配置RabbitMQ,网络上已经有很多这类文章,如果懒得去搜索,可以看看这篇介绍如何安装配置RabbitMQ的文章。 https://blog.csdn.net/weixin_39735923/article/details/79288578 其中,在安装RabbitMQ的过程中,遇到了一个坑,在启用RabbltMQ的管理界面执行 rabbitmq-plugins enable rabbitmq_management 命令时,出现了以下这样的报错 可以在该指令前加上 .\ 即 .\rabbitmq-plugins enable rabbitmq_management 祝安装顺利 !! -------正文------ 基本概念 下面是在.Net中使用RabbitMQ要明白的一些名词概念。 综上所诉,他们之间的关系可以用我下面的 丑图 表示。 在图中,没有吧Routing key画出。Producer每一次发送消息,除了发出消息本身,还会随着消息带上一个routingKey,而且每一次将Exchange和Queue绑定,大体需要三个参数, string queueName, string exchangeName, string routingKey 其中也有一个routingKey,但此RoutingKey非彼Routingkey。 大白话 对这个过程,我们可以理解为国家给灾区发送救灾物资,国家给当地政府划拨物资的时候,会规定,谁才能拿到这批物资,如(房子倒了的.家里有人受伤了的.家庭经济困难的)。 而当地政府在分配这批物资之前,为了方便物资的分配,会给每个家庭贴上一个标签,如 家庭A 经济困难 家庭B 房子倒了.经济困难 家庭C 家庭富有.房子倒了 家庭D 房子倒了的.家里有人受伤了的.家庭经济困难的 所以,发送消息时候的routingKey就是国家规定的那批物质分配规则。 而Exchange和Queue绑定时的RoutingKey可以理解为当地政府给每个家庭贴上的一个标签。 Exchange(交换机)转发消息的规则也有很多种:direct, topic, headers(不常用) 和 fanout,我们称之为交换类型。 我们可以把Exchange理解为分配这批物质的政府,现在国家规定了宏观的分配方向(发送消息时的routingKey),每个家庭也有了家庭情况的标签(绑定Exchange时的routingKey),但是这个物资具体怎么分,还是当地政府说了算。 Direct 严格按照国家规定来,只有房子倒了的,家里有人受伤了的而且家庭经济困难的才能分到救灾物资。 家庭D能分到 Fanout 只要是灾区的居民都能分到, 不管家庭情况如何。 家庭A\B\C\D都能分到 Topic 主题匹配: 只要家庭情况在国家规定分配规则内的,都能分到物资,但是家庭C分不到,因为他家太有钱了,这个条件不在国家的分配规则里。家庭A\B\D能分到 所以,我们在声明一个Exchange(交换机)的同时,还要指定该交换机的类型,即(当地政府怎么来分救灾物资) 其实,用这个例子,我是想说,生产者和消费者之间,就像国家与难民之间一样,国家只知道,我要帮助难民,但是难民有谁,物资能不能分到难民手里,还得当地政府说了算,你就说我这个例子恰不恰当吧!哈哈 好了,懂了概念,我们再来结合具体例子看看。 Fanout Producer.cs的代码 using System; using System.Text; using RabbitMQ.Client; namespace _2_Publish { class Program { static void Main(string[] args) { //创建连接工厂 var factory = new ConnectionFactory() { HostName = "localhost" }; //创建连接 using (var connection = factory.CreateConnection()) { //创建会话 using (var chancel = connection.CreateModel()) { //生命交换机 chancel.ExchangeDeclare(exchange: "FanoutDemo", type: ExchangeType.Fanout); string readMsg = "helloWorld"; while (readMsg.ToLower() != "exit") { var body = Encoding.UTF8.GetBytes(readMsg); //给交换机发送消息 chancel.BasicPublish(exchange: "FanoutDemo", routingKey: "", body: body); Console.WriteLine($"成功发送消息{readMsg}"); Console.WriteLine("请输入要发送的内容!"); readMsg = Console.ReadLine(); } } } } } } Customer.cs代码 using System; using System.Text; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace _2_Receiver { class Program { static void Main(string[] args) { //创建连接工厂 var factory = new ConnectionFactory() { HostName = "localhost" }; //创建连接 using (var connection = factory.CreateConnection()) { //创建会话 using (var channel = connection.CreateModel()) { //声明一个Fanout类型的交换机 channel.ExchangeDeclare(exchange: "FanoutDemo", type: ExchangeType.Fanout); //声明一个消息队列并获取它的名字 var queueName = channel.QueueDeclare().QueueName; //把消息队列和交换机绑定 channel.QueueBind(exchange: "FanoutDemo", queue: queueName, routingKey: ""); //创建消费者 var consume = new EventingBasicConsumer(channel); //把消费者和队列绑定 channel.BasicConsume(queue: queueName, autoAck: true,consumer: consume); consume.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); Console.WriteLine($"收到消息{message}"); }; Console.ReadLine(); } } } } } 在上面的代码中,无论是在生产者的发送消息里 //给交换机发送消息 chancel.BasicPublish(exchange: "FanoutDemo", routingKey: "", body: body); 还是消费者所在的Queue的绑定里 //把消息队列和交换机绑定 channel.QueueBind(exchange: "FanoutDemo", queue: queueName, routingKey: ""); 我们都没有制定routingKey,因为没个人都能获取消息,所以此处,声明routingKey就没有意义了。 我们看看运行效果。 运行了三个消费者,当生产者发出消息时,三个消费者都收到了相同的消息。可以理解为广播模式。(Customer单词拼写错了,图片修改不方便,就不改了,大家将就一下) Direct Direct时严格匹配的,只有队列绑定的RoutingKey与生产者发送消息时指定的RoutingKey完全相同,才能接收成功。 Producer.cs using System; using System.Text; using RabbitMQ.Client; namespace _2_Publish { class Program { static void Main(string[] args) { //创建连接工厂 var factory = new ConnectionFactory() { HostName = "localhost" }; //创建连接 using (var connection = factory.CreateConnection()) { //创建会话 using (var chancel = connection.CreateModel()) { //生命交换机 chancel.ExchangeDeclare(exchange: "DirectDemo", type: ExchangeType.Direct); string readMsg = "helloWorld"; while (readMsg.ToLower() != "exit") { var body = Encoding.UTF8.GetBytes(readMsg); //给交换机发送消息 chancel.BasicPublish(exchange: "DirectDemo", routingKey: "Direct.Key", body: body); Console.WriteLine($"成功发送消息{readMsg}"); Console.WriteLine("请输入要发送的内容!"); readMsg = Console.ReadLine(); } } } } } } 我把Exchange的类型更改为Direct类型,并且发送消息的routingKey设置为Direct.Key。 然后我们来定义消费者 Customer.CS using System; using System.Text; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace _2_Receiver { class Program { static void Main(string[] args) { //创建连接工厂 var factory = new ConnectionFactory() { HostName = "localhost" }; //创建连接 using (var connection = factory.CreateConnection()) { //创建会话 using (var channel = connection.CreateModel()) { //声明一个Fanout类型的交换机 channel.ExchangeDeclare(exchange: "DirectDemo", type: ExchangeType.Direct); //声明一个消息队列并获取它的名字 var queueName = channel.QueueDeclare().QueueName; Console.WriteLine("请输入RoutingKey!"); var routingKey = Console.ReadLine(); //把消息队列和交换机绑定 channel.QueueBind(exchange: "DirectDemo", queue: queueName, routingKey: routingKey); //创建消费者 var consume = new EventingBasicConsumer(channel); //把消费者和队列绑定 channel.BasicConsume(queue: queueName, autoAck: true,consumer: consume); Console.WriteLine("开始监听消息"); consume.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); Console.WriteLine($"收到消息{message}"); }; Console.ReadLine(); } } } } } 消费者的RoutingKey再控制台输入, 运行效果如下: 可以看到,只有RoutingKey为Direct.Key的消费者才收到了生产者发出的消息。 Topic RabbitMQ 中的 RouteKey 支持绑定键表达式写法,有两种主要的绑定键: *(星号)可以代替一个单词. # (井号) 可以代替0个或多个单词. 比如在下面这个图中(P为发送者,X为RabbitMQ中的Exchange,C为消费者,Q为队列) 在这个示例中,我们将发送一条关于动物描述的消息,也就是说 Name(routeKey) 字段中的内容包含 3 个单词。第一个单词是描述速度的(celerity),第二个单词是描述颜色的(colour),第三个是描述哪种动物的(species),它们组合起来类似:“..”。 然后在使用CapSubscribe绑定的时候,Q1绑定为CapSubscribe["*.orange.*"], Q2 绑定为CapSubscribe["*.*.rabbit"]和[CapSubscribe["lazy.#]。 那么,当发送一个名为 "quick.orange.rabbit" 消息的时候,这两个队列将会同时收到该消息。同样名为lazy.orange.elephant的消息也会被同时收到。另外,名为 "quick.orange.fox" 的消息将仅会被发送到Q1队列,名为 "lazy.brown.fox" 的消息仅会被发送到Q2。"lazy.pink.rabbit" 仅会被发送到Q2一次,即使它被绑定了2次。"quick.brown.fox" 没有匹配到任何绑定的队列,所以它将会被丢弃。 另外一种情况,如果你违反约定,比如使用 4个单词进行组合,例如 "quick.orange.male.rabbit",那么它将匹配不到任何的队列,消息将会被丢弃。 但是,假如你的消息名为 "lazy.orange.male.rabbit",那么他们将会被发送到Q2,因为 #(井号)可以匹配 0 或者多个单词。 我们结合代码来看一看。 Producer.cs using System; using System.Text; using RabbitMQ.Client; namespace _2_Publish { class Program { static void Main(string[] args) { //创建连接工厂 var factory = new ConnectionFactory() { HostName = "localhost" }; //创建连接 using (var connection = factory.CreateConnection()) { //创建会话 using (var chancel = connection.CreateModel()) { //生命交换机 chancel.ExchangeDeclare(exchange: "TopicDemo", type: ExchangeType.Topic); string readMsg = "helloWorld"; while (readMsg.ToLower() != "exit") { var body = Encoding.UTF8.GetBytes(readMsg); //给交换机发送消息 chancel.BasicPublish(exchange: "TopicDemo", routingKey: "Topic.Demo.Key", body: body); Console.WriteLine($"成功发送消息{readMsg}"); Console.WriteLine("请输入要发送的内容!"); readMsg = Console.ReadLine(); } } } } } } 我给发送消息的routingKey指定为Topic.Demo.Key 再来看看消费者 Cuustomer.cs using System; using System.Text; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace _2_Receiver { class Program { static void Main(string[] args) { //创建连接工厂 var factory = new ConnectionFactory() { HostName = "localhost" }; //创建连接 using (var connection = factory.CreateConnection()) { //创建会话 using (var channel = connection.CreateModel()) { //声明一个Fanout类型的交换机 channel.ExchangeDeclare(exchange: "TopicDemo", type: ExchangeType.Topic); //声明一个消息队列并获取它的名字 var queueName = channel.QueueDeclare().QueueName; Console.WriteLine("请输入RoutingKey!"); var routingKey = Console.ReadLine(); //把消息队列和交换机绑定 channel.QueueBind(exchange: "TopicDemo", queue: queueName, routingKey: routingKey); //创建消费者 var consume = new EventingBasicConsumer(channel); //把消费者和队列绑定 channel.BasicConsume(queue: queueName, autoAck: true,consumer: consume); Console.WriteLine("开始监听消息"); consume.Received += (model, ea) => { var body = ea.Body; var message = Encoding.UTF8.GetString(body); Console.WriteLine($"收到消息{message}"); }; Console.ReadLine(); } } } } } 其RoutingKey也是在外部输入。 我们看看运行效果 因为Producer发布消息的RoutingKey是Topic.Demo.Key 又因为#可以代表0个或者多个单词 ,*能代表一个单词 所以*.*.Key Topic.#与Topic.Demo.Key匹配,而其他两个*.Key和test.1.2当然是不匹配的,所以没有收到消息。 总结 对于上面的例子,我们可以总结出,编写一个生产者的过程如下: 创建连接工厂-》创建连接-》创建会话(Chanel)-》创建交换机(Exchange)-》发送消息 编写一个生产者的过程如下: 创建连接工厂-》创建连接-》创建会话(Chanel)-》创建交换机(Exchange)-》创建队列-》绑定队列和交换机-》创建消费者-》把消费者和队列绑定-》监听消息 掌握这个大的方向,不管交换机怎么分配,代码应该都会写了。 为什么在生产者中和消费者中都要创建交换机呢? 因为我们不确定是生产者先执行还是消费者先执行,所以提前创建一下,避免连接时发现没有创建交换机,出现错误,如果交换机已经创建了,那么默认不会再次创建的。 另外,交换机创建后,同一名称的交换机使用完不会自动删除,但是第二次如果创建的名称和上次一样,但是交换机类型不一样了,那么便会出现报错。 这里总结的是一些RabbitMQ的基础知识,后面还会继续写一些更深入的使用技巧,如果不想错过精彩信息,点击关注一下吧(๑¯◡¯๑)!

优秀的个人博客,低调大师

MaxCompute Studio 使用入门

MaxCompute Studio 是MaxCompute 平台提供的安装在开发者客户端的大数据集成开发环境工具,是一套基于流行的集成开发平台IntelliJ IDEA的开发插件,可以帮助您方便地进行数据开发。下面我们一起来看一看Studio的简单用法。 用户登录 Studio提供用户登录功能。常规登录入口在Intellij toolbar中右上角的Sign In。登录完成后可直接使用答疑机器人、添加D2项目、同步D2等功能。 答疑机器人 点击右侧“FAQ Robot”按钮,进入答疑机器人页面,如下图所示。答疑机器人支持自助答疑和人工答疑两种方式,支持图片和文件上传,如果对自助答疑的结果不满意,可以在聊天框发送“人工”呼叫ODPS值班同学。或者直接发送图片或文件唤起人工服务。 资源管理 Studio 的一大核心功能就是浏览 MaxCompute 项目空间(Project)的资源,包括Table、UDF、Resource等。为了能够在 Studio 中访问它们,以及其它很多功能,我们首先需要在新建项目连接。在Project Explorer中点击"+"添加连接,目前Studio支持同步D2项目和通过accessId/Key添加项目连接。 建立项目空间连接后,可以浏览Table&View、Function、Resource等项目资源,双击对应的元素可以在Intellij中查看资源详情。 Table 双击打开某个table,如下图所示。有两个tab页面,“表信息”页面如下如所示,该页面展示table的基本信息、schema信息,提供数据预览功能。 选择对应的分区,设置预览行数,点击“预览”按钮可以进行数据预览。同时,右键点击表头支持数据导入/导出功能。 “分区信息”页面如下所示,显示分区的详细信息,提供分区的查询、刷新功能。同时提供导出分区信息、分区数据导入导出等功能。 在project explorer中右键点击某张表,可以看到建表、改表、数据操作等一系列比较实用的功能。 在Studio中不光可以通过写SQL进行DDL相关的操作,也可以通过可视化界面创建和修改table:Project Explorer中右键点击项目名称或者“Table & Views”选择“Create a new table”进行建表操作。 右键点击某个table选择“open table editor”可以对表信息进行相应修改,如下图所示,Studio可以将用户操作转化为对应的SQL语句。 Functions Functions分为BuiltIn Function和UserDefied Function, 双击对应的function可以展开详情: 可以通过如下途径添加Function: Resources 双击对应的resource,可以在editor中打开文件。对于UDF文件数大于5的情况,只打开前5个class。 可以通过如下途径添加resource: SQL编辑器与作业提交 如何帮助用户高效愉快的编写SQL是MaxCompute studio的核心使命,下面就让我们来一起看一下SQL编辑器的使用。首先需要创建一个MaxCompute Script Module,如下图所示: Module创建完成后,新建SQL脚本文件如下图所示。 最后双击SQL文件就可以进行我们的脚本开发了,这里可以自己设置模式(单句模式|脚本模式)、系统类型(旧有系统类型|MaxCompute系统|Hive系统)、编译器类型(默认编译器|实验性编译器)等。右上角需要选择对应的project。 下图所示三个按钮分别表示将SQL同步到D2,在Cosonle中打开ODPS CMD,打开SQL History。 SQL编辑完成后,点击下方的graph tab按钮,可以显示该SQL的执行计划,双击Task节点会展开对应的Operator级别的信息。 点击绿色的提交按钮,Studio会先编译脚本,编译通过后提交Server后显示运行信息并打开Job分析页面,如下图所示: 作业详情 上面我们说到了如何编辑SQL和提交作业,接下来一起看看如何查看作业详情。作业详情页可以通过多条路径打开,比如上面说到的提交作业,会自动打开作业详情页。其次通过Job Explorer也可以打开作业详情页,再有就是如果已经知道logview,可以通过logview打开作业详情页,如下图所示: 作业详情页面分为两部分,左侧是作业的一些基本信息,右侧包含多个tab页,包含graph信息、时序图、详情、脚本、摘要、结果、分析等内容。下面对graph图、时序图、详情页和作业分析进行进一步介绍。 graph页面 graph页面展示作业的Job|Task|Operator三层结构。点击左上角的导航可切换不同level的视图,双击Job节点进入Task视图,双击Task节点进入Operator视图。 graph页面用户可以通过鼠标滚轮或者左侧缩放按钮对图像进行缩放,同时提供鹰眼和拖拽等功能。点击task节点显示task级别信息,点击task之间连线显示schema信息。 在task level视图中右键点击节点,选择"expand all"展开所有的operator。 同时,单击table节点会显示table的基本信息和分区信息,双击table节点会跳转到对应的table详情页。 时序图 时序图画的是所有Fuxi Instance的甘特图,通过时序图可以对作业的运行时间等进行详细的分析,左侧的Filter可以对instances进行过滤,鼠标悬停到对应的instance上会显示对应的信息,双击则会跳转到"详情”tab页并选中对应的instance,对用户分析十分方便。同时时序图支持缩放功能。 详情页 详情页展示的是Task级别和Instance级别的详细信息。 作业分析页面 作业分析页面提供作业分析的结论,比如长尾节点、数据倾斜等。并提供散点图、长尾图和数据倾斜图供用户分析。 作业队列 Maxcompute 作业从提交到开始执行之前,需要经历很多状态,如:执行编译、优化、排队等待资源等。作业队列提供了查看当前详细状态的功能。对于正在排队等待调度的作业,可也从队列窗口中查看排队位置和前序作业等信息。点击"Job Explorer"打开作业队列页面,该页面提供了项目名称、状态、日期等Filter,选择对应的条件后会得到对应的作业队列,双击某一个作业会打开对应的作业详情页面。

优秀的个人博客,低调大师

Python入门篇

1.1 Python介绍 1.1.1 Python简介 Python,是一种广泛使用的高级编程语言,属于通用型编程语言,由吉多·范罗苏姆(中文名字:龟叔)创造,第一版发布于 1991 年。可以视之为一种改良 (加入一些其他编程语言的优点,如面向对象) 的 LISP。 作为一种解释型语言,Python 的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而非使用大括号或者关键词)。 数据来源:https://www.tiobe.com/tiobe-index/ 由上图可见,Python整体呈上升趋势,反映出Python应用越来越广泛并且也逐渐得到业内的认可。相比于 C++ 或 Java,Python 让开发者能够用更少的代码表达想法。不管是小型还是大型程序,该语言都试图让程序的结构清晰明了。 1.1.2 Python设计哲学与定位 Python的设计哲学是“优雅”、“明确”、“简单”。 Python开发者的哲学是“用一种方法,最好是只有一种方法来做一件事”,也因此它和拥有明显个人风格的其他语言很不一样。在设计Python语言时,如果面临多种选择,Python开发者一般会拒绝花俏的语法,而选择明确没有或者很少有歧义的语法。 这些准则被称为“Python格言”。在Python解释器内运行import this可以获得完整的列表。 >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! 1.1.3 Python应用范围 Web程序: Python经常被用于Web开发。比如,通过mod_wsgi模块,Apache可以运行用Python编写的Web程序。使用Python语言编写的Gunicorn作为Web服务器,也能够运行Python语言编写的Web程序。 Python定义了WSGI标准应用接口来协调Http服务器与基于Python的Web程序之间的沟通。一些Web框架,如Django、Pyramid、TurboGears、Tornado、web2py、Zope、Flask等,可以让程序员轻松地开发和管理复杂的Web程序。 GUI开发: Python本身包含的Tkinter库能够支持简单的GUI开发。但是越来越多的Python程序员选择wxPython或者PyQt等GUI包来开发跨平台的桌面软件。使用它们开发的桌面软件运行速度快,与用户的桌面环境相契合。通过PyInstaller还能将程序发布为独立的安装程序包。 其他: YouTube、Google、Yahoo!、NASA都在内部大量地使用Python。OLPC的作业系统Sugar项目的大多数软件都是使用Python编写。 1.1.4 Python的种类 1、CPython Python的官方版本,使用C语言实现,使用最为广泛,CPython实现会将源文件(py文件)转换成字节码文件(pyc文件),然后运行在Python虚拟机上。 1、 Jython Python的Java实现,Jython会将Python代码动态编译成Java字节码,然后在JVM上运行。 3、IronPython Python的C#实现,IronPython将Python代码编译成C#字节码,然后在CLR上运行(与Jypthon类似)。 4、PyPy(特殊) Python实现的Python,将Python的字节码字节再编译成机器码。 5、RubyPython,Brython .... 注意:本文中都的为Python 3.6.2版本:https://www.python.org/downloads/release/python-362/ 关于Python环境部署可以参考:http://www.runoob.com/python/python-install.html 1.2 Python的语法 Python的设计目标之一是让代码具备高度的可阅读性。它设计时尽量使用其它语言经常使用的标点符号和英文单字,让代码看起来整洁美观。因为Python是动态语言,它不像其他的静态语言如C、Pascal那样需要书写声明语句。 1.2.1 缩进语法 Python开发者有意让违反了缩进规则的程序不能通过解释,以此来强迫程序员养成良好的编程习惯,也方便所有人查找和阅读。例如: if age < 21: print("你不能买酒。") print("不过你能买口香糖。") print("这句话处于if语句的外面。") 如果想要类似于执行shell脚本一样执行python脚本,例: ./clsn.py ,那么就需要在 clsn.py文件的头部指定解释器,如下: #!/usr/bin/env python # -*- coding: utf-8 -*- if age < 21: print("你不能买酒。") print("不过你能买口香糖。") print("这句话处于if语句的外面。") 注:上述例子为Python 3.0以上版本的代码。 1.2.2 变量说明 变量定义的规则: 1、变量名只能是 字母、数字或下划线的任意组合 2、变量名的第一个字符不能是数字 3、以下关键字不能声明为变量名 ['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield'] 4、变量的定义要具有可描述性。 1.2.3 语句和控制流 语句类型 说明 if语句 当条件成立时运行语句块。经常与else, elif(相当于else if)配合使用。 for语句 遍列列表、字符串、字典、集合等迭代器,依次处理迭代器中的每个元素。 while语句 当条件为真时,循环运行语句块。 try语句 与except, finally, else配合使用处理在程序运行中出现的异常情况。 class语句 用于定义类型。 def语句 用于定义函数和类型的方法。 pass语句 表示此行为空,不运行任何操作。 assert语句 用于程序调适阶段时测试运行条件是否满足。 with语句 Python2.6以后定义的语法,在一个场景中运行语句块。比如,运行语句块前加锁,然后在语句块运行结束后释放锁。 yield语句 在迭代器函数内使用,用于返回一个元素。自从Python 2.5版本以后。这个语句变成一个运算符。 raise语句 抛出一个异常。 import语句 导入一个模块或包。常用写法:from module import name, import module as name, from module import name as anothername 1.2.4 程序交互 input进行交互 #!/usr/bin/env python # -*- coding: utf-8 -*- # 将用户输入的内容赋值给 name 变量 name = input("请输入用户名:") # 打印输入的内容 print(name) 可以让用户输入多个信息,如下 #!/usr/bin/env python # -*- coding: utf-8 -*- name = input("What is your name?") age = input("How old are you?") hometown = input("Where is your hometown?") print("Hello ",name , "your are ", age , "years old, you came from",hometown) 1.2.5 数据类型与动态类型 Python内置多种数据类型。下面这个列表简要地描述了Python内置数据类型(适用于Python 3.x): 类型 描述 例子 str 一个由字符组成的不可更改的有序列。在Python 3.x里,字符串由Unicode字符组成。 'Wikipedia' "Wikipedia" """Spanning multiple lines""" bytes 一个由字节组成的不可更改的有序列。 b'Some ASCII' b"Some ASCII" list 可以包含多种类型的可改变的有序列 [4.0, 'string', True] tuple 可以包含多种类型的不可改变的有序列 (4.0, 'string', True) set, frozenset 与数学中集合的概念类似。无序的、每个元素唯一。 {4.0, 'string', True} frozenset([4.0, 'string', True]) dict或map 一个可改变的由键值对组成的无序列。 {'key1': 1.0, 3: False} int 精度不限的整数 42 float 浮点数。精度与系统相关。 3.1415927 complex 复数 3+2.7j bool 逻辑值。只有两个值:真、假 True False 除了各种数据类型,Python语言还用类型来表示函数、模块、类型本身、对象的方法、编译后的Python代码、运行时信息等等。因此,Python具备很强的动态性。 1.2.6 运算符 计算机可以进行的运算有很多种,可不只加减乘除这么简单,运算按种类可分为算数运算、比较运算、逻辑运算、赋值运算、成员运算、身份运算、位运算,今天我们暂只学习算数运算、比较运算、逻辑运算、赋值运算 算数运算 以下假设变量:a=10,b=20 比较运算 以下假设变量:a=10,b=20 赋值运算 以下假设变量:a=10,b=20 逻辑运算 关于逻辑运算 在没有()的情况下not 优先级高于 and,and优先级高于or,即优先级关系为( )>not>and>or,同一优先级从左往右计算。 in,not in : 判断子元素是否在原字符串(字典,列表,集合)中: 例如: #print('喜欢' in 'dkfljadklf喜欢hfjdkas') #print('a' in 'bcvd') #print('y' not in 'ofkjdslaf') 常见的占位符有: 1.3 流程控制语句 1.3.1 流程控制之--if 假如把写程序比做走路,那我们到现在为止,一直走的都是直路,还没遇到过分叉口,想象现实中,你遇到了分叉口,然后你决定往哪拐必然是有所动机的。你要判断那条岔路是你真正要走的路,很简单,只需要在程序里预设一些条件判断语句,满足哪个条件,就走哪条岔路。这个过程就叫流程控制。 单分支 if 条件: 满足条件后要执行的代码 双分支 """ if 条件: 满足条件执行代码 else: if条件不满足就走这段 """ MemInfo = 48 if MemInfo > 95 : print("内存即将用光") else: print("没事,放心用!") 多分支 if 条件: 满足条件执行代码 elif 条件: 上面的条件不满足就走这个 elif 条件: 上面的条件不满足就走这个 elif 条件: 上面的条件不满足就走这个 else: 上面所有的条件不满足就走这段 示例:猜猜我的年龄 age_of_clsn = 24 guess = int(input(">>:")) if guess > age_of_clsn : print("猜的太大了,往小里试试...") elif guess < age_of_clsn : print("猜的太小了,往大里试试...") else: print("恭喜你,猜对了...") 1.3.2 流程控制之--while循环 基本while循环 while 条件: # 循环体 # 如果条件为真,那么循环体则执行 # 如果条件为假,那么循环体不执行 循环中止语句 如果在循环的过程中,因为某些原因,你不想继续循环了,怎么把它中止掉呢?这就用到break 或 continue 语句 break用于完全结束一个循环,跳出循环体执行循环后面的语句 continue和break有点类似,区别在于continue只是终止本次循环,接着还执行后面的循环,break则完全终止循环。 示例: 之前猜年龄的代码运行一次使用一次,但稍加修改就能一自运行。 age_of_clsn = 24 while True: guess = int(input(">>:")) if guess > age_of_clsn: print("猜的太大了,往小里试试...") elif guess < age_of_clsn: print("猜的太小了,往大里试试...") else: print("恭喜你,猜对了...") break 1.3.3 格式化输出 现有一练习需求,问用户的姓名、年龄、工作、爱好 ,然后打印成以下格式 ------------ info of Alex Li ----------- Name : CLSN Age : 24 job : Linux Ops Hobbie: girl ------------- end ----------------- 这样的格式如何输出呢? name = input("Name:") age = input("Age:") job = input("Job:") hobbie = input("Hobbie:") info = ''' ------------ info of %s ----------- #这里的每个%s就是一个占位符,本行的代表 后面拓号里的 name Name : %s #代表 name Age : %s #代表 age job : %s #代表 job Hobbie: %s #代表 hobbie ------------- end ----------------- ''' %(name,name,age,job,hobbie) # 这行的 % 号就是 把前面的字符串 与拓号 后面的 变量 关联起来 print(info) 在格式化输出里面,怎么表示%? msg = "我是%s,年龄%d,目前工作进度为80%%"%('clsn',24) print(msg) 使用%% 将 % 转义. 1.4 编码说明 字符 ASCII Unicode utf-8 GBK 英文 1个字节 2-4个字节 1个字节 1个字节 中文 x 2-4个字节 3个字节 2个字节 其他 x 2-4个字节 2个字节 x 注: 1个字节 = 8 位bit 1.5 参考文献 [1]https://zh.wikipedia.org/wiki/Python [2]http://www.cnblogs.com/jin-xin/articles/7459977.html [3]http://www.cnblogs.com/wang-yc/articles/6419907.html [4]http://www.runoob.com/python/python-install.html [5]https://www.cnblogs.com/iDouble/p/8467738.html 我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。 作者: 惨绿少年 出处: https://www.nmtui.com 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

优秀的个人博客,低调大师

[jvm]jvm快速入门

本篇以jdk1.7为例 jvm内存结构 堆内存 方法区 jvm栈 程序计数器 本地方法栈如图: 使用processon作图 所以,这里可以看到jvm内存三大主要结构 方法区 堆区 栈区 常用jvm控制参数 -Xms 设置堆的最小空间大小。 -Xmx 设置堆的最大空间大小。 -XX:NewSize 设置新生代最小空间大小。 -XX:MaxNewSize 设置新生代最大空间大小。 -XX:PermSize 设置永久代最小空间大小。 -XX:MaxPermSize 设置永久代最大空间大小。 -Xss 设置每个线程的堆栈大小。 一张图来了解如何通过参数来控制各区域的内存大小 简单介绍每个区域的作用 Java堆(Heap)对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。 根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。 如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。 方法区(Method Area)方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。 对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已。 Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。 根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。 程序计数器(Program Counter Register) 程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Natvie方法,这个计数器值则为空(Undefined)。 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 JVM栈(JVM Stacks)与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。 其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。 在Java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。 本地方法栈(Native Method Stacks) 本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机(譬如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。 参考自《深入理解Java虚拟机:JVM高级特性与最佳实践 作者:周志明》 JVM (Java Virtual Machine)

优秀的个人博客,低调大师

liunx入门知识总结

了解以下Linux下的重要目录/proc, /sys, /SElinux, /bin, /usr/lib, /usr/local, /var, /tmp : /proc 此目录的数据都在内存中,如系统核心,外部设备,网络状态,由于数据都存放于内存中,所以不占用磁盘空间,比较重要的目录有/proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/*等 /sys 文件系统访问 Linux内核 /SELinux SELinux是一种基于域-类型模型(domain-type)的强制访问控制(MAC)安全系统,它由NSA编写并设计成内核模块包含到内核中,相应的某些安全相关的应用也被打了SELinux的补丁,最后还有一个相应的安全策略。 /bin /usr/bin: 可执行二进制文件的目录,如常用的命令ls、tar、mv、cat等。 /usr 应用程序存放目录,/usr/bin 存放应用程序, /usr/share 存放共享数据,/usr/lib 存放不能直接运行的,却是许多程序运行所必需的一些函数库文件。/usr/local:存放软件升级包。/usr/share/doc: 系统说明文件存放目录。/usr/share/man: 程序说明文件存放目录,使用 man ls时会查询/usr/share/man/man1/ls.1.gz的内容建议单独分区,设置较大的磁盘空间 /usr/lib /usr/lib:/usr/local/lib: 系统使用的函数库的目录,程序在执行过程中,需要调用一些额外的参数时需要函数库的协助,比较重要的目录为/lib/modules。 /usr/local 这里主要存放那些手动安装的软件,即不是通过“新立得”或apt-get安装的软件。它和/usr目录具有相类似的目录结构。让软件包管理器来管理/usr目录,而把自定义的脚本(scripts)放到/usr/local目录下面。 /var 放置系统执行过程中经常变化的文件,如随时更改的日志文件 /var/log,/var/log/message: 所有的登录文件存放目录,/var/spool/mail: 邮件存放的目录, /var/run: 程序或服务启动 /tmp 一般用户或正在执行的程序临时存放文件的目录,任何人都可以访问,重要数据不可放置在此目录下 重要命令. du, df, top, free, pstack, su, sudo(sudo -, sudo -s), adduser, password 1.du命令:du [选项] 文件 (1)功能该命令是显示指定文件以及下的所有文件占用系统数据块的情况,如果没有文件,默认为是当前工作目录 -a 显示所有文件对系统数据块的使用情况 -b 显示数据块大小时以字节为基本单位 -c 除了显示文件对系统数据块的使用情况外还显示出文件的总和 -s 只显示文件数据块总大小,不显示文件名 -x 只显示当前目录,但不统计子目录 2.df命令:du [选项] 文件名 (1)功能该命令与du命令相似,只不过是df计算的是当前文件所以数据快的使用情况(包括前不久删除的文件),而du只是计算当前存在的所有文件的数据快的使用情况 -a 递归显示各文件及其子目录的数据块利用 -h 方便阅读时显示 -H 和-h一样,只不过1k = 1000;而不是1024 -i 显示inode信息 -k 区块为1024字节 -T 文件系统类型 3.top命令: (1)功能:相当于windows下的资源管理器,可以查看当前CPU的使用情况,各进程的状况 (2)选项 -b 批处理 -I 忽略过失 -c 显示完整的治命令 -s 保密模式 4.free命令 (1)功能:显示所有内存利用率。包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统使用的缓冲区等。 (2)选项 -b 以bype为单位显示 -k 以KB为单位显示 -m 以MB为单位显示 -o 不显示缓冲区 -t 显示内存总和列 5.pstack命令 (1)功能:进程跟踪 6.su命令 (1)功能:切换用户(由root用户向普通用户切换时不需要密码,由普通用户向root用户切换时需要密码) 6.password命令用来修改用户命令,但需要注意,root用户可以修改任何用户的密码,但普通用户只能修改自己的密码(这里涉及s权限的相关知识)。

优秀的个人博客,低调大师

Mycat(入门篇)

Mycat是什么 Mycat是一款基于阿里开源产品Cobar而研发的开源数据库分库分表中间件(基于Java语言开发)。官网所言:Mycat国内最活跃的、性能最好的开源数据库中间件! 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群 一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL Server 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品 一个新颖的数据库中间件产品 Mycat关键特性 支持SQL92标准 支持MySQL、Oracle、DB2、SQL Server、PostgreSQL等DB的常见SQL语法 遵守Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理 基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluster集群 支持Galera for MySQL集群,Percona Cluster或者MariaDB cluster 基于Nio实现,有效管理线程,解决高并发问题 支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数,支持跨库分页 支持单库内部任意join,支持跨库2表join,甚至基于caltlet的多表join 支持通过全局表,ER关系的分片策略,实现了高效的多表join查询 支持多租户方案 支持分布式事务(弱xa) 支持XA分布式事务(1.6.5) 支持全局序列号,解决分布式下的主键生成问题 分片规则丰富,插件化开发,易于扩展 强大的web,命令行监控 支持前端作为MySQL通用代理,后端JDBC方式支持MySQL、PostgreSQL、Oracle、DB2、SQLServer、MongoDB、巨杉 支持密码加密 支持服务降级 支持IP白名单 支持SQL黑名单、sql注入攻击拦截 支持prepare预编译指令(1.6) 支持非堆内存(Direct Memory)聚合计算(1.6) 支持PostgreSQL的native协议(1.6) 支持mysql和oracle存储过程,out参数、多结果集返回(1.6) 支持zookeeper协调主从切换、zk序列、配置zk化(1.6) 支持库内分表(1.6) 集群基于ZooKeeper管理,在线升级,扩容,智能优化,大数据处理(2.0开发版) 安装与使用 下载(目前最新发行版是1.6.5):http://dl.mycat.io/ 安装:解压即可 配置:Mycat是基于Java开发的,确保安装好了Java环境,可命令行输入:java -version 进行测试。Linux下还需配置Mycat的解压目录:vim /etc/profile,配置完成后使用:source /etc/profile: export JAVA_HOME=xxx export MYCAT_HOME=xxx 运行(Linux): ./mycat start 启动 ./mycat stop 停止 ./mycat console 前台运行 ./mycat install 添加到系统自动启动(暂未实现) ./mycat remove 取消随系统自动启动(暂未实现) ./mycat restart 重启服务 ./mycat pause 暂停 ./mycat status 查看启动状态 运行(Windows):双击bin/tartup_nowrap.bat,如果出现闪退,可在cmd命令行运行,并查看出错原因 内存配置:启动前,一般需要修改JVM配置参数,打开conf/wrapper.conf文件,可根据本机配置情况修改为512M或其它值 # Java Additional Parameters #wrapper.java.additional.1= wrapper.java.additional.1=-DMYCAT_HOME=. wrapper.java.additional.2=-server wrapper.java.additional.3=-XX:MaxPermSize=64M wrapper.java.additional.4=-XX:+AggressiveOpts wrapper.java.additional.5=-XX:MaxDirectMemorySize=2G wrapper.java.additional.6=-Dcom.sun.management.jmxremote wrapper.java.additional.7=-Dcom.sun.management.jmxremote.port=1984 wrapper.java.additional.8=-Dcom.sun.management.jmxremote.authenticate=false wrapper.java.additional.9=-Dcom.sun.management.jmxremote.ssl=false wrapper.java.additional.10=-Xmx4G wrapper.java.additional.11=-Xms1G 连接测试: 测试mycat与测试mysql完全一致,mysql怎么连接,mycat就怎么连接 命令行:mysql -uroot -proot -P8066 -h127.0.0.1(其中,user和password可在conf/server.xml配置查找,8066是默认的服务端口,也可以在conf/server.xml中配置修改) 客户端:1.3和1.4版本目前部分工具无法连接,会提示database not selected,建议使用高版本的Mycat,1.5版本已经修复了部分客户端工具的连接 常见分库分表产品对比 分库分表产品 MyCat Sharding-JDBC Cobar Cobar-client TDDL 分库 有 有 有 有 未开源 分表 有 有 无 无 未开源 中间层 是 否 是 否 否 ORM支持 任意 任意 任意 仅MyBatis 任意 数据库支持 任意 任意 仅MySQL 任意 任意 社区情况 活跃 活跃 停更 未知 未知 相关链接 Mycat官网 Mycat从零开始 Mycat权威指南 GitHub:Mycat-Server Wiki:Mycat-Server Issues:Mycat-Server mysql中间件研究(Atlas,Cobar,TDDL) mysql中间件研究(Atlas,Cobar,TDDL,Mycat,Heisenberg,Oceanus,Vitess,OneProxy)

优秀的个人博客,低调大师

JavaScript面向对象入门

什么是JavaScript? 我们可以从几个方面去说JavaScript是什么: 基于对象 javaScript中内置了许多对象供我们使用【String、Date、Array】等等 javaScript也允许我们自己自定义对象 事件驱动 当用户触发执行某些动作的时候【鼠标单机、鼠标移动】,javaScript提供了监听这些事件的机制。当用户触发的时候,就执行我们自己写的代码。 解释性语言 [x] javaScript代码是由浏览器解析的,并不需要编译。 基于浏览器的动态交互技术 既然javaScript是由浏览器解析的,那么它肯定要基于浏览器。 javaScript让网页变得更加“灵活"" 弱类型 [x] 像java、c++等编译型语言,要先定义变量,后使用。javaScript能够直接使用,不需要先定义 JavaScript变量类型 javaScript变量可分为三种类型: 基本类型【number、string、boolean】 javaScript是弱类型语言,在运行的时候才知道具体的类型是什么。所有类型都用var来修饰。 特殊类型【null、undefined】 当定义了变量,没有任何赋值的时候,该变量就是undefined类型 复合类型【数组、对象、函数】 javaScript对象的类型 在JavaScript中对象的类型可分为4种: 内置对象【String、Math、Array】 自定义对象【程序员自己创建的对象】 浏览器对象【windows、document、history、status等等与浏览器相关的对象】 ActiveXObject(XMLHttpRequest)对象【异步对象,使用AJAX用到的对象,使用该对象与服务器进行异步交互】 定义函数三种方式 函数是属于特殊类型的一种,在另外一篇博文已经讲解了创建对象、创建类的几种方式,可参考:http://blog.csdn.net/hon_3y/article/details/69362242 值得注意的是:javaScript定义函数的时候,参数的类型是不用声明的! 正常方式 下面就定义了一个名称为mysum的函数 function mysum(num1,num2){ return num1 + num2; } var myresult = mysum(100,200); alert("myresult="+myresult); Function定义 在JavaScript中, 一切皆是对象,函数也可以用一个对象来代表:Function,我们可以使用Function来创建对象: 函数参数全都是字符串,最后一个字符串是方法体 var youresult = new Function("num1","num2","return num1+num2"); alert( youresult(1000,2000) ); 由于这种方法写起来并不好些,可读性也不太好,因此很少使用【不推荐使用】 匿名创建函数 其实这种和第一种差不多,只不过是将一个无名的函数赋值给一个变量。那么这个变量就代表了这个函数。 var theyresult = function(num1,num2){ return num1 + num2; } alert( theyresult(10000,20000) ); theyresult这个变量就代表了函数。 创建对象 方式① 直接使用new Object() var obj = new Object(); 方式② 使用空的{}大括号 var obj2 = {}; 测试 增加属性,访问属性 我们要为创建的对象增加属性和访问属性的值! 使用.操作符增加属性 JavaScript是弱类型的语言,可以动态的添加属性。 obj.age = 20; obj.name = "zhongfucheng"; obj.say = function () { alert("hello"); }; 测试 使用.操作符访问属性 var aa = obj.age; var bb = obj.name; 测试 使用[]操作符访问属性 var aa = [obj["age"]]; var bb = [obj["name"]]; 测试 创建类 方式① 使用function来模拟创建类,function充当了构造函数 //测试函数 function test() { var teacher = new Teacher(); } //使用function来模拟类 function Teacher() { } 测试 方式② 上面的function来模拟类很容易和函数混淆。 我们一般这样做:用一个变量记住一个匿名的function当做是类,function充当了构造函数 function test() { var teacher = new Teacher(); } var Teacher = function () { }; 测试 方式③ 使用JSON语法来创建类,也就是对象直接量定义方法 var obj = { age: 20, str: "zhongfucheng", method:function () { alert("aaa"); } }; 测试 公有属性和方法 我们创建公有属性应该在类中指定,创建公有方法应该使用原型对象prototype prototype定义的属性就类似于Java的静态成员:在原型对象上定义了属性,拥有这个原型对象的function所创建的对象也拥有定义的属性!所以,我们方法中就使用prototype var obj = function Teacher(name) { this.name = name; if( typeof obj._init=="undefined") { obj.prototype.setName = function (name) { this.name = name; }; obj.prototype.getName = function () { alert(this.name); }; } obj._init = true; }; 创建两个不同的Teacher对象,name属性是不一样的。而它们共享同一份setName()和getName()方法 值得注意的是:prototype定义的属性只可读的。如果你想要使用具体对象写prototype的属性,实际上并不是写,而是重新为该类定义了一个同名(和prototype同名)的属性。在读取同名属性的时候,优先读取对象上的属性,而不是prototype的。 私有属性 我们在Java中,定义私有属性是通过关键字private来修饰的。。 在JavaScript中是没有这样的关键字的,我们需要这样做:定义在方法内【也就是function内部,也可以看作成构造函数】的变量,就是私有变量。 var obj = function Teacher(name) { //这是私有属性,外界不能访问 var age = 23; //这是公有属性,外界可以访问 this.name = name; //想要访问私有变量age,只能在这里编写方法来访问。其余的地方都不行! //我们通常就是在这里编写公有方法来访问私有属性 }; 静态属性和方法 在JavaScript中定义静态属性其实就是通过prototype原型对象来定义的。 定义静态的时机: 当类的某个值与对象无关期望所有位置看到的结果是一样的时候,就可以定义为类静态属性。 如果类的一个方法做的是和具体对象无关的操作,而是做一些工作操作的时候,就可以将这个方法定义为静态的类方法。 //静态属性TYPE Book.TYPE = “IT”; Book.print = function(){alert(Book.TYPE);} JavaScript中的for in循环 在学习AJAX的时候,发现JavaScript中for in循环,这种循环对于遍历JSON是很好用的。于是写下了这篇博文 for in循环本质上是forEach循环,它主要有两个作用 遍历数组 遍历JavaScript对象 遍历数组 当使用for in来遍历数组的时候,它的循环计数器是数组元素的索引值 var a = ['a', 'b', 'c']; for(var index in a) { alert(index); } 效果: 遍历JavaScript对象 当使用for in来遍历对象的时候,它的循环计数器是对象的属性名 //对象json上,包含了两个对象a和b属性 var json = {a:{num:1},b:{num:2}}; for(var name in json){ alert(name); } 效果 JS打气球游戏 在B站中看见了一个JS大气球这么一个教程,才知道原来JS+HTML5+CSS3能那么有趣。但是视频中没并没有给出源码。于是在别人的博客中搜到了对应的源码以及他自己实现的思路,该博主对其进行了改编。 http://www.cnblogs.com/morang/p/7636148.html 以上的博文有源码的下载。下面我就直接贴上源码了。思路就在博文中。 <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd"> <html> <head> <title>气球大战</title> <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"> <style> /*CSS3能够将气球描绘出来,使用到了圆形、旋转、阴影等技术*/ body{margin:0px;padding:0px;} #ballDiv{position: fixed;top: 0;left: 0;} .balloon{ width:150px; height:150px; position:absolute; left:0px; top:0px; background-color:#f3778d; border-radius:50% 50% 10% 50%; transform:rotate(45deg); box-shadow:1px 1px 20px 20px pink inset; z-index:10; } /*这里使用到了伪元素,可以不用到html中定义元素就可以实现功能了!*/ .balloon:after{ width:20px; height:20px; content:""; display:block; background:transparent; position:absolute; right: -15px; bottom: -15px; border-left:5px solid pink; border-top:5px solid pink; } /*这里使用到了伪元素,可以不用到html中定义元素就可以实现功能了!*/ .balloon:before{ width: 2px; height: 50px; content: ""; display: block; background: #ffc0cb; position: absolute; right: -10px; top: 100%; margin-top: -16px; transform: rotate(-45deg); } </style> </head> <body> <div id="gameinfo" style="transform: translateZ(360px);"> <p> 最高连击:<span id='maxDoubleHit'>0</span> </p> <p> 本次游戏:<span id='currentDoubleHit'>0</span> </p> <p id="gamemsg" style="display:none;"> <span style="color:red;font-weight:bold;"> Game Over </span> <button onclick="javscript:location.reload();"> 重新开始 </button> </p> </div> <div id="ballDiv"> </div> <!--<div class="balloon"></div>--> <script> var maxDoubleHit=localStorage.getItem('eliminateCount')||0 var currentDoubleHit=0 //当做一个缓存池,优化性能的。 var bnElements=[];//存放所有气球 var random=Math.random;//随机函数 var wW=window.innerWidth;//窗口宽度 var wH=window.innerHeight;//窗口高度 var ballW=160;//气球的宽度 var ballH=300;//气球的宽度 var minSpeed=3;//最小速度,每次向上移动至少3px var speedNum=5;//速度的定量 var defBnNumber=5;//初始化气球 var moveTimer; var isEnd=false; var jindex=1; var ballDiv=document.getElementById('ballDiv'); //初始化 init(defBnNumber); //移动 move(); //绑定单击事件 bindClick(); //游戏信息 document.getElementById('maxDoubleHit').innerText=maxDoubleHit function record(){ if(isEnd){ clearTimeout(moveTimer); bnElements=[]; document.getElementById('gamemsg').style.display='block'; document.getElementById('gameinfo').style='transform: translateZ(360px);position: fixed;top:0;left:0;z-index:999'; } else{ init(1); document.getElementById('currentDoubleHit').innerText=++currentDoubleHit; if(currentDoubleHit>maxDoubleHit){ document.getElementById('maxDoubleHit').innerText=currentDoubleHit; localStorage.setItem('eliminateCount',currentDoubleHit) } } } //初始化气球 function init(num){ //创建一个虚拟文档节点 var docFragment=document.createDocumentFragment(); for(var i=0;i<num;i++){ var bnElement=document.createElement('div'); bnElement.className='balloon'; //速度随机,限定最小值 var speed=Math.max(minSpeed,~~(random()*speedNum)); bnElement.setAttribute('speed',speed);//~~取整 移动速度 bnElement.setAttribute('id','ball-'+jindex++); //分散排列 var x=(~~(random()*wW))-ballW; x=Math.max(0,x); bnElement.style.left=x+'px'; bnElement.style.top=wH+'px';//露一点出来 //1.先将创建的气球放入创建的虚拟文档节点 docFragment.appendChild(bnElement); bnElements.push(bnElement); } //2.将虚拟文档节点添加到body中 ballDiv.appendChild(docFragment); } //使用定时器来对气球进行移动。 function move(){ var bl=bnElements.length for(var i=0;i<bl;i++){ var currentElement=bnElements[i] if(currentElement==null){ continue; } var offsetTop=currentElement.offsetTop; if(offsetTop>0){//窗口中 //offset就是针对窗口的位置来进行移动的。 var speed=currentElement.getAttribute('speed'); currentElement.style.top=offsetTop-speed+'px' } else{ //移除dom节点 //ballDiv.removeChild(currentElement); //移除数组中 //bnElements.splice(i,1); //init(1); isEnd=true; record(); } } moveTimer=setTimeout(move,1000/30); } //对所有的气球进行单击监听事件,不要单独为每个气球来进行监听,这样耗费性能! function bindClick(){ ballDiv.addEventListener('click',clickFunc,false); function clickFunc(e){ if(!isEnd && e.target.className=='balloon'){ bnElements.splice(bnElements.lastIndexOf(e.target),1); //这里使用call主动调用,在boom方法中我们就可以使用this指针了。 boom.call(e.target,function(){ e.target.parentNode.removeChild(e.target); record(); }); } } } function boom(callback){ //var that=this; //替换了上下文,但是没有使用this的意义. var speed=this.getAttribute('speed'); this.timer=setInterval(function(){ this.style.opacity=0.1*(speed--) if(speed<1){ callback&&callback(); clearInterval(this.timer); } }.bind(this),30); } </script> </body> </html> 看了视频也学到了之前一直没有注意的东西: CSS3很厉害啊,能将方形的div转成是椭圆形的[也就是气球的形状],还有盒子的阴影设置。 使用伪元素就可以不用直接在html中设置标签了。配合CSS3也能够做出对应的样式。 使用实体边框配合CSS3也可以做出不同的形状样式 在生成元素的时候,可以先将要生成的元素加入到文档片段中,再使用文档片段来进行一次性添加到body上,这样性能会好很多! 使用~~运算符能够取整数 限定气球的边界就可以使用max和min函数来进行限定。这也是很好用的。 移动气球我们需要用到定时器。 使用call主动调用方法,把目标对象传递过去的话,我们就可以使用this指针了。 在定时器中使用bind(this),就可以在定时器中使用this指针的,因为定时器默认是由浏览器window来进行调用的,默认是不能使用this的 绑定单击事件的时候,不要使用循环来进行绑定,这样太耗费性能了,我们可以使用监听事件来进行一次绑定。 在遍历元素数组的时候,条件是元素数组的长度时,我们可以先把该元素数组的长度初始化出来,那么也可以提升性能!不然就每次判断前都要去查询数据的长度! for(var i=0,len = array.length; i<len;i++){} 如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y 更多的文章可往: 文章的目录导航

优秀的个人博客,低调大师

Python快速入门_1

注释 # 用#号字符开头注释单行 """ 三个引号可以注释多行 三个引号可以注释多行 三个引号可以注释多行 """ 原始数据类型和运算符 (1)整型 #整数 3 #=>3 (2)算术运算 #加法 1+1 #=>2 #减法 8-1 #=>7 #乘法 10*2 #=>20 #除法 !!!结果自动转换成浮点数 35/5 #=>7.0 5/3 #=>1.6666666666666667 #整数除法 !!!结果向下取整 5//3 #=>1 5.0//3.0 #=>1.0 -5//3 #=>-2 5//(-3) #=>-2 -5.0//3.0 #=>-2.0 #浮点数的运算结果也是浮点数 3*2.0 #=>6.0 #取模 7%3 #=>1 #x的y次方 2**4 #=>16 #用括号决定优先级 (1+3)*2 #=>8 (2)布尔运算与比较运算 #布尔值 True #=>True False #=>False #用not取非 not True #=>False not False #=>True #逻辑运算符,注意and和or都是小写 True and False #=>False True or False #=>True #整数也可以当做布尔值 0== False #=>True 2==True #=>False 1==True #=>True #用==判断相等 1==1 #=>True 2==1 #=>False #用!=判断不等 1!=1 #=>False 1!=2 #=>True #比较大小 1<10 #=>True 2<=2 #=>True 2>=2 #=>True (4)字符串运算 #字符串用单引号双引号都可以 '这个是字符串' "这个也是字符串" #用加号连接字符串 'Hello '+'World' #=>'Hello World' #字符串可以被当做字符列表 'This is a string'[0] #=>'T' #用format来格式化字符串 "{} can be {}".format("string",'interpolated') #=>'string can be interpolated' #可以重复参数以节省时间 "{0} be nimble,{0} be quick,{0} jump over the {1}".format("jack","candle stick") #=>'jack be nimble,jack be quick,jack jump over the candle stick' #如果不想数参数可以用关键词 "{name} wants to eat {food}".format(name='Bob',food='lasagna') #=>'Bob wants to eat lasagna' #如果你的python3程序也要运行在Python2.5以下环境运行,也可以用老式的格式化语法 "%s can be %s the %s way"%('strings','interpolater','old') #=>'strings can be interpolater the old way' (2)None #None是一个对象 None #当与None进行比较时不要用==,要用is,is是用来比较两个变量是否指向同一个对象 'etc' is None #=>False None is None #=>True #None,0,空字符串,空列表,空字典都算是False,其他都是True bool(None) #=>False bool(0) #=>False bool("") #=>False bool({}) #=>False bool([]) #=>False

优秀的个人博客,低调大师

Python入门:内置函数

可创建一个整数列表,一般用在 for 循环中。 函数语法 range(start, stop[, step]) 参数说明: start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5); end: 计数到 end 结束,但不包括 end。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5 step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1) 示例: >>>range(10) # 从 0 开始到 10 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> range(1, 11) # 从 1 开始到 11 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> range(0, 30, 5) # 步长为 5 [0, 5, 10, 15, 20, 25] >>> range(0, 10, 3) # 步长为 3 [0, 3, 6, 9] >>> range(0, -10, -1) # 负数 [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] >>> range(0) [] >>> range(1, 0) [] for i in range(0,10) # i遍历从0到9 range() 返回对象(字符、列表、元组等)长度或项目个数。 语法 len()方法语法: len( s ) 参数 s -- 对象。 返回值 返回对象长度。 示例 以下实例展示了 len() 的使用方法: >>>str = "runoob" >>> len(str) # 字符串长度 6 >>> l = [1,2,3,4,5] >>> len(l) # 列表元素个数 5 for i in range(len(list)) len() 打印输出 语法 print(*objects, sep=' ', end='\n', file=sys.stdout) 参数 objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。 sep -- 用来间隔多个对象,默认值是一个空格。 end -- 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符串。 file -- 要写入的文件对象。 返回值 无。 示例 以下展示了使用 print 函数的实例: Python3 下测试 >>>print(1) 1 >>> print("Hello World") Hello World >>> a = 1 >>> b = 'runoob' >>> print(a,b) 1 runoob >>> print("aaa""bbb") aaabbb >>> print("aaa","bbb") # 默认空格间隔 aaa bbb >>> >>> print("www","runoob","com",sep=".") # 设置间隔符 www.runoob.com print() 方法对系列进行求和计算。 语法 sum(iterable[, start]) 参数 iterable -- 可迭代对象,如列表。 start -- 指定相加的参数,如果没有设置这个值,默认为0。 返回值 返回计算结果。 示例 以下展示了使用 sum 函数的实例: >>>sum([0,1,2]) 3 >>> sum((2, 3, 4), 1) # 元组计算总和后再加 1 10 >>> sum([0,1,2,3,4], 2) # 列表计算总和后再加 2 12 sum() 返回给定参数的最小值,参数可以为序列。 语法 以下是 min() 方法的语法: min( x, y, z, .... ) 参数 x -- 数值表达式。 y -- 数值表达式。 z -- 数值表达式。 返回值 返回给定参数的最小值。 实例 以下展示了使用 min() 方法的实例: #!/usr/bin/python print "min(80, 100, 1000) : ", min(80, 100, 1000) print "min(-20, 100, 400) : ", min(-20, 100, 400) print "min(-80, -20, -10) : ", min(-80, -20, -10) print "min(0, 100, -400) : ", min(0, 100, -400) 以上实例运行后输出结果为: min(80, 100, 1000) : 80 min(-20, 100, 400) : -20 min(-80, -20, -10) : -80 min(0, 100, -400) : -400 min() 返回给定参数的最大值,参数可以为序列。 语法 以下是 max() 方法的语法: max( x, y, z, .... ) 参数 x -- 数值表达式。 y -- 数值表达式。 z -- 数值表达式。 返回值 返回给定参数的最大值。 示例 以下展示了使用 max() 方法的实例: #!/usr/bin/python print "max(80, 100, 1000) : ", max(80, 100, 1000) print "max(-20, 100, 400) : ", max(-20, 100, 400) print "max(-80, -20, -10) : ", max(-80, -20, -10) print "max(0, 100, -400) : ", max(0, 100, -400) 以上实例运行后输出结果为: max(80, 100, 1000) : 1000 max(-20, 100, 400) : 400 max(-80, -20, -10) : -10 max(0, 100, -400) : 100 max()

优秀的个人博客,低调大师

Google Native Client入门

上午在去往上海的动车组上看到《Google正在测试ActiveX的继任者》这条新闻,因为前段时间一直在做一个证件信息采集的ActiveX控件,而众所周知,ActiveX的安全性是臭名昭著的,所以对这个所谓的“继任者”非常感兴趣,晚上回来后就第一时间试了试。 Native Client项目主页:http://code.google.com/p/nativeclient/ Native Client是一个在Web应用程序中运行本地代码(目前只支持x86架构)的开源的研究性技术,提供更好的“富客户端”用户体验。它允许网络开发者编写更强大的Web程序,这些程序直接通过系统运行而不用通过浏览器来进行,据Google称,它到最后将允许网络开发者开发和桌面软件一样的的web程序,这些程序将带来更快的速度。Native Client类似于微软的ActiveX技术,它还能在Linux和Mac OS X下运行。目前它尚未支持IE,仅支持Google Chrome, Firefox, Safari 和Opera。 本文实验所用OS:Hiweed2.0,官网:http://www.hiweed.com/ 要使它带的示例程序运行为Native Client的模块,你必须要有如下软件:1)Native Client。2)Python(版本在2.4或2.5)。3)一个浏览器(推荐Firefox3) 下面是安装Native Client的步骤: 1,从官网上获取nacl_linux_0.1_9308700.tgz文件,解压缩到你指定的目录下: tar xvf nacl_linux_0.1_9308700.tgz 2,验证Python版本(注意下面的V是大写字母)是2.4或2.5。 python –V 若版本过低或未安装python,则使用下述命令安装: sudo apt-get install python2.4 将示例作为Native Client应用程序来运行 现在来看如何在Native Client中运行一个示例。 1,进入到earth这个demo所在目录 cd install_dir/nacl/googleclient/native_client/tests/earth 2,运行earth这个demo python run.py 结果如图所示,标题“NaCl Application”表明你是在一个特定的进程中运行一个Native Client模块: 安装和使用插件 现在我们切换到浏览器中来运行Native Client模块,我们必须安装Native Client插件,然后把引用这些Native Client模块的页面给加载到浏览器中。 1,进入native_client目录 cd install_dir/nacl/googleclient/native_client 2,若你正在运行firefox,那就关闭它,否则插件可能安装失败。 3,使用如下命令安装插件,在安装过程中回答一个yes ./scons --prebuilt firefox_install Okay to continue? [y/n] y 4,检查最后输出的安装结果,成功的话就去启动firefox 5,在firefox中打开下面这个页面 install_dir/nacl/googleclient/native_client/scons-out/nacl/staging/index.html 这里列出了很多示例,可以自行玩玩。 使用make编译和运行单独的示例(仅限于Linux或Mac) 1,进入到你要编译运行的示例目录下,以earth为例: cd install_dir/nacl/googleclient/native_client/tests/earth 2,重新编译为一个单独的应用程序并运行: make debug run 3,重新编译为一个Native Client模块并运行: make release nacl run 这就是文章最开头显示的realease版本 4,移除掉你自行编译的版本,使用预编译好的版本,和前面两种比较下(其实就是第二种啦)。 make clean python run.py 附:1)Google为了说明这个东西的安全性还发了一篇paper,刚开始看,以后再补上笔记 2)为了方便起见,没有在Windows下测试,有兴趣可按照官方文档试试 3)不知是不是故意捉弄微软,Google推出的这个“ActiveX杀手”竟然在第一时间不支持IE。(哈哈,相信后续会支持的,否则还有啥用?) 参考资料: 1,Native Client Getting Started guide. 2, Building Native Client 本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/12/09/1351378.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Visual Basic快速入门

Basic语言的全名是Beginner's All-purpose Symbolic Instruction Code(初学者通用的符号指令代码),是几十年前流行过的一门语言。我高中时候一门数学选修课中使用的也是Basic语言。我还记得当时我为了使用Basic语言,还从网上下了一个简陋的QBasic工具。当时第一次接触编程的我对编程语言充满了兴趣。当然在现在,Basic语言已经基本没什么用了。现在还在使用的Basic语言大概就是微软的Visual Basic了。今天就来介绍一下Visual Basic语言。需要注意的是,VB语言运行在微软的CLR上,所以如果你对C#比较熟悉的话,学习VB就很简单了。 HelloWorld 照例,第一个项目自然应该是HelloWorld。打开Visuall Studio,创建一个VB项目,然后就会出现如下图所示的代码。 HelloWorld 来解释一下HelloWorld的代码。首先第一行是导入类库,和C#、java的import语句是一个道理。然后下面定义了一个Program模块,其中定义了Main函数,在函数中输出Hello World。在VB中,不使用大括号作为块分隔符,而是使用End语句来结束块作用域。 Imports System Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") End Sub End Module 基本数据类型 由于VB和C#都是运行在CLR上的语言,所以其实它们的基本类型是一样的,都有有/无符号的各种长度整数、单精度双精度浮点数、布尔类型、字符和字符串等类型。下面的代码仅列出几个常用的。 Public Class DataType Sub DataType() Dim b As Byte Dim i As Integer Dim s As Single Dim d As Double Dim c As Char Dim str As String Dim bool As Boolean b = 100 i = 1000 s = 1.5 d = 3.1415926 c = "c"c str = "abc" bool = True End Sub End Class 变量和常量 VB的变量定义也和C系语言不同,使用的是Dim 变量名 As 变量类型的语法进行定义。变量必须先定义才能使用。如果想同时定义多个变量,可以这么写。 Dim i, j As Integer 如果想在定义变量的同时初始化,可以这样。 Dim bool As Boolean = True 如果要定义常量,可以变量类似,只不过使用Const关键字。 Const cs As Integer = 1000 运算符 先来看看算术运算符。 运算符 用途 例子 ^ 幂运算符 3 ^ 2 = 9 + 加法 - 减法 * 乘法 / 小数除法 3 / 2 = 1.5 \ 整除 3 \ 2 = 1 MOD 取模 6 MOD 4 = 2 然后是比较运算符。这里需要注意的就是VB的相等和不等和其他语言的可能不太一样。 运算符 用途 = 相等 <> 不等 < 小于 > 大于 <= 不大于 >= 不小于 然后是逻辑运算符。 运算符 用途 And 与运算符,不短路求值 Or 或运算符,不短路求值 Not 非运算符 Xor 异或运算符 AndAlso 与运算符,短路求值 OrElse 或运算符,短路求值 IsTrue 是否为真 IsFalse 是否为假 条件语句 If语句 先来看看VB中的If语句,其基本结构是If 条件 Then 执行体 Else 执行体 End If。 Dim num As Integer = 5 If num\2 = 0 Then Console.WriteLine($"{num} is even") Else Console.WriteLine($"{num} is odd") End If 如果需要多重If语句,可以添加ElseIf语句块。 If num = 1 Then Console.WriteLine($"{num} is 1") ElseIf num = 2 Console.WriteLine($"{num} is 2") Else Console.WriteLine($"{num} is other") End If Select语句 Select语句相当于其他语言中的switch语句,如果没有匹配项,会执行Case Else语句块。 Dim c As Char = "c"c Select c Case "a"c Console.WriteLine("a") Case "b"c, "c"c Console.WriteLine("b or c") Case Else Console.WriteLine("others") End Select 循环语句 Do语句循环 Do语句循环有两种结构,第一种是循环条件在前。先来看看Do-While语句,当满足循环条件的时候会继续循环,不满足条件时跳出循环。这里顺便提一下,VB中没有块注释,只有单行注释,以单引号开头,直到句末。 'Do While语句 Dim i = 0 Do While i < 5 If i = 3 Then Exit Do End If Console.Write(i) i += 1 Loop 再来看看Do-Until语句,和Do-While相反,在不满足条件的时候会执行循环,满足条件时跳出循环。 'Do Until语句 i = 0 Do Until i > 5 If i < 3 Then i += 2 Continue Do End If Console.Write(i) i += 1 Loop Do循环的第二种形式就是先执行循环体,然后进行判断,同样有While和Until两种。 i = 0 Do Console.Write(i) i += 1 Loop While i < 5 Console.WriteLine While循环 还有就是传统的While循环。 'While循环 i = 0 While i < 5 Console.Write(i) i += 1 End While For循环 下面是For循环的例子,在For循环中可以使用Step指定步长。 For counter As Integer = 1 To 9 Step 1 Console.Write(counter) Next Foreach循环 Foreach循环用于迭代一个列表中的每一项。 Dim array() as Integer = {1, 2, 3, 4, 5, 6, 7} For Each item As Integer In array Console.Write(item) Next With语句 With语句其实不算循环语句,不过我看的这个VB教程把With语句放到这里说,那我也放到这里好了。With语句在有些语言中也有,主要用途是节省代码数量。比方说有下面这个Person类。 Public Class Person Public Property Name As String Public Property Age As Integer End Class 假如有一个person对象多次出现的话,就可以使用With语句,在With语句中,点访问符默认指向的就是With语句指定的对象。 Dim person As Person = New Person With person .Name = "yitian" .Age = 25 Console.WriteLine($"Person(Name:{.Name}, Age:{.Age})") End With 跳转语句 Exit语句 Exit语句用于结束某个代码块,它的形式如下。想用Exit退出哪个代码块,就写哪个代码块的类型。 Exit { Do | For | Function | Property | Select | Sub | Try | While } Continue语句 Continue语句用于结束当前循环,直接进行下一次循环。它的形式如下,后面跟要继续的代码块类型。 Continue { Do | For | While } Goto语句 最后就是Goto语句,它会直接跳转到指定的标签处。 'Goto语句 GoTo Ending Console.WriteLine("Print something") Ending: Console.WriteLine("This is end.") 数组 先来看看数组定义。VB中的数组比较特殊,定义一个Dim a1(3),其实是下标0-4长度为四的一维数组,这一点要非常注意。 '下标0-9的十个元素的数组 Dim array1(9) As Integer '11X11的二维数组 Dim array2(2, 2) As Integer '定义并初始化数组 Dim array3() = {1, 2, 3, 4, 5} '锯齿数组,也就是数组的数组 Dim array4 As Integer()() = New Integer(1)() {} array4(0) = New Integer() {1, 2} array4(1) = New Integer() {3, 4} 访问数组元素需要使用圆括号,而不是一般语言的方括号。 '初始化一维数组 For i As Integer = 0 To 9 array1(i) = i Next '初始化二维数组 For i = 0 To 2 For j = 0 To 2 array2(i, j) = (i + 1)*(j + 1) Next Next 最后就是遍历数组了,可以使用For循环迭代下标,或者用Foreach循环直接遍历元素。 '显示数组 For Each e In array1 Console.Write(e) Next Console.WriteLine For i As Integer = 0 To 2 For j = 0 To 2 Console.Write(array2(i, j)) Next Console.WriteLine Next For Each e In array3 Console.Write(e) Next Console.WriteLine For i As Integer = 0 To 1 For j = 0 To 1 Console.Write(array4(i)(j)) Next Console.WriteLine Next 函数 Sub函数 回头来看看前面的HelloWorld,其中就有一个Main函数,它是一个Sub函数,也就是没有返回值的函数。 Imports System Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") End Sub End Module 函数可以按值传参,也可以按引用传参,默认情况下是按值传参。 Function GetParam(ByVal a As Integer, ByRef b As Integer) a = 10 b = 10 Console.WriteLine("Param changed") End Function Function函数 Function函数就是有返回值的函数。在函数中,如果要返回值,可以有两种办法,第一种是使用Return语句,第二种是在函数体中向函数名赋值。 '函数返回值可以用Return语句 Function Return1() As Integer Return 1 End Function '也可以向函数名赋值 Function Return2() As Integer Return2 = 2 End Function 可变参数列表 可变参数列表使用ParamArray声明。 Function PrintIntegers(ParamArray integers As Integer()) For Each i In integers Console.Write(i) Next Console.WriteLine End Function 面向对象编程 类 VB的类和C#的类非常相似,同样有字段、属性等概念。构造函数使用New声明,不需要返回值。析构函数使用Finalize声明,也不需要返回值。 Class Contact ' 字段 Private _name As String Private _tel As String '构造函数 Public Sub New(name As String, tel As String) _name = name _tel = tel End Sub '析构函数 Protected Overrides Sub Finalize() End Sub '属性 Public Property Tel As String Get Return _tel End Get Set _tel = value End Set End Property Public Property Name As String Get Return _name End Get Set(value As String) _name = value End Set End Property '重写方法 Public Overrides Function ToString() As String Return $"Contact(Name:{Name}, Tel:{Tel})" End Function End Class 抽象类和接口 如果一个类的方法含有MustOverride修饰符,那么这个方法就是一个抽象方法。含有抽象方法的类就是抽象类,需要使用MustInherit关键字修饰。 MustInherit Class Shape MustOverride Function GetArea() As Double End Class Interface Color Function GetColor() As String End Interface 继承 继承基类和实现接口的声明必须写在类实现的前面。如果一个方法重写了基类的版本,那么这个方法应该使用Overrides关键字修饰。如果不希望类被其他类继承,可以使用NotInheritable修饰,类似于Java的final关键字或者C#的sealed关键字。如果子类需要调用基类的方法,可以使用MyBase关键字代表基类。 Class Circle Inherits Shape Protected radius As Double Public Sub New(r As Double) radius = r End Sub Public Overrides Function GetArea() As Double Return Math.PI*radius*radius End Function End Class NotInheritable Class RedCircle Inherits Circle Implements Color Public Sub New(r As Double) MyBase.New(r) End Sub Public Function Color_GetColor() As String Implements Color.GetColor Return "Red" End Function End Class 静态成员 静态成员和静态函数使用Shared关键字声明,对于每个类来说Shared成员只会存在一个。 Class MyMath Public Shared PI As Double = 3.1415926 Public Shared Function GetPI As Double Return PI End Function End Class 模块 Module类似于Class,不同之处在于Module不需要实例化,其中的函数可以直接调用,就像静态函数一样。 Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") End Sub End Module 异常处理 VB的异常处理和C#的一样,都有Try、Catch、Finally部分。 Public Module ExceptionHandling Sub HandleException() Try Throw New ArithmeticException("除数不能为零") Catch ex As ArithmeticException Console.WriteLine($"捕获了数学计算异常:{ex.Message}") Catch ex As Exception Console.WriteLine($"捕获了异常:{ex.Message}") Finally Console.WriteLine("终结代码") End Try End Sub End Module 以上就是VB语言的一些介绍了,希望对大家能有所帮助。

优秀的个人博客,低调大师

ExtJS 2.0入门指南

开始! 我们将讲讲怎么使用ExtJS,来完成一些JavaScript常见的任务。如果你想自己试试,就应该先下IntroToExt2.zip,用来构建已下面的Ext代码。 Zip包里有三个文件:ExtStart.html,ExtStart.js和ExtStart.css。解包这三个文件到Ext的安装目录中(例如,Ext是在“C:\code\Ext\v2.0”中,那应该在"v2.0"里面新建目录“tutorial”。双击ExtStart.htm,接着你的浏览器打开启动页面,应该会有一条消息告诉你配置已完毕。如果出现了Javascript错误,请按照页面上的指引操作。 现在在你常用的IDE中或文本编辑器中,打开ExtStart.js看看。 Ext.onReady(function(){alert("Congratulations! You have Ext configured correctly!");}); Ext.onReady可能是你接触的第一个也可能是在每个页面都要使用的方法。这个方法会在DOM加载全部完毕后,保证页面内的所有元素能被Script引用(reference)之后调用。你可删除alert()那行,加入一些实际用途的代码试试。 Element:Ext的核心 大多数的JavaScript操作都需要先获取页面上的某个元素的引用(reference),好让你来做些实质性的事情。传统的JavaScript做法,是通过ID获取Dom节点的: var myDiv = document.getElementById('myDiv'); 这毫无问题,不过这样单单返回一个对象(DOM节点),用起来并不是太实用和方便。为了要用那节点干点事情,你还将要手工编写不少的代码;另外,对于不同类型浏览器之间的差异,要处理起来可真头大了。 进入Ext.element 对象。元素(element)的的确确是Ext的心脏地带,--无论是访问元素(elements)还是完成一些其他动作,都要涉及它。Element的API是整个Ext库的基础,如果你时间不多,只是想了解Ext中的一两个类的话,Element一定是首选! 由ID获取一个Ext Element如下(首页ExtStart.htm包含一个div,ID名字为“myDiv”,然后,在ExtStart.js中加入下列语句): Ext.onReady(function(){var myDiv = Ext.get('myDiv');}); 再回头看看Element对象,发现什么有趣的东东呢? Element包含了常见的DOM方法和属性,提供一个快捷的、统一的、跨浏览器的接口(若使用Element.dom的话,就可以直接访问底层DOM的节点。); Element.get()方法提供内置缓存(Cache),多次访问同一对象效率上有极大优势; 内置常用的DOM节点的动作,并且是跨浏览器的定位的位置、大小、动画、拖放等等(add/remove CSS classes, add/remove event handlers, positioning, sizing, animation, drag/drop)。 这意味着你可用少量的代码来做各种各样的事情,这里仅仅是一个简单的例子(完整的列表在Element API 文档中)。 继续在ExtStart.js中,在刚才我们获取好myDiv的位置中加入: myDiv.highlight();//黄色高亮显示然后渐退 myDiv.addClass('red');// 添加自定义CSS类 (在ExtStart.css定义) myDiv.center();//在视图中将元素居中 myDiv.setOpacity(.25);// 使元素半透明 获取多个DOM的节点 通常情况下,想获取多个DOM的节点,难以依靠ID的方式来获取。有可能因为没设置ID,或者你不知道ID,又或者直接用ID方式引用有太多元素了。这种情况下,你就会不用ID来作为获取元素的依据,可能会用属性(attribute)或CSS Classname代替。基于以上的原因,Ext引入了一个异常强大的Dom Selector库,叫做DomQuery。 DomQuery可作为单独的库使用,但常用于Ext,你可以在上下文环境中(Context)获取多个元素,然后通过Element接口调用。令人欣喜的是,Element对象本身便有Element.selcect的方法来实现查询,即内部调用DomQuery选取元素。这个简单的例子中,ExtStart.htm包含若干段落(<p>标签),没有一个是有ID的,而你想轻松地通过一次操作马上获取每一段,全体执行它们的动作,可以这样做: // 每段高亮显示 Ext.select('p').highlight(); Element.select在这个例子中的方便性显露无疑。它返回一个复合元素,能通过元素接口(Element interface)访问每个元素。这样做的好处是可不用循环和不分别访问每一个元素。 DomQuery的选取参数可以是一段较长的数组,其中包括W3C CSS3 Dom选取器、基本XPatch、HTML属性和更多,请参阅DomQuery API文档以了解这功能强大的库个中细节。 响应事件 到这范例为止,我们所写的代码都是放在onReady中,即当页面加载后总会立即执行,功能较单一——这样的话,你便知道,如何响应某个动作或事件来执行你希望做的事情,做法是,先分配一个function,再定义一个event handler事件处理器来响应。我们由这个简单的范例开始,打开ExtStart.js,编辑下列的代码: 复制代码 function MyparagraphClick() { alert("dsdf"); } function test(e) { var para = Ext.get(e.target); para.highlight(); Ext.MessageBox.show({title:'para clicked',msg:para.dom.innerHTML,width:400, buttons:Ext.MessageBox.OK,animEl:para}); } Ext.onReady(function() { var myDiv = Ext.get('myDiv'); myDiv.highlight(); myDiv.addClass('red'); myDiv.center(); Ext.select('p').highlight(); Ext.get('myButton').on('click',function() { alert("click me!"); }); var paragraphClick = function(e) { //alert("click wto"); Ext.get(e.target).highlight(); } Ext.select('p').on('click',test); }); 复制代码 现在,为了我们接下来阐述新概念的演示,请观察MessageBox的调用。乍一看,这像一连串的参数传入到方法中,但仔细看,这是一个非常特别的语法。实际上,传入到MessageBox.show的只有一个参数:一个Object literal,包含一组属性和属性值。在Javascript中,Object Literal是动态的,你可在任何时候用{和}创建一个典型的对象(object)。其中的字符由一系列的name/value组成的属性,属性的格式是[property name]:[property value]。在整个Ext中,你将会经常遇到这种语法,因此你应该马上消化并吸收这个知识点! 使用Object Literal的原因是什么呢?主要的原因是“可伸缩性(flexibility)”的考虑",随时可新增、删除属性,亦可不管顺序地插入。而方法不需要改变。这也是多个参数的情况下,为最终开发者带来不少的方便(本例中的MessageBox.show())。例如,我们说这儿的foo.action方法,有四个参数,而只有一个是你必须传入的。本例中,你想像中的代码可能会是这样的foo.action(null, null, null, 'hello').,若果那方法用Object Literal来写,却是这样, foo.action({ param4: 'hello' }),这更易用和易读. Grid Grid是Ext中人们最想先睹为快的和最为流行Widgets之一。好,让我们看看怎么轻松地创建一个Grid并运行。 复制代码 Ext.onReady(function() { var myData =[['Apple',29.89,0.24,0.81,'9/1 12:00am'], ['Ext',83.81,0.28,0.34,'9/12 12:00am'], ['Google',71.72,0.02,0.03,'10/1 12:00am'], ['Microsoft',52.55,0.01,0.02,'7/4 12:00am'], ['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']]; var myReader =new Ext.data.ArrayReader({},[{name:'company'},{name:'price', type:'float'},{name:'change', type:'float'},{name:'pctChange', type:'float'},{name:'lastChange', type:'date', dateFormat:'n/j h:ia'}]); var grid =new Ext.grid.GridPanel({store:new Ext.data.Store({data: myData, reader: myReader}), columns:[{header:"Company", width:120, sortable:true, dataIndex:'company'},{header:"Price", width:90, sortable:true, dataIndex:'price'},{header:"Change", width:90, sortable:true, dataIndex:'change'},{header:"% Change", width:90, sortable:true, dataIndex:'pctChange'},{header:"Last Updated", width:120, sortable:true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex:'lastChange'}], viewConfig:{forceFit:true}, renderTo:'content', title:'My First Grid', width:500, frame:true}); grid.getSelectionModel().selectFirstRow(); }); 复制代码 这看上去很复杂,但实际上加起来,只有四行代码(不包含测试数据的代码)。 第一行创建数组并作为数据源。实际案例中,你很可能从数据库、或者WebService那里得到动态的数据。 接着,我们创建并加载data store, data store将会告诉Ext的底层库接手处理和格式化这些数据。不同的数据类型须在类Reader中指明。 接着,我们创建一个Grid的组件,传入各种的配置值,有: 新的data store, 配置好测试数据和reader 列模型column model定义了列columns的配置 其他的选择指定了Grid所需的功能 最后,通过SelectionModel告诉Grid高亮显示第一行。 不是太困难吧?如果一切顺利,完成之后你会看到像这样的: 使用Ajax 在弄好一些页面后,你已经懂得在页面和脚本之间的交互(interact)原理。接下来,你应该掌握的是,怎样与远程服务器(remote server)交换数据,常见的是从数据库加载数据(load)或是保存数据(save)到数据库中。通过JavaScript异步无刷新交换数据的这种方式,就是所谓的Ajax。Ext内建卓越的Ajax支持,例如,一个普遍的用户操作就是,异步发送一些东西到服务器,然后,UI元素根据回应(Response)作出更新。 客户端: <div id="msg"></div> <div>Name:<input type="text"id="name"/> <input type="button"id="okButton" value="确定"/> </div> 复制代码 Ext.onReady(function() { Ext.get('okButton').on('click',function() { var msg = Ext.get('msg'); msg.load({url:'http://localhost:8080/ajaxDemo/hello', params:'name='+ Ext.get('name').dom.value, text:'Updating'}); msg.show(); }); }); 复制代码 服务器端: 复制代码 import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class hello extends HttpServlet { public hello() { super(); } public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("From Server: hello,ajax!"); out.close(); } public void init() throws ServletException { // Put your code here } } 复制代码 本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/07/14/1242855.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

《javascript入门经典》摘录

JavaScript中可以对内建对象进行扩展。 <html> <head><title>Test of heading method</title> </head> <body> <script LANGUAGE="JavaScript" type="text/javascript"> function addhead (level) { html = "H" + level; text = this.toString(); start = "<" + html + ">"; stop = "</" + html + ">"; return start + text + stop; } String.prototype.heading = addhead; document.write ("This is a heading 1".heading(1)); document.write ("This is a heading 2".heading(2)); document.write ("This is a heading 3".heading(3)); </script> </body> </html> 1,Prototype Prototype is free, open-source software. You can download it from its official website at http://prototype.conio.net/. Prototype is also built into the Ruby on Rails framework for the server-side language Rubysee http://www.rubyonrails.com/ for more information. 2,Script.aculo.us Script.aculo.us by Thomas Fuchs is one such library. It includes functions to simplify drag-and-drop tasks, such as rearranging lists of items. It also includes a number of Combination Effects, which enable you to use highlighting and animated transitions within your pages. 3,AJAX Frameworks The Prototype library, described previously, includes AJAX features. There are also many dedicated AJAX libraries. One of the most popular is SAJAX (Simple AJAX), an open-source toolkit that makes it easy to use AJAX to communicate with PHP, Perl, and other languages from JavaScript. Visit the SAJAX website for details at http://www.modernmethod.com/sajax. 4,Dojo (http://www.dojotoolkit.org/) is an open-source toolkit that adds power to JavaScript to simplify building applications and user interfaces. It adds features ranging from extra string and math functions to animation and AJAX. 5, The Yahoo! UI Library (http://developer.yahoo.net/yui/) was developed by Yahoo! and made available to everyone under an open-source license. It includes features for animation, DOM features, event management, and easy-to-use user interface elements such as calendars and sliders. 6, MochiKit (http://mochikit.com/) is a lightweight library that adds features for working with the DOM, CSS colors, string formatting, and AJAX. It also supports a nice logging mechanism for debugging your scripts. 本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2007/05/12/744215.html,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册