
善于分享,乐于分享
暂时未有相关通用技术能力~
阿里云技能认证
详细说明北京Java笔试题整理 1、什么是java虚拟机?为什么ava被称作是“平台无关的编程语言? 答:Java虚拟机可以理解为一个特殊的“操作系统”,只是它连接的不是硬件,而是一般的操作系统和java程序。 正是因为有这样一层操作系统与程序之间的连接,Java程序就能在一台机子上编译后到处都能运行——只要有对应不同系统的Java虚拟机就可以了。因此Java被称为“平台无关”。 Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 2、关键字是什么意思?Java中是否可以覆盖或者static的方法? 答:static表示静态的意义,它可以修饰一个变量,一个方法,被其修饰的变量被称为类变量,被其修饰的方法成为类方法,其随着类的加载而被加载。 无法重写被private修饰的方法,因为被private修饰的父类方法在子类中是不可见的。 static修饰的方法是静态绑定的,而方法覆盖是为了实现多态,是动态绑定,所以static修饰的方法不需要被覆盖 3、是否可以在static环境中访问非static变量? 答:不能。 static变量在java中是属于类的,在类的所有实例中,它的值都是一样的。在类被JVM载入时,静态变量的值就确定了。 而非静态变量是属于实例的,要在new一个实例之后,值才会存在。 在static环境中,调用非static变量,可能这个变量都还不存在,当然会出错。 4、java支持的数据类型有哪些?什么是自动拆装箱? 答:Java语言支持的8中基本数据类型是: byte short int long float double boolean char 自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成Integer,double转化成double,等等。反之就是自动拆箱。 5、Java中的方法覆盖和方法重载是什么意思? 答:重载: 在一个类当中才可以重载,方法名相同,参数个数不同或参数个数相同而参数类型不同。 覆盖: 又称重写,在派生类(子类)中重写基类(父类)的方法,名称、参数、类型都必须相同。 6、Java中,什么是构造函数?什么是构造函数重载?什么是赋值构造函数? 答:当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。 Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。 Java不支持像C++中那样的赋值构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的赋值构造函数。 7、Java支持多继承吗? 答: Java中类不支持多继承,只支持单继承(即一个类只有一个父类)。 但是java中的接口可以间接实现多继承,,即一个子接口可以有多个父接口。(接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)。 8、进程和线程的区别是什么? 答:1)进程是什么? 是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独 立运行的一段程序。 2)线程又是什么? 线程进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。 在运行时,只是暂用一些计数器、寄存器和栈 。二、他们之间的关系 3)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(通常说的主线程)。 9、什么是值传递和引用传递? 答:值传递 指的是在方法调用时,传递的参数是按值的拷贝传递。 引用传递 指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。 10、创建线程有几种方式?你喜欢哪一种?为什么? 答:链接:https://www.nowcoder.com/questionTerminal/e33c72bceb4343879948342e2b6e3bca?pos=48&mutiTagIds=570&orderByHotValue=1 来源:牛客网 1)继承Thread类(真正意义上的线程类),是Runnable接口的实现。 2)实现Runnable接口,并重写里面的run方法。 3)通过Callable接口实现多线程,重写call方法,优点是可以获取返回值,确定是比较繁琐 4)使用Executor框架创建线程池。Executor框架是juc里提供的线程池的实现。 调用线程的start():启动此线程;调用相应的run()方法 继承于Thread类的线程类,可以直接调用start方法启动线程(使用static也可以实现资源共享).一个线程(对象)只能够执行一次start(),而且不能通过Thread实现类对象的run()去启动一个线程。 实现Runnable接口的类需要再次用Thread类包装后才能调用start方法。(三个Thread对象包装一个类对象,就实现了资源共享)。 线程的使用的话,注意锁和同步的使用。(多线程访问共享资源容易出现线程安全问题) 一般情况下,常见的是第二种。 Runnable接口有如下好处: *①避免点继承的局限,一个类可以继承多个接口。 *②适合于资源的共享 11、概括的解释下线程的几种可用状态? 答: 新建( new ):新创建了一个线程对象。 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获 取 cpu 的使用权 。 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。阻塞的情况分三种: (一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。 (二). 同步阻塞:运行( running )的线程在获取对象的同步锁时,若该同步锁 被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。 (三). 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。 当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生 12、同步方法和同步代码块的区别是什么? 答: 同步方法:(粗粒度锁): 1.修饰一般方法: public synchronized void method (){...},获取的是当前调用 对象this上的锁 2.修饰静态方法: public static synchronized void method (){...},获取当前类的 字节码对象上的锁 ③同步代码块(细粒度锁): synchronized ( obj ) {...},同步代码块可以指定获取哪个对象上的锁。 13、什么是死锁? 答:所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 14、为什么Java集合类没有实现Cloneable和Serializable接口? 答:克隆(cloning)或者序列化(serialization)的语义和含义是跟具体的实现相关的。因此应该由集合类的具体实现类来决定如何被克隆或者序列化 15、Java集合类框架的基本接口有哪些? 答: 1)总共有两大接口:Collection 和Map ,一个元素集合,一个是键值对集合; 其中List和Set接口继承了Collection接口,一个是有序元素集合,一个是无序元素集合; 而ArrayList和 LinkedList 实现了List接口,HashSet实现了Set接口,这几个都比较常用; HashMap 和HashTable实现了Map接口,并且HashTable是线程安全的,但是HashMap性能更好; 2) Java集合类里最基本的接口有: Collection:单列集合的根接口 List:元素有序 可重复 ArrayList:类似一个长度可变的数组 。适合查询,不适合增删 LinkedList:底层是双向循环链表。适合增删,不适合查询。 Set:元素无序,不可重复 HashSet:根据对象的哈希值确定元素在集合中的位置 TreeSet: 以二叉树的方式存储元素,实现了对集合中的元素排序 Map:双列集合的根接口,用于存储具有键(key)、值(value)映射关系的元素。 HashMap:用于存储键值映射关系,不能出现重复的键key TreeMap:用来存储键值映射关系,不能出现重复的键key,所有的键按照二叉树的方式排列 16、什么是迭代器? 答: 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。 Java中的Iterator功能比较简单,并且只能单向移动: 17、Iterator和Listiterator的区别是什么? 答:一.相同点 都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。 二.不同点 1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。 2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。 3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。 4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。 5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。 18、Java中的Hashmap的工作原理是什么? 答:java8对hashmap做了优化 ,底层有两种实现方法,一种是数组和链表,一种是数组和红黑树,hsahmap会根据数据量选择存储结构 if (binCount >= TREEIFY_THRESHOLD - 1) 当符合这个条件的时候,把链表变成treemap,这样查找效率从o(n)变成了o(log n) 19、hashcode()和equals()方法的重要性体现在什么地方? 答:Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。 20、Hashmap和Hashtable有什么区别? 答: HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。 HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。 HashMap不能保证随着时间的推移Map中的元素次序是不变的 21、数组((Array)和列表(ArrayList)有什么区别?什么时候应该使用Arrayi不是Arraylist? 答: 数据类型方面: Array数据可以是基本类型何包装类型,ArrayList只能是包装类型. 容量方面:Array容量是静态固定的,ArrayList是动态变化的。 支持操作:ArrayList提供更多操作,Array提供的更多依赖于Arrays提供的方法。 使用建议:如果你的操作对象是基本型别,而且需要在空间不足时自动扩增容量,Array便不适合,此时就得使用外覆类的容器了。 ArrayList存入对象时,抛弃类型信息,所有对象屏蔽为Object,编译时不检查类型,但是运行时会报错。 基于效率和类型检验,应尽可能使用Array,无法确定数组大小时才使用ArrayList! 22、Arraylist和Linkedlist有什么区别? 答:1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 23、Comparable和Comparator接口是干什么的?列出它们的区别? 答: Comparatable接口必须由需要排序的多元素类本身来实现,且在其内部重写comparaTo()方法;Comparator接口是在需要排序的多元素类的外部(即使用外部类)来实现,且必须在该外部类中重写compara()方法。 两者的比较 comparable接口: 优点:对于单元素集合可以实现直接排序 缺点:对于多元素排序,排序依据是固定不可更改的。(元素内部只能实现一次compareTo方法) comparator接口: 元素的排序依据时刻变的,所以可以通过定义多个外部类的方式来实现不同的排序。使用时按照需求选取。 创建外部类的代价太大。 24、Java中垃圾回收有什么目的?什么时候进行垃圾回收? 答: 目的:回收堆内存中不再使用的对象,释放资源 回收时间:当对象永久地失去引用后,系统会在合适的时候回收它所占的内存 垃圾回收的目的是回收堆中已经不在被使用的对象。垃圾回收机制是一个守护线程,优先级别低,其在当前服务器空闲或堆中老年代等占用率较大时触发。 若转载请注明出处!若有疑问,请回复交流!
Linux下tomcat服务的启动、关闭与错误跟踪,通常通过以下几种方式启动关闭tomcat服务: 切换到tomcat主目录下的bin目录 启动tomcat服务 生产模式: 方式一:直接启动 ./startup.sh 方式二:作为服务启动 nohup ./startup.sh & 开发者模式: 方式三:控制台动态输出方式启动 ./catalina.sh run 动态地显示tomcat后台的控制台输出信息,Ctrl+C后退出并关闭服务 解释: 通过方式一、方式三启动的tomcat有个弊端,当客户端连接断开的时候,tomcat服务也会立即停止,通过方式二可以作为linux服务一直运行 通过方式一、方式二方式启动的tomcat,其日志会写到相应的日志文件中,而不能动态地查看tomcat控制台的输出信息与错误情况,通过方式三可以以控制台模式启动tomcat服务, 直接看到程序运行时后台的控制台输出信息,不必每次都要很麻烦的打开catalina.out日志文件进行查看,这样便于跟踪查阅后台输出信息。tomcat控制台信息包括log4j和System.out.println()等输出的信息。 关闭tomcat服务 生产模式下: ./shutdown.sh 开发者模式: Ctrl+C后退出并关闭服务 若转载请注明出处!若有疑问,请回复交流!
在配置nginx 虚拟机时,执行 sudo /usr/sbin/nginx -t 报下面的错误: nginx: [emerg] "root" directive is duplicate in /etc/nginx/server/blogs.conf:107 nginx: configuration file /etc/nginx/nginx.conf test failed 错误原因是:在配置文件时,访问路径设置了两个,重复配置webroot路径导致,去掉一个就可以了。 server { listen 80 default_server; #root /usr/share/nginx/html/;去掉这行 index index.html index.htm; # Make site accessible from http://localhost/ root /home/wangkongming/webroot/blogs; index index.html index.htm; server_name blogs.local; location / { try_files $uri $uri/ =404; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } access_log /data/logs/blogs/access.log; error_log /data/logs/blogs/error.log; } 转自:https://www.cnblogs.com/wangkongming/p/4290520.html
SpringMvc支持跨域访问,Spring跨域访问,SpringMvc @CrossOrigin 跨域 原文地址:https://www.cnblogs.com/fanshuyao/p/7168471.html ©Copyright 蕃薯耀 2017年7月14日 http://www.cnblogs.com/fanshuyao/ 一、SpringMvc跨域支持 从Spring MVC 4.2 开始增加支持跨域访问 二、使用方法 1、某个方法支持跨域访问 在方法上增加@CrossOrigin注解,如下: Java代码 @RequestMapping("/crossDomain2") @ResponseBody @CrossOrigin public String crossDomain2(HttpServletRequest req, HttpServletResponse res, String name){ …… …… }其中@CrossOrigin中的2个参数: origins : 允许可访问的域列表 Java代码 List of allowed origins, e.g. "http://domain1.com". These values are placed in the Access-Control-Allow-Origin header of both the pre-flight response and the actual response. "*" means that all origins are allowed. If undefined, all origins are allowed. maxAge:飞行前响应的缓存持续时间的最大年龄(以秒为单位)。 Java代码 The maximum age (in seconds) of the cache duration for pre-flight responses. This property controls the value of the Access-Control-Max-Age header in the pre-flight response. Setting this to a reasonable value can reduce the number of pre-flight request/response interactions required by the browser. A negative value means undefined. If undefined, max age is set to 1800 seconds (i.e., 30 minutes). 2、整个Controller都支持跨域访问,在类上面加上注解@CrossOrigin,如下: Java代码 @Controller @CrossOrigin public class TestController { …… …… } 3、自定义规则支持全局跨域访问,在spring-mvc.xml文件中配置映射路径,如下: Java代码 如果整个项目所有方法都可以访问,则可以这样配置 Xml代码 其中* 表示匹配到下一层 ** 表示后面不管有多少层,都能匹配。 如: Java代码 这个可以匹配到的路径有: /cross/aaa /cross/bbbb 不能匹配的: /corss/aaa/bbb 因为* 只能匹配到下一层路径,如果想后面不管多少层都可以匹配,配置如下: Xml代码 就是一颗星(*) 变成两颗星(**) 上面表示有/cross/路径的请求都支持跨域访问,也可以增加其它的,如下: Java代码 请求路径有/cross/,方法示例如下: Java代码 @RequestMapping("/cross/crossDomain") @ResponseBody public String crossDomain(HttpServletRequest req, HttpServletResponse res, String name){ …… …… } 官方文档见:http://spring.io/blog/2015/06/08/cors-support-in-spring-framework 或者见附件的图片附件:CORS support in Spring Framework.png 若转载请注明出处!若有疑问,请回复交流!
将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id". $将传入的数据直接显示生成在sql中。如:order by \(user_id\),如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id. 方式能够很大程度防止sql注入。 4.$方式无法防止Sql注入。 5.\(方式一般用于传入数据库对象,例如传入表名. 6.一般能用#的就别用\). MyBatis排序时使用order by 动态参数时需要注意,用$而不是# 字符串替换 默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDER BY,你可以这样来使用: ORDER BY ${columnName} 这里MyBatis不会修改或转义字符串。 重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。 转自:http://weijun726.blog.163.com/blog/static/87342299201362652950398/ 若转载请注明出处!若有疑问,请回复交流!
Spring官网改版后,很多项目的完整zip包下载链接已经隐掉了,虽然Spring旨在引导大家用更“高大上”的maven方式来管理所依赖的jar包,但是完全没想到中国的国情,在伟大的墙内,直接通过maven下载墙外的东西,要么龟速,要么直接被和谐。 下面是从网上搜集的一些方法,可用于一次性下载Spring各项目的完整dist.zip 第一种 直接 http://repo.springsource.org/libs-release-local/org/springframework/spring/3.2.8.RELEASE/spring-framework-3.2.8.RELEASE-dist.zip http://repo.spring.io/libs-release-local/org/springframework/security/spring-security/3.2.3.RELEASE/spring-security-3.2.3.RELEASE-dist.zip 直接粘到地址栏或者下载工具里,每次有更新只要改版本号就可以; 第二种http://repo.springsource.org/libs-release-local/ 把这个粘到地址栏里,你会看到一个树型目录,然后就是一级一级往下点了; 第三种 你要在官网的projects里找到spring framework,然后左侧的"小猫"图标,跳到github,在Downloading artifacts下面 找到 building a distribution with dependencies的超链,进去后再找 到 the SpringSource repository的超链,接着打开Spring repository FAQ后,找到libs- release-local,进去后点Artifacts页签,再在左边的列表里先simple brower,后面的流程和第二步一样。(不过,Github在墙内很不稳定,你懂的。。。) 第四种 http://repo.spring.io/webapp/search/artifact/?0&q=spring-framework 或 http://repo.spring.io/webapp/search/artifact/?0&q=spring-security 把q后的关键字换成Spring子项目的名称即可 若转载请注明出处!若有疑问,请回复交流!
FastDFS是国人开发的一款分布式文件系统,目前社区比较活跃。系统中存在三种节点:Client、Tracker、Storage,在底层存储上通过逻辑的分组概念,使得通过在同组内配置多个Storage,从而实现软RAID10,提升简单负载均衡、并发IO的性能、及数据的冗余备份;同时通过线性的添加新的逻辑存储组,从容实现存储容量的线性扩容。 文件下载上,除了支持通过API方式,目前还提供了apache和nginx的插件支持,同时也可以不使用对应的插件,直接以Web静态资源方式对外提供下载。目前FastDFS(V4.x)代码量大概6w多行,内部的网络模型使用比较成熟的libevent三方库,具备高并发的处理能力。 特性 1)在上述介绍中Tracker服务器是整个系统的核心枢纽,其完成了访问调度(负载均衡),监控管理Storage服务器,由此可见Tracker的作用至关重要,也就增加了系统的单点故障,为此FastDFS支持多个备用的Tracker,虽然实际测试发现备用Tracker运行不是非常完美,但还是能保证系统可用。 2)在文件同步上,只有同组的Storage才做同步,由文件所在的源Storage服务器push至其它Storage服务器,目前同步是采用Binlog方式实现,由于目前底层对同步后的文件不做正确性校验,因此这种同步方式仅适用单个集群点的局部内部网络,如果在公网上使用,肯定会出现损坏文件的情况,需要自行添加文件校验机制。 3)支持主从文件,非常适合存在关联关系的图片,在存储方式上,FastDFS在主从文件ID上做取巧,完成了关联关系的存储。 优点 1)系统无需支持POSIX(可移植操作系统),降低了系统的复杂度,处理效率更高 2)支持在线扩容机制,增强系统的可扩展性 3)实现了软RAID,增强系统的并发处理能力及数据容错恢复能力 4)支持主从文件,支持自定义扩展名 5)主备Tracker服务,增强系统的可用性 缺点 1)不支持断点续传,对大文件将是噩梦(FastDFS不适合大文件存储) 2)不支持POSIX通用接口访问,通用性较低 3)对跨公网的文件同步,存在较大延迟,需要应用做相应的容错策略 4)同步机制不支持文件正确性校验,降低了系统的可用性 5)通过API下载,存在单点的性能瓶颈 问题分析: 从FastDFS的整个设计看,基本上都已简单为原则。比如以机器为单位备份数据,简化了tracker的管理工作;storage直接借助本地文件系统原样存储文件,简化了storage的管理工作;文件写单份到storage即为成功、然后后台同步,简化了写文件流程。但简单的方案能解决的问题通常也有限,FastDFS目前尚存在如下问题: 数据安全性: >写一份即成功:从源storage写完文件至同步到组内其他storage的时间窗口内,一旦源storage出现故障,就可能导致用户数据丢失,而数据的丢失对存储系统来说通常是不可接受的。 缺乏自动化恢复机制:当storage的某块磁盘故障时,只能换存磁盘,然后手动恢复数据;由于按机器备份,似乎也不可能有自动化恢复机制,除非有预先准备好的热备磁盘,缺乏自动化恢复机制会增加系统运维工作。 数据恢复效率低:恢复数据时,只能从group内其他的storage读取,同时由于小文件的访问效率本身较低,按文件恢复的效率也会很低,低的恢复效率也就意味着数据处于不安全状态的时间更长。 缺乏多机房容灾支持:目前要做多机房容灾,只能额外使用工具来将数据同步到备份的集群,无自动化机制。 存储空间利用率: 单机存储的文件数受限于inode数量 每个文件对应一个storage本地文件系统的文件,平均每个文件会存在block_size/2的存储空间浪费。 文件合并存储能有效解决上述两个问题,但由于合并存储没有空间回收机制,删除文件的空间不保证一定能复用,也存在空间浪费的问题 负载均衡: group机制本身可用来做负载均衡,但这只是一种静态的负载均衡机制,需要预先知道应用的访问特性;同时group机制也导致不可能在group之间迁移数据来做动态负载均衡 若转载请注明出处!若有疑问,请回复交流!
端口开放 这是命令运行的前提 iptables -I INPUT -p tcp -m state –state NEW -m tcp –dport 22 -j ACCEPT iptables -I INPUT -p tcp -m state –state NEW -m tcp –dport 23000 -j ACCEPT iptables -I INPUT -p tcp -m state –state NEW -m tcp –dport 80 -j ACCEPT 日常命令 如何重启server进程 直接使用如下命令 /usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf restart 也可以使用FastDFS自带的restart.sh脚本 /usr/local/bin/restart.sh /usr/local/bin/fdfs_tracked /home/yuqing/FastDFS/conf/tracker.conf /usr/local/bin/restart.sh /usr/local/bin/fdfs_storaged /home/yuqing/FastDFS/conf/storage.conf 如何让server进程退出运行 直接kill即可让server进程正常退出,可以使用killall命令,例如: killall fdfs_trackerd killall fdfs_storaged 也可以使用如下命令: /usr/local/bin/fdfs_trackerd /etc/fdfs/tracker.conf stop /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf stop 千万不要使用-9参数强杀,否则可能会导致binlog数据丢失的问题。 也可以使用FastDFS自带的stop.sh脚本 /usr/local/bin/stop.sh /usr/local/bin/fdfs_tracked /home/yuqing/FastDFS/conf/tracker.conf /usr/local/bin/stop.sh /usr/local/bin/fdfs_storaged /home/yuqing/FastDFS/conf/storage.conf fdfs_test和fdfs_test1是做什么用的 这两个是FastDFS自带的测试程序,会对一个文件上传两次,分别作为主文件和从文件。返回的文件ID也是两个。 并且会上传文件附加属性,storage server上会生成4个文件。 /usr/local/bin/fdfs_test upload 这两个程序仅用于测试目的,请不要用作实际用途 下载文件 /usr/bin/fdfs_download_file [local_filename] 删除文件 /usr/bin/fdfs_delete_file 节点监控 fdfs_monitor /etc/fdfs/client.conf storage server 状态操作 STORAGE SERVER的状态通常有七种: # FDFS_STORAGE_STATUS:INIT :初始化,尚未得到同步已有数据的源服务器 # FDFS_STORAGE_STATUS:WAIT_SYNC :等待同步,已得到同步已有数据的源服务器 # FDFS_STORAGE_STATUS:SYNCING :同步中 # FDFS_STORAGE_STATUS:DELETED :已删除,该服务器从本组中摘除 # FDFS_STORAGE_STATUS:OFFLINE :离线 # FDFS_STORAGE_STATUS:ONLINE :在线,尚不能提供服务 # FDFS_STORAGE_STATUS:ACTIVE :在线,可以提供服务 正常状态必须是ACTIVE,如果运行以下命令 fdfs_monitor /etc/fdfs/client.conf 发现有以下状态的服务器 Storage 4: ip_addr = 10.120.151.114 WAIT_SYNC #从集群中删除 fdfs_monitor /etc/fdfs/client.conf delete group1 10.120.151.114 #在114服务器中,删除数据文件夹 rm -rf /home/storage1/fastdfs/data #重启114节点 fdfs_storaged /etc/fdfs/storage.conf 重新查状态 fdfs_monitor /etc/fdfs/client.conf 概念 什么是主从文件 主从文件是指文件ID有关联的文件,一个主文件可以对应多个从文件。 主文件ID = 主文件名 + 主文件扩展名 从文件ID = 主文件名 + 从文件后缀名 + 从文件扩展名 使用主从文件的一个典型例子:以图片为例,主文件为原始图片,从文件为该图片的一张或多张缩略图。 FastDFS中的主从文件只是在文件ID上有联系。FastDFS server端没有记录主从文件对应关系,因此删除主文件,FastDFS不会自动删除从文件。 删除主文件后,从文件的级联删除,需要由应用端来实现。 主文件及其从文件均存放到同一个group中。 主从文件的生成顺序: 1)先上传主文件(如原文件),得到主文件ID 2)然后上传从文件(如缩略图),指定主文件ID和从文件后缀名(当然还可以同时指定从文件扩展名),得到从文件ID 若转载请注明出处!若有疑问,请回复交流!
1: 启动FastDFS tracker: /usr/local/bin/fdfs_trackered /etc/fdfs/tracker.conf storage: /usr/local/bin/fdfs_storaged /etc/fdfs/storage.conf 2:关闭FastDFS tracker:/usr/local/bin/stop.sh /usr/local/bin/fdfs_tracker storage:/usr/local/bin/stop.sh /usr/local/bin/fdfs_storage 或者 killall fdfs_trackered(storaged) -------注意,千万不要使用-9强行杀死进程。 3:重启FastDFS tracker:/usr/local/bin/restart.sh /usr/local/bin/fdfs_trackered storage:/usr/local/bin/restart.sh /usr/local/bin/fdfs_storaged 4:查看集群情况 在任意一台storage(tracker也可以) /usr/local/bin/fdfs_monitor /etc/fdfs/storage.conf 5:删除一个storage: 在任意一台storage(tracker也可以) /usr/local/bin/fdfs_monitor /etc/fdfs/storage.conf delete group2 20.12.1.73 若转载请注明出处!若有疑问,请回复交流!
启动 启动代码格式:nginx安装目录地址 -c nginx配置文件地址 例如: [root@LinuxServer sbin]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 停止 nginx的停止有三种方式: 从容停止 1、查看进程号 [root@LinuxServer ~]# ps -ef|grep nginx 2、杀死进程 [root@LinuxServer ~]# kill -QUIT 2072 快速停止 1、查看进程号 [root@LinuxServer ~]# ps -ef|grep nginx 2、杀死进程 [root@LinuxServer ~]# kill -TERM 2132 或 [root@LinuxServer ~]# kill -INT 2132 强制停止 [root@LinuxServer ~]# pkill -9 nginx 重启 1、验证nginx配置文件是否正确 方法一:进入nginx安装目录sbin下,输入命令./nginx -t 看到如下显示nginx.conf syntax is ok nginx.conf test is successful 说明配置文件正确! 方法二:在启动命令-c前加-t 2、重启Nginx服务 方法一:进入nginx可执行目录sbin下,输入命令./nginx -s reload 即可 方法二:查找当前nginx进程号,然后输入命令:kill -HUP 进程号 实现重启nginx服务 若转载请注明出处!若有疑问,请回复交流!
正则表达式——古老而又强大的文本处理工具。仅用一段简短的表达式语句,就能快速地实现一个复杂的业务逻辑。掌握正则表达式,让你的开发效率有一个质的飞跃。 正则表达式经常被用于字段或任意字符串的校验,比如下面这段校验基本日期格式的JavaScript代码: var reg = /^(\\d{1,4})(-|\\/)(\\d{1,2})\\2(\\d{1,2})$/; var r = fieldValue.match(reg); if(r==null)alert('Date format error!'); 1、校验密码强度 密码的强度必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间 ^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ 2、校验中文 字符串只能是中文 ^[\\u4e00-\\u9fa5]{0,}$ 3、由数字,26个英文字母或下划线组成的字符串 ^\\w+$ 4、校验E-Mail 地址 [\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])? 5、校验身份证号码 15位: ^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$ 18位: ^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$ 6、校验日期 “yyyy-mm-dd“ 格式的日期校验,已考虑平闰年 ^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$ 7、校验金额 金额校验,精确到2位小数 ^[0-9]+(.[0-9]{2})?$ 8、校验手机号 下面是国内 13、15、18开头的手机号正则表达式 ^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$ 9、判断IE的版本 ^.*MSIE [5-8](?:\\.[0-9]+)?(?!.*Trident\\/[5-9]\\.0).*$ 10、校验IP-v4地址 \\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b 11、校验IP-v6地址 (([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])) 12、检查URL的前缀 if (!s.match(/^[a-zA-Z]+:\\/\\//)){ s = 'http://' + s;} 13、提取URL链接 ^(f|ht){1}(tp|tps):\\/\\/([\\w-]+\\.)+[\\w-]+(\\/[\\w- ./?%&=]*)? 14、文件路径及扩展名校验 ^([a-zA-Z]\\:|\\\\)\\\\([^\\\\]+\\\\)*[^\\/:*?"<>|]+\\.txt(l)?$ 15、提取Color Hex Codes ^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$ 16、提取网页图片 \\< *[img][^\\\\>]*[src] *= *[\\"\\']{0,1}([^\\"\\'\\ >]*) 17、提取页面超链接 (<a\\s*(?!.*\\brel=)[^>]*)(href="https?:\\/\\/)((?!(?:(?:www\\.)?'.implode('|(?:www\\.)?', $follow_list).'))[^"]+)"((?!.*\\brel=)[^>]*)(?:[^>]*)> 18、查找CSS属性 ^\\s*[a-zA-Z\\-]+\\s*[:]{1}\\s[a-zA-Z0-9\\s.#]+[;]{1} 19、抽取注释 <!--(.*?)--> 20、匹配HTML标签 <\\/?\\w+((\\s+\\w+(\\s*=\\s*(?:".*?"|'.*?'|[\\^'">\\s]+))?)+\\s*|\\s*)\\/?>若转载请注明出处!若有疑问,请回复交流!
MongoDB之Java测试代码(DAO层),mongodbdao MongoInit.java是数据库初始化及连接类 MongoUtils.java是对mongodb的各种操作方法 MongoInit.java package com.wlwcloud.datatest; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.UnknownHostException; import java.util.Properties; import org.apache.log4j.Logger; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.Mongo; import com.mongodb.MongoOptions; import com.mongodb.ServerAddress; /** * Mongo工具类:设计为单例模式,每当月份发生变化,数据库连接名称就会发生变化,这是业务规则 因MongoDB的Java驱动是线程安全的,对于一般的应用,只要一个Mongo实例即可,Mongo有个内置的连接池(池大小默认为10个)。 * 对于有大量写和读的环境中,为了确保在一个Session中使用同一个DB时,我们可以用以下方式保证一致性: DB mdb =mongo.getDB('dbname'); mdb.requestStart(); // 业务代码 mdb.requestDone(); * DB和DBCollection是绝对线程安全的 * @author undoner */ public class MongoInit { /** DB监听端口号 */ private static int DBPort = 27017; /** DB连接URL */ private static String DBUrl = "localhost"; /** 连接DB库名称 */ private static String DBName = "wlwdb"; static Logger log = Logger.getRootLogger(); private static Mongo mongo; private static DBCollection coll; private static DB db; static { try { DBproperties(); MongoOptions options = new MongoOptions(); options.autoConnectRetry = true; options.connectionsPerHost = 1000; options.maxWaitTime = 5000; options.socketTimeout = 0; options.connectTimeout = 15000; options.threadsAllowedToBlockForConnectionMultiplier = 5000; // 事实上,Mongo实例代表了一个数据库连接池,即使在多线程的环境中,一个Mongo实例对我们来说已经足够了 ServerAddress serverAddress = new ServerAddress(DBUrl, DBPort); mongo = new Mongo(serverAddress, options); } catch (UnknownHostException e) { log.info("get mongo instance failed"); } } static void DBproperties() { // 读取配置文件config.properties中的属性值 String myFilePath = MongoInit.class.getResource("/").getPath() + "MongoDBConfig.properties"; Properties properties = new Properties(); FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(myFilePath); properties.load(fileInputStream); DBPort = Integer.parseInt((String) properties.getProperty("DBPort")); DBUrl = (String) properties.getProperty("DBUrl"); DBName = (String) properties.getProperty("DBName"); } catch (Exception e) { e.printStackTrace(); } finally { try { fileInputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static DB getDB() { if (db == null) { db = mongo.getDB(DBName); } return db; } public static Mongo getMong() { return mongo; } public static DBCollection getColl(String collname) { return getDB().getCollection(collname); } } MongoUtils.java package com.wlwcloud.datatest; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.ketayao.ketacustom.entity.main.User; import com.ketayao.utils.SecurityUtils; import com.mongodb.AggregationOutput; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MapReduceCommand; import com.mongodb.MapReduceOutput; import com.mongodb.Mongo; import com.mongodb.MongoException; import com.mongodb.QueryBuilder; import com.mongodb.WriteConcern; public class MongoUtils { //DBCursor cursor = coll.find(condition).addOption(Bytes.QUERYOPTION_NOTIMEOUT);//设置游标不要超时 /** * 获取所有数据库实例 */ public void testGetDBS() { List<String> dbnames = MongoInit.getMong().getDatabaseNames(); for (String dbname : dbnames) { System.out.println("dbname:" + dbname); } } /** * 删除数据库 */ public void dropDatabase(String dbname) { MongoInit.getMong().dropDatabase(dbname); } /** * 查询所有表名 */ public void getAllCollections() { Set<String> colls = MongoInit.getDB().getCollectionNames(); for (String s : colls) { System.out.println("Collections:"+s); } } /** * 删除一个表 */ public void dropCollection(String collection) { MongoInit.getColl(collection).drop(); } /** * 添加一条记录 */ public void addData(String dbCollection,String dataID,String dataTime,String dataContent,String dataStatus) { DBCollection coll = MongoInit.getColl(dbCollection); BasicDBObject doc = new BasicDBObject(); doc.put("id", dataID); doc.put("time", dataTime); doc.put("data", dataContent); doc.put("status", dataStatus); coll.insert(doc); // 设定write concern,以便操作失败时得到提示 coll.setWriteConcern(WriteConcern.SAFE); findOne(dbCollection); } /** * 创建索引 */ public void createIndex(String collection) { MongoInit.getColl(collection).createIndex(new BasicDBObject("index_id", 1)); } /** * 获取索引信息 */ public void getIndexInfo(String dbCollection) { List<DBObject> list = MongoInit.getColl(dbCollection).getIndexInfo(); for (DBObject o : list) { System.out.println(o); } } /** * 添加多条记录 */ public void addMultiData() { for (int i = 0; i < 100; i++) { MongoInit.getColl("wujintao").insert( new BasicDBObject().append("i", i)); } List<DBObject> docs = new ArrayList<DBObject>(); for (int i = 0; i < 50; i++) { docs.add(new BasicDBObject().append("i", i)); } MongoInit.getColl("wujintao").insert(docs); // 设定write concern,以便操作失败时得到提示 MongoInit.getColl("wujintao").setWriteConcern(WriteConcern.SAFE); } /** * 查找第一条记录 */ public void findOne(String dbCollection) { DBObject myDoc = MongoInit.getColl(dbCollection).findOne(); System.out.println(myDoc); } /** * 获取表中所有记录条数 */ public void count(String dbCollection) { System.out.println(MongoInit.getColl(dbCollection).getCount()); System.out.println(MongoInit.getColl(dbCollection).count()); } /** * 获取查询结果集的记录数 */ public void getCount(String dbCollection,String dataID) { DBObject query = new BasicDBObject("id", dataID); long count = MongoInit.getColl(dbCollection).count(query); System.out.println(count); } /** * 查询所有结果 */ public void getAllDocuments(String dbCollection) { DBCursor cursor = MongoInit.getColl(dbCollection).find(); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } /** * 按照一个条件查询 */ public void queryByConditionOne() { BasicDBObject query = new BasicDBObject(); query.put("name", "MongoDB"); DBCursor cursor = MongoInit.getColl("wujintao").find(query); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } public List<SensorData> queryById(String id) { User user = SecurityUtils.getLoginUser(); BasicDBObject query = new BasicDBObject(); System.out.print(id); query.put("id", id); String table="table_"; DBCursor cursor = MongoInit.getColl("table_"+user.getUsername()).find(query); List<DBObject> list=cursor.toArray(); System.out.println(list.size()); System.out.println("dao.."+list.toString()); List<SensorData> sensordata=new ArrayList<SensorData>(); for(int i=1;i<list.size();i++) { String sid=(String)list.get(i).get("id"); String stime=(String)list.get(i).get("time"); String sdata=(String)list.get(i).get("data"); String status=(String)list.get(i).get("status"); String sstatus; if(status.equals("0"))sstatus="正常"; else if(status.equals("1")) sstatus="删除"; else sstatus="未知状态"; SensorData a=new SensorData(sid,stime,sdata,sstatus); //System.out.print(a.getData()+a.getId()+a.getStatus()+a.getTime()); sensordata.add(a); } return sensordata; /* try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } */ } /** * AND多条件查询,区间查询 */ public void queryMulti() { BasicDBObject query = new BasicDBObject(); // 查询j不等于3,k大于10的结果集 query.put("j", new BasicDBObject("$ne", 3)); query.put("k", new BasicDBObject("$gt", 10)); DBCursor cursor = MongoInit.getColl("wujintao").find(query); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } /** * 区间查询 * select * from table where i >50 */ public void queryMulti2() { BasicDBObject query = new BasicDBObject(); query = new BasicDBObject(); query.put("i", new BasicDBObject("$gt", 50)); // e.g. find all where i > DBCursor cursor = MongoInit.getColl("wujintao").find(query); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } /** * 区间查询 * select * from table where 20 < i <= 30 //比较符 //"$gt": 大于 //"$gte":大于等于 //"$lt": 小于 //"$lte":小于等于 //"$in": 包含 */ public void queryMulti3() { BasicDBObject query = new BasicDBObject(); query = new BasicDBObject(); query.put("i", new BasicDBObject("$gt", 20).append("$lte", 30)); DBCursor cursor = MongoInit.getColl("wujintao").find(query); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } /** * 组合in和and select * from test_Table where (a=5 or b=6) and (c=5 or d = 6) */ public void queryMulti4() { BasicDBObject query11 = new BasicDBObject(); query11.put("a", 1); BasicDBObject query12 = new BasicDBObject(); query12.put("b", 2); List<BasicDBObject> orQueryList1 = new ArrayList<BasicDBObject>(); orQueryList1.add(query11); orQueryList1.add(query12); BasicDBObject orQuery1 = new BasicDBObject("$or", orQueryList1); BasicDBObject query21 = new BasicDBObject(); query21.put("c", 5); BasicDBObject query22 = new BasicDBObject(); query22.put("d", 6); List<BasicDBObject> orQueryList2 = new ArrayList<BasicDBObject>(); orQueryList2.add(query21); orQueryList2.add(query22); BasicDBObject orQuery2 = new BasicDBObject("$or", orQueryList2); List<BasicDBObject> orQueryCombinationList = new ArrayList<BasicDBObject>(); orQueryCombinationList.add(orQuery1); orQueryCombinationList.add(orQuery2); BasicDBObject finalQuery = new BasicDBObject("$and", orQueryCombinationList); DBCursor cursor = MongoInit.getColl("wujintao").find(finalQuery); } /** * IN查询 * if i need to query name in (a,b); just use { name : { $in : ['a', 'b'] } } * select * from things where name='a' or name='b' * @param coll */ public void queryIn() { BasicDBList values = new BasicDBList(); values.add("a"); values.add("b"); BasicDBObject in = new BasicDBObject("$in", values); DBCursor cursor = MongoInit.getColl("wujintao").find( new BasicDBObject("name", in)); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } /** * 或查询 * select * from table where name = '12' or title = 'p' * @param coll */ public void queryOr() { QueryBuilder query = new QueryBuilder(); query.or(new BasicDBObject("name", 12), new BasicDBObject("title", "p")); DBCursor cursor = MongoInit.getColl("wujintao").find(query.get()).addSpecial("$returnKey", ""); try { while (cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); } } public void customQueryField() throws UnknownHostException{ Mongo mongo = new Mongo("localhost", 27017); DB db = mongo.getDB("zhongsou_ad"); BasicDBObjectBuilder bulder = new BasicDBObjectBuilder(); bulder.add("times",1); bulder.add("aid",1); DBCursor cusor = db.getCollection("ad_union_ad_c_1").find(new BasicDBObject(),bulder.get()); for (DBObject dbObject : cusor) { System.out.println(dbObject); } } public void mapReduce() throws UnknownHostException{ Mongo mongo = new Mongo("localhost", 27017); DB db = mongo.getDB("zhongsou_ad"); /*** * book1 = {name : "Understanding JAVA", pages : 100} * book2 = {name : "Understanding JSON", pages : 200} * db.books.save(book1) * db.books.save(book2) * book = {name : "Understanding XML", pages : 300} * db.books.save(book) * book = {name : "Understanding Web Services", pages : 400} * db.books.save(book) * book = {name : "Understanding Axis2", pages : 150} * db.books.save(book) * var map = function() { var category; if ( this.pages >= 250 ) category = 'Big Books'; else category = "Small Books"; emit(category, {name: this.name}); }; var reduce = function(key, values) { var sum = 0; values.forEach(function(doc) { sum += 1; }); return {books: sum}; }; var count = db.books.mapReduce(map, reduce, {out: "book_results"}); */ try { DBCollection books = db.getCollection("books"); BasicDBObject book = new BasicDBObject(); book.put("name", "Understanding JAVA"); book.put("pages", 100); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding JSON"); book.put("pages", 200); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding XML"); book.put("pages", 300); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding Web Services"); book.put("pages", 400); books.insert(book); book = new BasicDBObject(); book.put("name", "Understanding Axis2"); book.put("pages", 150); books.insert(book); String map = "function() { "+ "var category; " + "if ( this.pages >= 250 ) "+ "category = 'Big Books'; " + "else " + "category = 'Small Books'; "+ "emit(category, {name: this.name});}"; String reduce = "function(key, values) { " + "var sum = 0; " + "values.forEach(function(doc) { " + "sum += 1; "+ "}); " + "return {books: sum};} "; MapReduceCommand cmd = new MapReduceCommand(books, map, reduce, null, MapReduceCommand.OutputType.INLINE, null); MapReduceOutput out = books.mapReduce(cmd); for (DBObject o : out.results()) { System.out.println(o.toString()); } } catch (Exception e) { e.printStackTrace(); } } public void GroupByManyField() throws UnknownHostException{ //此方法没有运行成功 Mongo mongo = new Mongo("localhost", 27017); DB db = mongo.getDB("libary"); DBCollection books = db.getCollection("books"); BasicDBObject groupKeys = new BasicDBObject(); groupKeys.put("total", new BasicDBObject("$sum","pages")); BasicDBObject condition = new BasicDBObject(); condition.append("pages", new BasicDBObject().put("$gt", 0)); String reduce = "function(key, values) { " + "var sum = 0; " + "values.forEach(function(doc) { " + "sum += 1; "+ "}); " + "return {books: sum};} "; /** BasicDBList basicDBList = (BasicDBList)db.getCollection("mongodb中集合编码或者编码") .group(DBObject key, --分组字段,即group by的字段 DBObject cond, --查询中where条件 DBObject initial, --初始化各字段的值 String reduce, --每个分组都需要执行的Function String finial --终结Funciton对结果进行最终的处理 */ DBObject obj = books.group(groupKeys, condition, new BasicDBObject(), reduce); System.out.println(obj); AggregationOutput ouput = books.aggregate(new BasicDBObject("$group",groupKeys)); System.out.println(ouput.getCommandResult()); System.out.println(books.find(new BasicDBObject("$group",groupKeys))); } /** * 分页查询 */ public void pageQuery() { DBCursor cursor = MongoInit.getColl("wujintao").find().skip(0) .limit(10); while (cursor.hasNext()) { System.out.println(cursor.next()); } } /** * 模糊查询 */ public void likeQuery() { Pattern john = Pattern.compile("joh?n"); BasicDBObject query = new BasicDBObject("name", john); // finds all people with "name" matching /joh?n/i DBCursor cursor = MongoInit.getColl("wujintao").find(query); } /** * 条件删除 */ public void delete(String dbCollection,String dataID) { BasicDBObject query = new BasicDBObject(); query.put("id", dataID); // 找到并且删除,并返回删除的对象 DBObject removeObj = MongoInit.getColl(dbCollection).findAndRemove(query); System.out.println(removeObj); } /** * 更新 */ public void update() { BasicDBObject query = new BasicDBObject(); query.put("name", "liu"); DBObject stuFound = MongoInit.getColl("wujintao").findOne(query); stuFound.put("name", stuFound.get("name") + "update_1"); MongoInit.getColl("wujintao").update(query, stuFound); } public void testGpsData() { try { //13862082455:117.13172:029.77659:131.2580 Date d = new Date(); SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); String dateNowStr = sdf.format(d); System.out.println(dateNowStr); DBCollection coll = MongoInit.getColl("table_admin"); BasicDBObject doc = new BasicDBObject(); doc.put("id", "12345678"); doc.put("time", dateNowStr); doc.put("data", "117.13172:029.77659:131.2580"); doc.put("status", "0"); coll.insert(doc); // 设定write concern,以便操作失败时得到提示 coll.setWriteConcern(WriteConcern.SAFE); BasicDBObject dsort = new BasicDBObject(); dsort.put("time", -1); BasicDBObject searchDevice = new BasicDBObject(); searchDevice.put("id", "12345678"); DBCursor cursor = coll.find(searchDevice).sort(dsort); List<DBObject> list = cursor.toArray(); //ArrayList<SensorData> listSensorData=new ArrayList<SensorData>(list.size()); ObjectMapper mapper = new ObjectMapper(); String jsonfromList = null; try { //list转json jsonfromList = mapper.writeValueAsString(list); } catch (JsonProcessingException e) { // TODO Auto-generated catch block e.printStackTrace(); } //System.out.println(jsonfromList); // for(int i=0;i<list.size();i++) // { // System.out.println((String) list.get(i).get("time")); //} //System.out.println(list.size()+","+listSensorData);//list的长度 // System.out.println(cursor.count());//计算结果的数量,类似于(mysql count()函数),不受limit的影响 // while (cursor.hasNext()) { // System.out.println(cursor.next()); // } System.out.println("The Search Query has Executed!"); } catch (MongoException e) { e.printStackTrace(); } } public static void main(String[] args) { String dbname="wlwdb"; String dbCollection="table_admin"; String dbCollection1="15257102317"; String dataID="12345678"; MongoUtils tb=new MongoUtils(); tb.testGetDBS();//查询所有数据库 tb.getAllCollections();//查询所有表 // // tb.findOne(dbCollection);//查找第一条记录 tb.testGpsData(); tb.getAllDocuments(dbCollection);//获取制定表明的所有数据 //tb.dropDatabase(dbname);//删除指定数据库 //tb.delete(dbCollection,dataID);//删除制定表明和设备ID的数据 //tb.dropCollection(dbCollection);// 删除一个表 //tb.createIndex(dbCollection1);//创建索引 //tb.getIndexInfo(dbCollection1);//获得表中所有索引 } } MongoDBConfig.properties #端口设置 DBPort=27017 #URL DBUrl=localhost #URL DBName=wlwdb [DAO层]java代码解释逐行解释 你用的应该是ibatis,这里是批量删除,相当于把一堆操作用一个事务来提交,提高数据库性能。//函数功能,删除list中的所有元素在数据库中的记录。protected void batchDelete(List<?> lst, String statement)throws SQLException{getSqlMapClient().startBatch();//开始批量操作//遍历listfor (Iterator localIterator = lst.iterator(); localIterator.hasNext(); ) { Object obj = localIterator.next();getSqlMapClient().delete(statement, obj);//statement表示你调用的删除方法,在xml文件中定义的。}getSqlMapClient().executeBatch();//结束批量操作} 若转载请注明出处!若有疑问,请回复交流!
1、含日期查询 从起始时间到结束时间 BasicDBObject queryObj = new BasicDBObject(); queryObj.put("date",new BasicDBObject().append("$gte",starttime).append("$lt",endtime)); 2、distinct 查询 BasicDBObject queryObj = new BasicDBObject(); coll.distinct("field_name",queryObj);// field_name 为数据库中需要distinct的字段名称,queryObj为查询条件 ,先执行查询条件后在distinct;返回为一个list集合 里面存放所有不重复的 field_name. 这种方式还是有中缺陷,如果数据量过大 list可能超出容量,不好控制,可以使用group by的方法替换 3、exists 查询 BasicDBObject basicObj = new BasicDBObject(); BasicDBObject andSearch = new BasicDBObject(); andSearch.put("$gte", start.getTime());andSearch.put("$lt", end.getTime());basicObj.put("date", andSearch); basicObj.put("field_name", new BasicDBObject("$exists", true)); //若数据库中 field_name 这个字段有值 (包含null),则符合条件,反之这条记录没有这个字段则不符合条件 4、group 查询 (分组查询) Map<String, Integer> map = new HashMap<String,Integer>(); DBCollection coll = MongoDB.getDBCollection("user_processed_corpus"); DBObject fields = new BasicDBObject(); fields.put("cust_name", "$cust_name"); DBObject groupField = new BasicDBObject(); groupField.put("_id", fields); groupField.put("count", new BasicDBObject("$sum",1)); DBObject group = new BasicDBObject("$group",groupField); BasicDBObject matchObj = new BasicDBObject(); matchObj.put("date",new BasicDBObject("$lt", end.getTime()).append("$gt",start.getTime())); matchObj.put("userid", userid); matchObj.put("from", from); DBObject match = new BasicDBObject("$match",matchObj); AggregationOutput output = coll.aggregate(match, group); Iterable<DBObject> results = output.results(); Iterator<DBObject> it = results.iterator(); while(it.hasNext()){ DBObject obj = it.next(); DBObject name = (DBObject) obj.get("_id"); Object cust_name =name.get("cust_name"); if(CommonUtil.isNotNull(cust_name)){ map.put(cust_name.toString(), Integer.valueOf(obj.get("count").toString())); } } 4.2 group(方式2) public static void group(){ BasicDBObject group = new BasicDBObject(); group.put("_id", "$userid"); group.put("count", new BasicDBObject("$sum",1)); AggregationOutput output = coll.aggregate(new BasicDBObject("$group",group)); DBObject obj = output.getCommand(); System.out.println(obj); CommandResult result = output.getCommandResult(); System.out.println(result.get("result")); } 5、addToSet(只能确保添加到记录,不能影响原有记录数据) 相同的数据则不添加 public static void addToSetAndEachElementInArray(String _id){ List list = new ArrayList(); list.add("str0"); list.add("str1"); list.add(new BasicDBObject("arr90",90)); BasicDBObject idObj = new BasicDBObject("_id", new ObjectId(_id)); BasicDBObject updateObj = new BasicDBObject(); updateObj.put("$addToSet", new BasicDBObject("arrays",new BasicDBObject("$each",list))); WriteResult result = coll.update(idObj,updateObj); System.out.println("update count:"+result.getN()); } 6、or 查询 将多个查询条件加入一个list中 用$or 连接list中的查询条件即可 public static void test1(){ BasicDBObject query1 = new BasicDBObject(); BasicDBObject query2 = new BasicDBObject(); query1.put("count", new BasicDBObject("$exists",false)); query2.put("count", new BasicDBObject("$exists",true)); BasicDBList list = new BasicDBList(); list.add(query2); list.add(query1); BasicDBObject query = new BasicDBObject(); query.put("$or", list); int count = coll.find(query).count(); System.out.println(count); } 7、in 查询 1 public void findByINQuery(int value1,int value2){ 2 coll = getCollection("ParentColl"); 3 BasicDBObject query=new BasicDBObject(); 4 BasicDBList cond=new BasicDBList(); 5 cond.add(value1); 6 cond.add(value2); 7 query.put("intData",new BasicDBObject("$in", cond)); 8 DBCursor cur = coll.find(query); 9 while(cur.hasNext()){ 10 System.out.println(cur.next()); 11 } 12 } 8、addToSet的另外一种用法(本质相同) 对分组之后的数据在进行操作 userid question 1 a 1 b 2 c 2 a 2 b 1 a 3 c 3 b 3 a 1 public static void group1(){ 2 BasicDBObject obj = new BasicDBObject(); 3 BasicDBObject query = new BasicDBObject(); 4 BasicDBObject match = new BasicDBObject(); 5 BasicDBObject group = new BasicDBObject(); 6 BasicDBObject g1 = new BasicDBObject(); 7 //第一个分组 (userid 和 question 共同作为分组字段) 8 g1.put("userid", "$userid"); 9 g1.put("question", "$question"); 10 group.put("_id", g1); 11 //可以额外的添加一些字段(以便下次的统计操作) 12 group.put("count", new BasicDBObject("$sum",1)); 13 group.put("userid",new BasicDBObject("$addToSet", "$userid")); 14 group.put("question",new BasicDBObject("$addToSet", "$question")); 15 obj.put("$group", group); 16 match.put("$match", query); 17 18 //对第一次分组产生的结果进行再次分组(第一次分组的结果见注1) 19 DBObject _group = new BasicDBObject(); 20 _group.put("question", "$question"); 21 DBObject groupFields1 = new BasicDBObject("_id", _group); 22 groupFields1.put("user_sum", new BasicDBObject("$sum", 1)); 23 BasicDBObject group1 = new BasicDBObject(); 24 group1.append("$group", groupFields1); 25 26 AggregationOutput out = coll.aggregate(match,obj,group1); 27 CommandResult result = out.getCommandResult(); 28 BasicDBList record = (BasicDBList) result.get("result"); 29 System.out.println(record.size()); 30 } 注1:第一次分组的结果 [{ "_id" : { "userid" : "0003", "question" : "how" }, "count" : 30, "userid" : ["0003"], "question" : ["how"] }, { "_id" : { "userid" : "0002", "question" : "I am comming" }, "count" : 1, "userid" : ["0002"], "question" : ["I am comming"] }, { "_id" : { "userid" : "0002", "question" : "2323" }, "count" : 1, "userid" : ["0002"], "question" : ["2323"] }, { "_id" : { "userid" : "0002", "question" : "how" }, "count" : 38, "userid" : ["0002"], "question" : ["how"] }, { "_id" : { "userid" : "0001", "question" : "I comming" }, "count" : 1, "userid" : ["0001"], "question" : ["I comming"] }, { "_id" : { "userid" : "0002", "question" : "123" }, "count" : 1, "userid" : ["0002"], "question" : ["123"] }, { "_id" : { "userid" : "0001", "question" : "I am " }, "count" : 1, "userid" : ["0001"], "question" : ["I am "] }, { "_id" : { "userid" : "0001", "question" : "I am comming" }, "count" : 4, "userid" : ["0001"], "question" : ["I am comming"] } ] 结果解释:_id 中的内容为分组的字段是唯一的,故作为_id 后面的count userid 和question都是在分组过程中手动添加上去的,这个其实就当做中间表 以便下面的数据统计和操作 9、模糊查询(pattern) String like = "..."; Pattern pattern = Pattern.compile("^.*"+like+".*$", Pattern.CASE_INSENSITIVE); BasicDBObject obj = new BasicDBObject(); obj.put("name",pattern); coll.find(obj); 10、$eleMatch 查询(数组匹配查询) DBObject edit = new BasicDBObject(); edit.put("slotname", "content"); query.put("slotbind", new BasicDBObject("$elemMatch", edit)); 不难发现主要用到BasicDBObject、BasicDBList、DBCursor这三个类。BasicDBObject好比一个map,好比使用json查询中的{} 。BasicDBList是个list,用于or,nin等条件查询。DBCursor用于遍历结果集。其实只要将对应的json查询使用这3个类转化一下,就能写出对应的java代码了。若转载请注明出处!若有疑问,请回复交流!
1.漏洞危害 开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增删改高危动作)而且可以远程访问数据库。 2.漏洞成因 在刚安装完毕的时候MongoDB都默认有一个admin数据库,此时admin数据库是空的,没有记录权限相关的信息!当admin.system.users一个用户都没有时,即使mongod启动时添加了—auth参数,如果没有在admin数据库中添加用户,此时不进行任何认证还是可以做任何操作(不管是否是以—auth 参数启动),直到在admin.system.users中添加了一个用户。加固的核心是只有在admin.system.users中添加用户之后,mongodb的认证,授权服务才能生效。 3.mongoDB未授权漏洞加固方案 1) 修改默认端口 修改默认的mongoDB 端口(默认为:TCP 27017)为其他端口 2) 不要把MongoDB服务器部署在互联网上或者DMZ 使用安全组防火墙或本地操作系统防火墙对访问源IP进行控制,如果仅对内网服务器提供服务,建议禁止将mongoDB服务发布到互联网上 3) 使用- -bind_ip选项 该选项可以限制监听接口IP, 当在启动mongodb的时候,使用 -bind_ip 192.168.0.1表示启动ip地址绑定,数据库实例将只监听192.168.0.1的请求。 4) 启动基于角色的登录认证功能 在admin 数据库中创建用户,如 supper 密码为 sup(此处均为举例说明,请勿使用此账号密码) [mongodb@rac3 bin]$ ./mongo 127.0.0.1:27028 (此处修改了默认端口) MongoDB shell version: 2.0.1 connecting to: 127.0.0.1:27028/test > use admin switched to db admin > > db.addUser("supper", "sup") { "n" : 0, "connectionId" : 4, "err" : null, "ok" : 1 } { "user" : "supper", "readOnly" : false, "pwd" : "51a481f72b8b8218df9fee50b3737c44", "_id" : ObjectId("4f2bc0d357a309043c6947a4") } > db.auth("supper","sup") 1 > exit bye 更多选项参见:MongoDB – Add Users and Authenticate 5)禁用HTTP和REST端口 MongoDB自身带有一个HTTP服务和并支持REST接口。在2.6以后这些接口默认是关闭的。mongoDB默认会使用默认端口监听web服务,一般不需要通过web方式进行远程管理,建议禁用。修改配置文件或在启动的时候选择–nohttpinterface 参数nohttpinterface = false 6)开启日志审计功能 审计功能可以用来记录用户对数据库的所有相关操作。这些记录可以让系统管理员在需要的时候分析数据库在什么时段发生了什么事情。具体请参见:Mongodb审计功能 7)使用SSL加密功能 MongoDB集群之间以及从客户端连接到MongoDB实例的连接应该使用SSL。使用SSL对性能没有影响并且可以防范类似于man-in-the-middle的攻击。 注意MongoDB社区版默认并不支持SSL。您可以选用MongoDB企业版(有SSL支持),或者从源码重新编译MongoDB并使用 —ssl 选项来获得SSL功能。 具体请参见:Configure mongod and mongos for TLS/SSL 以上所有配置推荐以配置文件形式保存配置 [mongodb@rac3 bin]$ vim /path/mongod.conf port=27028-------端口。默认27017,MongoDB的默认服务TCP端口,监听客户端连接。要是端口设置小于1024,比如1021,则需要root权限启动,不能用mongodb帐号启动,(普通帐号即使是27017也起不来)否则报错:[mongo --port=1021 连接] bind_ip=192.168.0.1------绑定地址。默认127.0.0.1,只能通过本地连接。进程绑定和监听来自这个地址上的应用连接。要是需要给其他服务器连接,则需要注释掉这个或则把IP改成本机地址,如192.168.200.201[其他服务器用 mongo --host=192.168.200.201 连接] ,可以用一个逗号分隔的列表绑定多个IP地址。 logpath=/path/mongod.log------开启日志审计功能,此项为日志文件路径,可以自定义指定 pidfilepath=/path/mongod.pid------进程ID,没有指定则启动时候就没有PID文件。默认缺省。 auth=true------用户认证,默认false。不需要认证。当设置为true时候,进入数据库需要auth验证,当数据库里没有用户,则不需要验证也可以操作。直到创建了第一个用户,之后操作都需要验证。 logappend=true------写日志的模式:设置为true为追加。默认是覆盖。如果未指定此设置,启动时MongoDB的将覆盖现有的日志文件。 fork=true------是否后台运行,设置为true 启动 进程在后台运行的守护进程模式。默认false。 nohttpinterface = false------是否禁止http接口,即28017 端口开启的服务。默认false,支持。 然后启动mongod时加载配置文件 [mongodb@rac3 bin]$ ./mongod -f /path/mongod.conf 更多关于MongoDB加固内容参见:MongoDB security checklist若转载请注明出处!若有疑问,请回复交流!
安装 1>设置MongoDB目录 cd /home/apps 附:centOS下创建目录命令 mkdir /home/apps 2>下载mongodb curl -O http://fastdl.mongodb.org/Linux/mongodb-linux-x86_64-2.4.6.tgz 或者直接下载再copy或用xftp上传到指定目录 3>解压缩文件 tar xzf mongodb-linux-x86_64-2.4.6.tgz 4>启动服务 ./mongodb/bin/mongod -dbpath=/data/mongodb/db -logpath=/data/mongodb/log mongodb 是mongo解压后的目录,下同 5>将mongoDB服务加入随机启动 vi /etc/rc.local 使用vi编辑器打开配置文件,并在其中加入下面一行代码 /home/apps/mongodb/bin/mongod --dbpath /data/mongodb/db --port 27017 --logpath /data/mongodb/log --logappend 这种方式能保证开机mongod 进程能开启,但没有作为服务运行 6>把mongod 作为服务开机启动 先在/etc/rc.d/init.d下用vi 新建文件 mongod 内容如下: #!/bin/bash # #chkconfig: 2345 80 90 #description: mongodb start() { /usr/mongodb/bin/mongod --config /usr/mongodb/config/mongod.conf } stop() { /usr/mongodb/bin/mongod --config /usr/mongodb/config/mongod.conf --shutdown } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo $"Usage: $0 {start|stop|restart}" exit 1 esac 保存 /usr/mongodb/config/mongod.conf 配置文件的内容如下 #master.conf dbpath=/usr/mongodb/data/db logpath=/usr/mongodb/log/db.log pidfilepath=/usr/mongodb/db.pid directoryperdb=true logappend=true bind_ip=192.168.1.7 port=27017 oplogSize=1000 fork=true noprealloc=true nojournal=true smallfiles=true 2、增加服务并开机启动 chmod +x /etc/rc.d/init.d/mongod chkconfig --add mongod chkconfig --level 345 mongod on chkconfig --list mongod service mongod start 执行该脚本后,就可以开始start|stop|restart|list你的服务了。 以后关机再启动就会自动启动mongo了,如果在同一台机需要启动多个mongod照此方法即可 暂时只知道这样设为开机启动服务,如果有更好的方式请告知哦,先谢了! 7>连接mongoDB ./mongodb/bin/mongo 27017 即可连上mongo 讲到这儿,mongoDB的在Linux下安装已完成,本地连接mongoDB也已成功,这时我们就要考虑到另外一个问题了,局域网如何来连接mongoDB呢?局域网中windows机器如何来连接Linux机器中的mongoDB呢? 其实做法一样很简单:./mongodb/bin/mongo 192.168.10.234:port即可。 不过此处就需要注意了,我们需要在centOS上打开mongoDB的端口号,接下来讲讲如何在centOS上打开指定端口。 我们打开配置文件 /etc/sysconfig/iptables,在该文件中添加如下内容: -A RH-Firewall-l-INPUT -P tcp -m tcp --dport mongoDB端口号 -j ACCEPT 然后重启服务 service iptables restart 此时,你已可以开始通过局域网来访问centOS上部署的mongoDB 顺便再增加一点centOS与windows互访的知识,譬如,我们想把原来在windows机器上的mongoDB产生的文件移植到centOS中,当然可以用移动存储设备来拷贝,但是我这里讲的是Linux(centOS)如何来访问windows共享目录,命令如下: mount -t cifs //ip/共享目录名称 /mnt/sharefile -o username=,password= 上面的命令即将windows的共享目录映射为linux上的/mnt/sharefile目录 顶 1 踩若转载请注明出处!若有疑问,请回复交流!
转自:http://blog.csdn.net/5iasp/article/details/8669644 模拟表单html如下: <form action="up_result.jsp" method="post" enctype="multipart/form-data" name="form1" id="form1"> <label> <input type="text" name="name" value="" /> </label> <label> <input type="file" name="userfile" /> </label> <label> <input type="submit" value="上传" /> </label> </form> java代码如下: [java] view plain copy package com.yanek.util; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.activation.MimetypesFileTypeMap; import net.sf.json.JSONArray; import net.sf.json.JSONObject; public class HttpPostUploadUtil { /** * @param args */ public static void main(String[] args) { String filepath="E:\\ziliao\\0.jpg"; String urlStr = "http://127.0.0.1:8080/minicms/up/up_result.jsp"; Map<String, String> textMap = new HashMap<String, String>(); textMap.put("name", "testname"); Map<String, String> fileMap = new HashMap<String, String>(); fileMap.put("file", filepath); String ret = formUpload(urlStr, textMap, fileMap); System.out.println(ret); } /** * 上传图片 * * @param urlStr * @param textMap * @param fileMap * @return */ public static String formUpload(String urlStr, Map<String, String> textMap, Map<String, String> fileMap) { String res = ""; HttpURLConnection conn = null; String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符 try { URL url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(30000); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn .setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); OutputStream out = new DataOutputStream(conn.getOutputStream()); // text if (textMap != null) { StringBuffer strBuf = new StringBuffer(); Iterator iter = textMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String inputName = (String) entry.getKey(); String inputValue = (String) entry.getValue(); if (inputValue == null) { continue; } strBuf.append("\r\n").append("--").append(BOUNDARY).append( "\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n"); strBuf.append(inputValue); } out.write(strBuf.toString().getBytes()); } // file if (fileMap != null) { Iterator iter = fileMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String inputName = (String) entry.getKey(); String inputValue = (String) entry.getValue(); if (inputValue == null) { continue; } File file = new File(inputValue); String filename = file.getName(); String contentType = new MimetypesFileTypeMap() .getContentType(file); if (filename.endsWith(".png")) { contentType = "image/png"; } if (contentType == null || contentType.equals("")) { contentType = "application/octet-stream"; } StringBuffer strBuf = new StringBuffer(); strBuf.append("\r\n").append("--").append(BOUNDARY).append( "\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"; filename=\"" + filename + "\"\r\n"); strBuf.append("Content-Type:" + contentType + "\r\n\r\n"); out.write(strBuf.toString().getBytes()); DataInputStream in = new DataInputStream( new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); } } byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes(); out.write(endData); out.flush(); out.close(); // 读取返回数据 StringBuffer strBuf = new StringBuffer(); BufferedReader reader = new BufferedReader(new InputStreamReader( conn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { strBuf.append(line).append("\n"); } res = strBuf.toString(); reader.close(); reader = null; } catch (Exception e) { System.out.println("发送POST请求出错。" + urlStr); e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); conn = null; } } return res; } }若转载请注明出处!若有疑问,请回复交流!
一、设置图片的缩放比例或者图片的质量比 第一步:导入maven的jar包 <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.8</version> </dependency> 第二步:获取一个Builder<File>对象 public static Builder<File> of(String... files) { checkForNull(files, "Cannot specify null for input files."); checkForEmpty(files, "Cannot specify an empty array for input files."); return Builder.ofStrings(Arrays.asList(files)); } ...... 第三步:设置图片缩放比例 通过Builder<File>对象的scale(double scale)方法 通过Builder<File>对象的size(int width, int height)方法 通过Builder<File>对象的height(int height)或width(int width)方法 第四步:设置图片质量比 通过Builder<File>对象的outputQuality(double quality) 二、获取图片的信息 第一步:通过Thumbnails.Builder<File>的asBufferedImage()方法获取BufferedImage对象,把照片加载到内存中 第二步: 通过BufferedImage对象的getHeight(null)获取图片的高度 通过BufferedImage对象的getWidth(null)获取图片的宽度 小示例: public static boolean ThumbnailsCompressPic(String inputFile, String outputFile, int size, float quality) { File input = new File(inputFile); try { Thumbnails.Builder<File> fileBuilder = Thumbnails.of(input).scale(1.0).outputQuality(1.0); BufferedImage src = fileBuilder.asBufferedImage(); if(src.getHeight(null) > size || src.getWidth(null) > size) { Thumbnails.Builder<File> builder = Thumbnails.of(input); builder.size(size, size); //取最大的尺寸变成size,然后等比缩放 builder.outputQuality(quality).toFile(outputFile); } else { Thumbnails.of(input).scale(1.0).outputQuality(quality).toFile(outputFile); } return true; } catch (IOException e) { logger.error(e.getMessage(), e); } return false; }若转载请注明出处!若有疑问,请回复交流!
将MongoDB服务加入随机启动 vi /etc/rc.local 使用vi编辑器打开配置文件,并在其中加入下面一行代码 /usr/local/mongodb/bin/mongod -dbpath=/usr/local/mongodb/data/db --fork --port 27017 --logpath=/usr/local/mongodb/log/work.log --logappend --auth 启动服务 /usr/local/mongodb/bin/mongod -dbpath=/usr/local/mongodb/data/db --fork --port 27017 --logpath=/usr/local/mongodb/log/work.log --logappend --auth 其他: Mongodb在Linux下安装及配置 我这里选用rehl 6作为其运行载体。 1.下载mongodb的linux版本(注意32位和64位的区别),下载地址:http://www.mongodb.org/downloads 2.将下载的mongodb安装文件mongodb-linux-i686-1.6.5.tgz放到/usr/local/下 3.解压tar -zxvf mongodb-linux-i686-1.6.5.tgz 重命名mv mongodb-linux-i686-1.6.5.tgz mongodb 4,创建数据库文件目录,默认为/data/db,我把数据库文件目录放在当前文件夹下,mkdir -p data/db,创建日志目录mkdir log 5.启动服务 cd /usr/local/mongodb/bin ./mongod -dbpath=../data/db -logpath=../log/mongodb.log 6,启动客户端shell测试 [root@localhost bin]# ./mongo MongoDB shell version: 1.6.5 connecting to: test > db.foo.save({a:1}) > db.foo.find() { "_id" : ObjectId("4d292a457e289d5d90dc6f33"), "a" : 1 } 7.将mongoDB服务加入随机启动 vi /etc/rc.local 使用vi编辑器打开配置文件,并在其中加入下面一行代码 /usr/local/mongodb/bin/mongod -dbpath=/usr/local/mongodb/data/db --port 27017 -logpath=/usr/local/mongodb/log --logappend 8.连接mongoDB客户端,出现如下信息则启动成功 ./mongodbbin/mongo MongoDB shell version: 1.6.5 connecting to: test > 9,脚本启动关闭mongodb ## start-mongod.sh MONGODIR = /usr/local/mongodb MONGOD = $MONGODIR /bin/mongod MONGO = $MONGODIR /bin/mongo DBDIR = $MONGODIR /data/db LOGPATH = $MONGODIR/log /mongodb.log # mongod will print its pid, so store it in out.tmp, then # print it using awk to mongod.pid $MONGOD --dbpath $DBDIR --fork --logpath $LOGPATH --logappend > out.tmp awk 'NR == 2 { print $3 }' < out.tmp > mongod.pid sleep 3 $MONGO < onstart.js ## in onstart.js use admin; db.runCommand ( "logRotate" ) ;若转载请注明出处!若有疑问,请回复交流!
/** * */ package com.hd.admin.wxmeet.utils; /** * @author jymcpp * */ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class wxLongutils { public static void main(String[] args){ String createTime = "1483084803"; String formatTime = formatTime(createTime); System.out.println(formatTime); String year = formatTime.substring(6, 10); String month = formatTime.substring(0, 2); String day = formatTime.substring(3, 5); String hour = formatTime.substring(11, 13); String minute = formatTime.substring(14, 16); String second = formatTime.substring(17, 19); System.out.println(year); System.out.println(Long.parseLong(month)); System.out.println(day); System.out.println(hour); System.out.println(minute); System.out.println(second); String sDt = "08/07/2014 10:14:36"; System.out.println(formatToLongTime(sDt)); } /** * 将微信消息中的CreateTime转换成标准格式的时间(MM/dd/yyyy HH:mm:ss) * * @param createTime 消息创建时间 * @return */ public static String formatTime(String createTime) { // 将微信传入的CreateTime转换成long类型,再乘以1000 long msgCreateTime = Long.parseLong(createTime) * 1000L; DateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); return format.format(new Date(msgCreateTime)); } /** * 将标准格式的时间(MM/dd/yyyy HH:mm:ss)转换为微信服务器的long型 * @param formatTime * @return * @throws ParseException */ public static long formatToLongTime(String formatTime){ SimpleDateFormat sdf= new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); Date dt2; try { dt2 = sdf.parse(formatTime); return dt2.getTime() / 1000; } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } //转换失败返回值 return -1; } } 若转载请注明出处!若有疑问,请回复交流!
管理员账号无法执行show dbs 、show collections Js代码 { "_id" : ObjectId("52a82bb26cea234c4deb06fd"), "user" : "admin", "pwd" : "7c67ef13bbd4cae106d959320af3f704", "roles" : [ "userAdminAnyDatabase" ] } db.system.users.findOne() { "_id" : ObjectId("52a849331575fa94bad8b7ce"), "user" : "admin", "pwd" : "7c67ef13bbd4cae106d959320af3f704", "roles" : [ "userAdminAnyDatabase", "dbAdminAnyDatabase", "readWriteAnyDatabase", "clusterAdmin" ] } 功能全开这才是超级管理员的权限嘛若转载请注明出处!若有疑问,请回复交流!
一、数据库常用命令 1、Help查看命令提示 复制代码代码如下: help db.help(); db.yourColl.help(); db.youColl.find().help(); rs.help(); 2、切换/创建数据库 复制代码代码如下: use yourDB; 当创建一个集合(table)的时候会自动创建当前数据库 3、查询所有数据库 复制代码代码如下: show dbs; 4、删除当前使用数据库 复制代码代码如下: db.dropDatabase(); 5、从指定主机上克隆数据库 复制代码代码如下: db.cloneDatabase(“127.0.0.1”); 将指定机器上的数据库的数据克隆到当前数据库 6、从指定的机器上复制指定数据库数据到某个数据库 复制代码代码如下: db.copyDatabase("mydb", "temp", "127.0.0.1");将本机的mydb的数据复制到temp数据库中 7、修复当前数据库 复制代码代码如下: db.repairDatabase(); 8、查看当前使用的数据库 复制代码代码如下: db.getName(); db; db和getName方法是一样的效果,都可以查询当前使用的数据库 9、显示当前db状态 复制代码代码如下: db.stats(); 10、当前db版本 复制代码代码如下: db.version(); 11、查看当前db的链接机器地址 复制代码代码如下: db.getMongo(); 二、Collection聚集集合 1、创建一个聚集集合(table) 复制代码代码如下: db.createCollection(“collName”, {size: 20, capped: 5, max: 100});//创建成功会显示{“ok”:1} //判断集合是否为定容量db.collName.isCapped(); 2、得到指定名称的聚集集合(table) 复制代码代码如下: db.getCollection("account"); 3、得到当前db的所有聚集集合 复制代码代码如下: db.getCollectionNames(); 4、显示当前db所有聚集索引的状态 复制代码代码如下: db.printCollectionStats(); 三、用户相关 1、添加一个用户 复制代码代码如下: db.addUser("name"); db.addUser("userName", "pwd123", true); 添加用户、设置密码、是否只读 2、数据库认证、安全模式 复制代码代码如下: db.auth("userName", "123123"); 3、显示当前所有用户 复制代码代码如下: show users; 4、删除用户 复制代码代码如下: db.removeUser("userName"); 四、聚集集合查询 1、查询所有记录 复制代码代码如下: db.userInfo.find(); 相当于:select* from userInfo; 默认每页显示20条记录,当显示不下的情况下,可以用it迭代命令查询下一页数据。注意:键入it命令不能带“;” 但是你可以设置每页显示数据的大小,用DBQuery.shellBatchSize= 50;这样每页就显示50条记录了。 2、查询去掉后的当前聚集集合中的某列的重复数据 复制代码代码如下: db.userInfo.distinct("name"); 会过滤掉name中的相同数据 相当于:select distict name from userInfo; 3、查询age = 22的记录 复制代码代码如下: db.userInfo.find({"age": 22}); 相当于: select * from userInfo where age = 22; 4、查询age > 22的记录 复制代码代码如下: db.userInfo.find({age: {$gt: 22}}); 相当于:select * from userInfo where age >22; 5、查询age < 22的记录 复制代码代码如下: db.userInfo.find({age: {$lt: 22}}); 相当于:select * from userInfo where age <22; 6、查询age >= 25的记录 复制代码代码如下: db.userInfo.find({age: {$gte: 25}}); 相当于:select * from userInfo where age >= 25; 7、查询age <= 25的记录 复制代码代码如下: db.userInfo.find({age: {$lte: 25}}); 8、查询age >= 23 并且 age <= 26 复制代码代码如下: db.userInfo.find({age: {$gte: 23, $lte: 26}}); 9、查询name中包含 mongo的数据 复制代码代码如下: db.userInfo.find({name: /mongo/}); //相当于%% [code]select * from userInfo where name like ‘%mongo%'; 10、查询name中以mongo开头的 复制代码代码如下: db.userInfo.find({name: /^mongo/}); select * from userInfo where name like ‘mongo%'; 11、查询指定列name、age数据 复制代码代码如下: db.userInfo.find({}, {name: 1, age: 1}); 相当于:select name, age from userInfo; 当然name也可以用true或false,当用ture的情况下河name:1效果一样,如果用false就是排除name,显示name以外的列信息。 12、查询指定列name、age数据, age > 25 复制代码代码如下: db.userInfo.find({age: {$gt: 25}}, {name: 1, age: 1}); 相当于:select name, age from userInfo where age >25; 13、按照年龄排序 复制代码代码如下: 升序:db.userInfo.find().sort({age: 1}); 降序:db.userInfo.find().sort({age: -1}); 14、查询name = zhangsan, age = 22的数据 复制代码代码如下: db.userInfo.find({name: 'zhangsan', age: 22}); 相当于:select * from userInfo where name = ‘zhangsan' and age = ‘22'; 15、查询前5条数据 复制代码代码如下: db.userInfo.find().limit(5); 相当于:selecttop 5 * from userInfo; 16、查询10条以后的数据 复制代码代码如下: db.userInfo.find().skip(10); 相当于:select * from userInfo where id not in ( selecttop 10 * from userInfo ); 17、查询在5-10之间的数据 复制代码代码如下: db.userInfo.find().limit(10).skip(5); 可用于分页,limit是pageSize,skip是第几页*pageSize 18、or与 查询 复制代码代码如下: db.userInfo.find({$or: [{age: 22}, {age: 25}]}); 相当于:select * from userInfo where age = 22 or age = 25; 19、查询第一条数据 复制代码代码如下: db.userInfo.findOne(); 相当于:selecttop 1 * from userInfo; db.userInfo.find().limit(1); 20、查询某个结果集的记录条数 复制代码代码如下: db.userInfo.find({age: {$gte: 25}}).count(); 相当于:select count(*) from userInfo where age >= 20; 21、按照某列进行排序 复制代码代码如下: db.userInfo.find({sex: {$exists: true}}).count(); 相当于:select count(sex) from userInfo; 五、索引 1、创建索引 复制代码代码如下: db.userInfo.ensureIndex({name: 1}); db.userInfo.ensureIndex({name: 1, ts: -1}); 2、查询当前聚集集合所有索引 复制代码代码如下: db.userInfo.getIndexes(); 3、查看总索引记录大小 复制代码代码如下: db.userInfo.totalIndexSize(); 4、读取当前集合的所有index信息 复制代码代码如下: db.users.reIndex(); 5、删除指定索引 复制代码代码如下: db.users.dropIndex("name_1"); 6、删除所有索引索引 复制代码代码如下: db.users.dropIndexes(); 六、修改、添加、删除集合数据 1、添加 复制代码代码如下: db.users.save({name: ‘zhangsan', age: 25, sex: true}); 添加的数据的数据列,没有固定,根据添加的数据为准 2、修改 复制代码代码如下: db.users.update({age: 25}, {$set: {name: 'changeName'}}, false, true); 相当于:update users set name = ‘changeName' where age = 25; db.users.update({name: 'Lisi'}, {$inc: {age: 50}}, false, true); 相当于:update users set age = age + 50 where name = ‘Lisi'; db.users.update({name: 'Lisi'}, {$inc: {age: 50}, $set: {name: 'hoho'}}, false, true); 相当于:update users set age = age + 50, name = ‘hoho' where name = ‘Lisi'; 3、删除 复制代码代码如下: db.users.remove({age: 132}); 4、查询修改删除 复制代码代码如下: db.users.findAndModify({ query: {age: {$gte: 25}}, sort: {age: -1}, update: {$set: {name: 'a2'}, $inc: {age: 2}}, remove: true }); db.runCommand({ findandmodify : "users", query: {age: {$gte: 25}}, sort: {age: -1}, update: {$set: {name: 'a2'}, $inc: {age: 2}}, remove: true }); update 或 remove 其中一个是必须的参数; 其他参数可选。 参数 详解 默认值 query 查询过滤条件 {} sort 如果多个文档符合查询过滤条件,将以该参数指定的排列方式选择出排在首位的对象,该对象将被操作 {} remove 若为true,被选中对象将在返回前被删除 N/A update 一个 修改器对象 N/A new 若为true,将返回修改后的对象而不是原始对象。在删除操作中,该参数被忽略。 false fields 参见Retrieving a Subset of Fields (1.5.0+) All fields upsert 创建新对象若查询结果为空。 示例 (1.5.4+) false 七、语句块操作 1、简单Hello World 复制代码代码如下: print("Hello World!"); 这种写法调用了print函数,和直接写入"Hello World!"的效果是一样的; 2、将一个对象转换成json 复制代码代码如下: tojson(new Object()); tojson(new Object('a')); 3、循环添加数据 复制代码代码如下: > for (var i = 0; i < 30; i++) { ... db.users.save({name: "u_" + i, age: 22 + i, sex: i % 2}); ... }; 这样就循环添加了30条数据,同样也可以省略括号的写法 复制代码代码如下: > for (var i = 0; i < 30; i++) db.users.save({name: "u_" + i, age: 22 + i, sex: i % 2}); 也是可以的,当你用db.users.find()查询的时候,显示多条数据而无法一页显示的情况下,可以用it查看下一页的信息; 4、find 游标查询 复制代码代码如下: >var cursor = db.users.find(); > while (cursor.hasNext()) { printjson(cursor.next()); } 这样就查询所有的users信息,同样可以这样写 复制代码代码如下: var cursor = db.users.find(); while (cursor.hasNext()) { printjson(cursor.next); } 同样可以省略{}号 5、forEach迭代循环 复制代码代码如下: db.users.find().forEach(printjson); forEach中必须传递一个函数来处理每条迭代的数据信息 6、将find游标当数组处理 复制代码代码如下: var cursor = db.users.find(); cursor[4]; 取得下标索引为4的那条数据 既然可以当做数组处理,那么就可以获得它的长度:cursor.length();或者cursor.count(); 那样我们也可以用循环显示数据 复制代码代码如下: for (var i = 0, len = c.length(); i < len; i++) printjson(c[i]); 7、将find游标转换成数组 复制代码代码如下: > var arr = db.users.find().toArray(); > printjson(arr[2]); 用toArray方法将其转换为数组 8、定制我们自己的查询结果 只显示age <= 28的并且只显示age这列数据 复制代码代码如下: db.users.find({age: {$lte: 28}}, {age: 1}).forEach(printjson); db.users.find({age: {$lte: 28}}, {age: true}).forEach(printjson); 排除age的列 复制代码代码如下: db.users.find({age: {$lte: 28}}, {age: false}).forEach(printjson); 9、forEach传递函数显示信息 复制代码代码如下: db.things.find({x:4}).forEach(function(x) {print(tojson(x));}); 八、其他 1、查询之前的错误信息 复制代码代码如下: db.getPrevError(); 2、清除错误记录 复制代码代码如下: db.resetError(); 查看聚集集合基本信息 1、查看帮助 db.yourColl.help(); 2、查询当前集合的数据条数 db.yourColl.count(); 3、查看数据空间大小 db.userInfo.dataSize(); 4、得到当前聚集集合所在的db db.userInfo.getDB(); 5、得到当前聚集的状态 db.userInfo.stats(); 6、得到聚集集合总大小 db.userInfo.totalSize(); 7、聚集集合储存空间大小 db.userInfo.storageSize(); 8、Shard版本信息 db.userInfo.getShardVersion() 9、聚集集合重命名 db.userInfo.renameCollection("users"); 将userInfo重命名为users 10、删除当前聚集集合 db.userInfo.drop(); 复制代码代码如下: show dbs:显示数据库列表 show collections:显示当前数据库中的集合(类似关系数据库中的表) show users:显示用户 use <db name>:切换当前数据库,这和MS-SQL里面的意思一样 db.help():显示数据库操作命令,里面有很多的命令 db.foo.help():显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令 db.foo.find():对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据) db.foo.find( { a : 1 } ):对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1若转载请注明出处!若有疑问,请回复交流!
redis默认只允许本地访问,要使redis可以远程访问可以修改redis.conf 打开redis.conf文件在NETWORK部分有说明 ################################## NETWORK ##################################### # By default, if no "bind" configuration directive is specified, Redis listens # for connections from all the network interfaces available on the server. # It is possible to listen to just one or multiple selected interfaces using # the "bind" configuration directive, followed by one or more IP addresses. # # Examples: # # bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 # # ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the # internet, binding to all the interfaces is dangerous and will expose the # instance to everybody on the internet. So by default we uncomment the # following bind directive, that will force Redis to listen only into # the IPv4 lookback interface address (this means Redis will be able to # accept connections only from clients running into the same computer it # is running). # # IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES # JUST COMMENT THE FOLLOWING LINE. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bind 127.0.0.1 解决办法:注释掉bind 127.0.0.1可以使所有的ip访问redis 若是想指定多个ip访问,但并不是全部的ip访问,可以bind 注意 下面还有个说明 # Protected mode is a layer of security protection, in order to avoid that # Redis instances left open on the internet are accessed and exploited. # # When protected mode is on and if: # # 1) The server is not binding explicitly to a set of addresses using the # "bind" directive. # 2) No password is configured. # # The server only accepts connections from clients connecting from the # IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain # sockets. # # By default protected mode is enabled. You should disable it only if # you are sure you want clients from other hosts to connect to Redis # even if no authentication is configured, nor a specific set of interfaces # are explicitly listed using the "bind" directive. protected-mode yes 在redis3.2之后,redis增加了protected-mode,在这个模式下,即使注释掉了bind 127.0.0.1,再访问redisd时候还是报错,如下 (error) DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside. 修改办法:protected-mode no若转载请注明出处!若有疑问,请回复交流!
转自:http://www.cnblogs.com/yangzhilong/p/5667165.html java后台对前端输入的特殊字符进行转义 HTML: 常见的帮助类有2个:一个是spring的HtmlUtils,另外一个是apache.commons下的StringEscapeUtils 1 public static void testHtml(){ 2 String str = "<a href='http://www.qq.com'>QQ</a><script>"; 3 /** 4 * Spring的HtmlUtils进行转义 5 */ 6 //&lt;a href='http://www.qq.com'&gt;QQ&lt;/a&gt;&lt;script&gt; 7 System.out.println(org.springframework.web.util.HtmlUtils.htmlEscape(str)); 8 //<a href='http://www.qq.com'>QQ</a><script> 9 System.out.println(org.springframework.web.util.HtmlUtils.htmlEscapeDecimal(str)); 10 //<a href='http://www.qq.com'>QQ</a><script> 11 System.out.println(org.springframework.web.util.HtmlUtils.htmlEscapeHex(str)); 12 13 /** 14 * Spring的HtmlUtils进行还原 15 */ 16 //<a href='http://www.qq.com'>QQ</a><script> 17 System.out.println(org.springframework.web.util.HtmlUtils.htmlUnescape("&lt;a href='http://www.qq.com'&gt;QQ&lt;/a&gt;&lt;script&gt;")); 18 //<a href='http://www.qq.com'>QQ</a><script> 19 System.out.println(org.springframework.web.util.HtmlUtils.htmlUnescape("<a href='http://www.qq.com'>QQ</a><script>")); 20 //<a href='http://www.qq.com'>QQ</a><script> 21 System.out.println(org.springframework.web.util.HtmlUtils.htmlUnescape("<a href='http://www.qq.com'>QQ</a><script>")); 22 23 /** 24 * apache的StringEscapeUtils进行转义 25 */ 26 //&lt;a href='http://www.qq.com'&gt;QQ&lt;/a&gt;&lt;script&gt; 27 System.out.println(org.apache.commons.lang.StringEscapeUtils.escapeHtml(str)); 28 29 /** 30 * apache的StringEscapeUtils进行还原 31 */ 32 //<a href='http://www.qq.com'>QQ</a><script> 33 System.out.println(org.apache.commons.lang.StringEscapeUtils.unescapeHtml("&lt;a href='http://www.qq.com'&gt;QQ&lt;/a&gt;&lt;script&gt;")); 34 } JavaScript: 常见的帮助类有2个:一个是spring的JavaScriptUtils,另外一个是apache.commons下的StringEscapeUtils 1 public static void testJavascript(){ 2 String js = "<script type='text/javascript'>var a=10;alert(a);</script>"; 3 /** 4 * Spring的JavaScriptUtils进行转义, 未提供还原的方法 5 */ 6 //\u003Cscript type=\'text\/javascript\'\u003Evar a=10;alert(a);\u003C\/script\u003E 7 System.out.println(org.springframework.web.util.JavaScriptUtils.javaScriptEscape(js)); 8 9 /** 10 * apache的StringEscapeUtils进行转义 11 */ 12 //<script type=\'text\/javascript\'>var a=10;alert(a);<\/script> 13 System.out.println(org.apache.commons.lang.StringEscapeUtils.escapeJavaScript(js)); 14 /** 15 * apache的StringEscapeUtils进行还原 16 */ 17 //<script type='text/javascript'>var a=10;alert(a);</script> 18 System.out.println(org.apache.commons.lang.StringEscapeUtils.unescapeJavaScript(org.apache.commons.lang.StringEscapeUtils.escapeJavaScript(js))); 19 } SQL: apache.commons下的StringEscapeUtils /** * apache的StringEscapeUtils进行转义 */ String sql = "select * from table where username='" + org.apache.commons.lang.StringEscapeUtils.escapeSql("admin' or '1=1") + "' and password='admin'"; //select * from table where username='admin'' or ''1=1' and password='admin' System.out.println(sql); 若转载请注明出处!若有疑问,请回复交流!
转自:http://blog.csdn.net/hj7jay/article/details/51280405 众所周知页面上的字符内容通常都需要进行HTML转义才能正确显示,尤其对于Input,Textarea提交的内容,更是要进行转义以防止javascript注入攻击。 通常的HTML转义主要是针对内容中的"<",">","&",以及空格、单双引号等。但其实还有很多字符也需要进行转义。具体的可以参考这篇文章。 ** 1、HTML转义 参考上面的提到的文章,基本上可以确定以下的转义的范围和方式。 1)对"\""、"&"、"'"、"<"、">"、空格(0x20)、0x00到0x20、0x7F-0xFF 以及0x0100-0x2700的字符进行转义,基本上就覆盖的比较全面了。 用javascript的正则表达式可以写为: this.REGX_HTML_ENCODE = /"|&|'|<|>|[\x00-\x20]|[\x7F-\xFF]|[\u0100-\u2700]/g; 2)为保证转义结果对浏览器的无差别,转义编码为实体编号,而不用实体名称。 3)空格(0x20)通常转义为“ ”也就是“ ”。 转义的代码非常简单: [javascript] view plain copy this.encodeHtml = function(s){ return (typeof s != "string") ? s : s.replace(this.REGX_HTML_ENCODE, function($0){ var c = $0.charCodeAt(0), r = ["&#"]; c = (c == 0x20) ? 0xA0 : c; r.push(c); r.push(";"); return r.join(""); }); }; ** 2、反转义 既然有转义,自然需要反转义。 1) 对“&#num;”实体编号的转义,直接提取编号然后fromCharCode就可以得到字符。 2) 对于诸如“<”,需要建立一张如下的表来查询。 this.HTML_DECODE = { "<" : "<", ">" : ">", "&" : "&", " ": " ", """: "\"", "©": "©" // Add more }; 由此我们可以有反转义的正则表达式: this.REGX_HTML_DECODE = /&\w+;|&#(\d+);/g; 反转的代码也很简单,如下: [javascript] view plain copy this.decodeHtml = function(s){ return (typeof s != "string") ? s : s.replace(this.REGX_HTML_DECODE, function($0,$1){ var c = this.HTML_ENCODE[$0]; // 尝试查表 if(c === undefined){ // Maybe is Entity Number if(!isNaN($1)){ c = String.fromCharCode(($1 == 160) ? 32 : $1); }else{ // Not Entity Number c = $0; } } return c; }); }; ** 3、一个有意思的认识 其实在用正则表达式转义之前,我一直都是用遍历整个字符串,逐个比较字符的方式。直到有一天,看到一篇文章说,javascript正则表达式是C实现的,比自己用javascript遍历字符要快,于是我就试着改写成上面这种方式。虽然代码看起来的确显得神秘而又牛叉,但遗憾的是,在我的Chrome 11 (FreeBSD 64 9.0)上,遍历字符转义/反转的方式要比上面正则表达式的代码快2到3倍(字符串长度越长越明显)。其实,想想也能明白为什么。 ** 4、完整版本的代码 [javascript] view plain copy $package("js.lang"); // 没有包管理时,也可简单写成 js = {lang:{}}; js.lang.String = function(){ this.REGX_HTML_ENCODE = /"|&|'|<|>|[\x00-\x20]|[\x7F-\xFF]|[\u0100-\u2700]/g; this.REGX_HTML_DECODE = /&\w+;|&#(\d+);/g; this.REGX_TRIM = /(^\s*)|(\s*$)/g; this.HTML_DECODE = { "<" : "<", ">" : ">", "&" : "&", " ": " ", """: "\"", "©": "" // Add more }; this.encodeHtml = function(s){ s = (s != undefined) ? s : this.toString(); return (typeof s != "string") ? s : s.replace(this.REGX_HTML_ENCODE, function($0){ var c = $0.charCodeAt(0), r = ["&#"]; c = (c == 0x20) ? 0xA0 : c; r.push(c); r.push(";"); return r.join(""); }); }; this.decodeHtml = function(s){ var HTML_DECODE = this.HTML_DECODE; s = (s != undefined) ? s : this.toString(); return (typeof s != "string") ? s : s.replace(this.REGX_HTML_DECODE, function($0, $1){ var c = HTML_DECODE[$0]; if(c == undefined){ // Maybe is Entity Number if(!isNaN($1)){ c = String.fromCharCode(($1 == 160) ? 32:$1); }else{ c = $0; } } return c; }); }; this.trim = function(s){ s = (s != undefined) ? s : this.toString(); return (typeof s != "string") ? s : s.replace(this.REGX_TRIM, ""); }; this.hashCode = function(){ var hash = this.__hash__, _char; if(hash == undefined || hash == 0){ hash = 0; for (var i = 0, len=this.length; i < len; i++) { _char = this.charCodeAt(i); hash = 31*hash + _char; hash = hash & hash; // Convert to 32bit integer } hash = hash & 0x7fffffff; } this.__hash__ = hash; return this.__hash__; }; }; js.lang.String.call(js.lang.String); 在实际的使用中可以有两种方式: 1)使用js.lang.String.encodeHtml(s)和js.lang.String.decodeHtml(s)。 2)还可以直接扩展String的prototype [javascript] view plain copy js.lang.String.call(String.prototype); // 那么 var str = "&'\"中国abc def"; var ec_str = str.encodeHtml(); document.write(ec_str); document.write(""); // CU的博客在线编辑有bug, 放不上来!!! var dc_str = ec_str.decodeHtml(); document.write(dc_str); 若转载请注明出处!若有疑问,请回复交流!
Mongodb启动命令mongod参数说明mongod的主要参数有: 基本配置-------------------------------------------------------------------------------- --quiet # 安静输出 --port arg # 指定服务端口号,默认端口27017 --bind_ip arg # 绑定服务IP,若绑定127.0.0.1,则只能本机访问,不指定默认本地所有IP --logpath arg # 指定MongoDB日志文件,注意是指定文件不是目录 --logappend # 使用追加的方式写日志 --pidfilepath arg # PID File 的完整路径,如果没有设置,则没有PID文件 --keyFile arg # 集群的私钥的完整路径,只对于Replica Set 架构有效 --unixSocketPrefix arg # UNIX域套接字替代目录,(默认为 /tmp) --fork # 以守护进程的方式运行MongoDB,创建服务器进程 --auth # 启用验证 --cpu # 定期显示CPU的CPU利用率和iowait --dbpath arg # 指定数据库路径 --diaglog arg # diaglog选项 0=off 1=W 2=R 3=both 7=W+some reads --directoryperdb # 设置每个数据库将被保存在一个单独的目录 --journal # 启用日志选项,MongoDB的数据操作将会写入到journal文件夹的文件里 --journalOptions arg # 启用日志诊断选项 --ipv6 # 启用IPv6选项 --jsonp # 允许JSONP形式通过HTTP访问(有安全影响) --maxConns arg # 最大同时连接数 默认2000 --noauth # 不启用验证 --nohttpinterface # 关闭http接口,默认关闭27018端口访问 --noprealloc # 禁用数据文件预分配(往往影响性能) --noscripting # 禁用脚本引擎 --notablescan # 不允许表扫描 --nounixsocket # 禁用Unix套接字监听 --nssize arg (=16) # 设置信数据库.ns文件大小(MB) --objcheck # 在收到客户数据,检查的有效性, --profile arg # 档案参数 0=off 1=slow, 2=all --quota # 限制每个数据库的文件数,设置默认为8 --quotaFiles arg # number of files allower per db, requires --quota --rest # 开启简单的rest API --repair # 修复所有数据库run repair on all dbs --repairpath arg # 修复库生成的文件的目录,默认为目录名称dbpath --slowms arg (=100) # value of slow for profile and console log --smallfiles # 使用较小的默认文件 --syncdelay arg (=60) # 数据写入磁盘的时间秒数(0=never,不推荐) --sysinfo # 打印一些诊断系统信息 --upgrade # 如果需要升级数据库 * Replicaton 参数-------------------------------------------------------------------------------- --fastsync # 从一个dbpath里启用从库复制服务,该dbpath的数据库是主库的快照,可用于快速启用同步 --autoresync # 如果从库与主库同步数据差得多,自动重新同步, --oplogSize arg # 设置oplog的大小(MB) * 主/从参数-------------------------------------------------------------------------------- --master # 主库模式 --slave # 从库模式 --source arg # 从库 端口号 --only arg # 指定单一的数据库复制 --slavedelay arg # 设置从库同步主库的延迟时间 * Replica set(副本集)选项:-------------------------------------------------------------------------------- --replSet arg # 设置副本集名称 * Sharding(分片)选项-------------------------------------------------------------------------------- --configsvr # 声明这是一个集群的config服务,默认端口27019,默认目录/data/configdb --shardsvr # 声明这是一个集群的分片,默认端口27018 --noMoveParanoia # 关闭偏执为moveChunk数据保存 # 上述参数都可以写入 mongod.conf 配置文档里例如:dbpath = /data/mongodblogpath = /data/mongodb/mongodb.loglogappend = trueport = 27017fork = trueauth = true e.g:./mongod -shardsvr -replSet shard1 -port 16161 -dbpath /data/mongodb/data/shard1a -oplogSize 100 -logpath /data/mongodb/logs/shard1a.log -logappend -fork -rest 若转载请注明出处!若有疑问,请回复交流!
在搭建SpringMVC环境,在使用中遇到了多次Bad Request的连接,下面来总结下. 1.参数类型不对,如后台实体类的属性为int,但传来的参数为字符串 2.因为我的粗心,本来是要通过Ajax获得一个json串,但是后台的方法在返回值类型前没有加@RequestBody注解 3.传递的参数为日期,spring不知道该以什么格式转换为Date类型,解决办法为在实体类的日期属性上加上@DateTimeFormat(pattern="yyyy-MM-dd")注解即可 4.刚遇到的问题,排查了好久终于知道是什么原因了,实体类中有int类型的属性,但是前台传参时传递的样子是这样的"age=",并没有给一个准确的数字(age=18),所以导致Spring在对int型属性进行赋值时无法正确赋值 目前就遇到了这几个原因导致Bad Request连接的,欢迎大家补充,我也会持续更新 转自:http://blog.csdn.net/c5906343/article/details/26482975 若转载请注明出处!若有疑问,请回复交流!
pom.xml 内容: [html] view plain copy <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> </dependency> 报错误:Missing artifact net.sf.json-lib:json-lib:jar:2.4:compile 原因:json-lib是需要区分jdk版本的,pom.xml中的配置应加上标签classifier指定jdk版本,如用jdk15 修改为: [html] view plain copy <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier><!--指定jdk版本--> t;/dependency> 类似问题: maven javax.transaction:jta:jar:1.0.1B:compile错误提示: 解决办法: <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.1.ga</version> <optional>false</optional> <exclusions> <exclusion> <artifactId>jta</artifactId> <groupId>javax.transaction</groupId> </exclusion> </exclusions> </dependency> log4j.jar引起的missing artifact javax jms jms jar 1.1问题: 解决办法:原因是log4j在1.2.15及以上版本更换了协议,与jms冲突,所以用log4j的1.2.14版本就可以啦 <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency>若转载请注明出处!若有疑问,请回复交流!
转自http://www.iyunv.com/thread-38535-1-1.html 公司业务线上对后端节点的健康检查是通过nginx_upstream_check_module模块做的,这里我将分别介绍这三种实现方式以及之间的差异性。 一、ngx_http_proxy_module 模块和ngx_http_upstream_module模块(自带) 严格来说,nginx自带是没有针对负载均衡后端节点的健康检查的,但是可以通过默认自带的ngx_http_proxy_module 模块和ngx_http_upstream_module模块中的相关指令来完成当后端节点出现故障时,自动切换到健康节点来提供访问。 这里列出这两个模块中相关的指令:ngx_http_proxy_module 模块中的 proxy_connect_timeout 指令、proxy_read_timeout指令和proxy_next_upstream指令 123 语法: proxy_connect_timeout time;默认值: proxy_connect_timeout 60s;上下文: http, server, location 设置与后端服务器建立连接的超时时间。应该注意这个超时一般不可能大于75秒。 123 语法: proxy_read_timeout time;默认值: proxy_read_timeout 60s;上下文: http, server, location 定义从后端服务器读取响应的超时。此超时是指相邻两次读操作之间的最长时间间隔,而不是整个响应传输完成的最长时间。如果后端服务器在超时时间段内没有传输任何数据,连接将被关闭。 123 语法: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 |http_404 | off ...;默认值: proxy_next_upstream error timeout;上下文: http, server, location 指定在何种情况下一个失败的请求应该被发送到下一台后端服务器: 123456789 error # 和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现错误timeout # 和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现超时invalid_header # 后端服务器返回空响应或者非法响应头http_500 # 后端服务器返回的响应状态码为500http_502 # 后端服务器返回的响应状态码为502http_503 # 后端服务器返回的响应状态码为503http_504 # 后端服务器返回的响应状态码为504http_404 # 后端服务器返回的响应状态码为404off # 停止将请求发送给下一台后端服务器 需要理解一点的是,只有在没有向客户端发送任何数据以前,将请求转给下一台后端服务器才是可行的。也就是说,如果在传输响应到客户端时出现错误或者超时,这类错误是不可能恢复的。 范例如下: 123 http {proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;} ngx_http_upstream_module模块中的server指令 123 语法: server address [parameters];默认值: —上下文: upstream 范例如下: 1234 upstream name { server 10.1.1.110:8080 max_fails=1 fail_timeout=10s; server 10.1.1.122:8080 max_fails=1 fail_timeout=10s; } 下面是每个指令的介绍: 123456 max_fails=number # 设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout时间段,服务器不会再被尝试。 失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。 你可以通过指令proxy_next_upstream、fastcgi_next_upstream和 memcached_next_upstream来配置什么是失败的尝试。 默认配置时,http_404状态不被认为是失败的尝试。fail_timeout=time # 设定服务器被认为不可用的时间段以及统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。默认情况下,该超时时间是10秒。 在实际应用当中,如果你后端应用是能够快速重启的应用,比如nginx的话,自带的模块是可以满足需求的。但是需要注意。如果后端有不健康节点,负载均衡器依然会先把该请求转发给该不健康节点,然后再转发给别的节点,这样就会浪费一次转发。 可是,如果当后端应用重启时,重启操作需要很久才能完成的时候就会有可能拖死整个负载均衡器。此时,由于无法准确判断节点健康状态,导致请求handle住,出现假死状态,最终整个负载均衡器上的所有节点都无法正常响应请求。由于公司的业务程序都是java开发的,因此后端主要是nginx集群和tomcat集群。由于tomcat重启应部署上面的业务不同,有些业务启动初始化时间过长,就会导致上述现象的发生,因此不是很建议使用该模式。 并且ngx_http_upstream_module模块中的server指令中的max_fails参数设置值,也会和ngx_http_proxy_module 模块中的的proxy_next_upstream指令设置起冲突。比如如果将max_fails设置为0,则代表不对后端服务器进行健康检查,这样还会使fail_timeout参数失效(即不起作用)。此时,其实我们可以通过调节ngx_http_proxy_module 模块中的 proxy_connect_timeout 指令、proxy_read_timeout指令,通过将他们的值调低来发现不健康节点,进而将请求往健康节点转移。 以上就是nginx自带的两个和后端健康检查相关的模块。 二、nginx_upstream_check_module模块 除了自带的上述模块,还有一个更专业的模块,来专门提供负载均衡器内节点的健康检查的。这个就是淘宝技术团队开发的 nginx 模块 nginx_upstream_check_module,通过它可以用来检测后端 realserver 的健康状态。如果后端 realserver 不可用,则所以的请求就不会转发到该节点上。 在淘宝自己的 tengine 上是自带了该模块的,大家可以访问淘宝tengine的官网来获取该版本的nginx,官方地址:http://tengine.taobao.org/。 如果我们没有使用淘宝的 tengine 的话,可以通过补丁的方式来添加该模块到我们自己的 nginx 中。我们业务线上就是采用该方式进行添加的。 下面是部署流程!1、下载nginx_upstream_check_module模块 12345 [iyunv@localhost ~]# cd /usr/local/srcwget https://codeload.github.com/yaow ... k_module/zip/masterunzip master[iyunv@localhost /usr/local/src]# ll -d nginx_upstream_check_module-masterdrwxr-xr-x. 6 root root 4096 Dec 1 02:28 nginx_upstream_check_module-master 2、为nginx打补丁 12345678 [iyunv@localhost /usr/local/src]# cd nginx-1.6.0 # 进入nginx的源码目录[iyunv@localhost nginx-1.6.0]# patch -p1 < ../nginx_upstream_check_module-master/check_1.5.12+.patch[iyunv@localhost nginx-1.6.0]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx-1.6.0 --with-http_ssl_module --with-openssl=/usr/local/src/openssl-0.9.8q --with-pcre=/usr/local/src/pcre-8.32 --add-module=/usr/local/src/nginx_concat_module/ --add-module=../nginx_upstream_check_module-master/make (注意:此处只make,编译参数需要和之前的一样)[iyunv@localhost nginx-1.6.0]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-1.6.0.bak[iyunv@localhost nginx-1.6.0]# cp ./objs/nginx /usr/local/nginx/sbin/[iyunv@localhost nginx-1.6.0]# /usr/local/nginx/sbin/nginx -t # 检查下是否有问题[iyunv@localhost nginx-1.6.0]# kill -USR2 `cat /usr/local/nginx/logs/nginx.pid` 3、在nginx.conf配置文件里面的upstream加入健康检查,如下: 123456 upstream name { server 192.168.0.21:80; server 192.168.0.22:80; check interval=3000 rise=2 fall=5 timeout=1000 type=http; } 上面配置的意思是,对name这个负载均衡条目中的所有节点,每个3秒检测一次,请求2次正常则标记 realserver状态为up,如果检测 5 次都失败,则标记 realserver的状态为down,超时时间为1秒。 这里列出nginx_upstream_check_module模块所支持的指令意思: 123 Syntax: check interval=milliseconds [fall=count] [rise=count] [timeout=milliseconds] [default_down=true|false] [type=tcp|http|ssl_hello|mysql|ajp] [port=check_port]Default: 如果没有配置参数,默认值是:interval=30000 fall=5 rise=2 timeout=1000 default_down=true type=tcpContext: upstream 该指令可以打开后端服务器的健康检查功能。 指令后面的参数意义是: 123456789101112 - interval:向后端发送的健康检查包的间隔。 - fall(fall_count): 如果连续失败次数达到fall_count,服务器就被认为是down。 - rise(rise_count): 如果连续成功次数达到rise_count,服务器就被认为是up。 - timeout: 后端健康请求的超时时间。 - default_down: 设定初始时服务器的状态,如果是true,就说明默认是down的,如果是false,就是up的。默认值是true,也就是一开始服务器认为是不可用,要等健康检查包达到一定成功次数以后才会被认为是健康的。 - type:健康检查包的类型,现在支持以下多种类型 - tcp:简单的tcp连接,如果连接成功,就说明后端正常。 - ssl_hello:发送一个初始的SSL hello包并接受服务器的SSL hello包。 - http:发送HTTP请求,通过后端的回复包的状态来判断后端是否存活。 - mysql: 向mysql服务器连接,通过接收服务器的greeting包来判断后端是否存活。 - ajp:向后端发送AJP协议的Cping包,通过接收Cpong包来判断后端是否存活。 - port: 指定后端服务器的检查端口。你可以指定不同于真实服务的后端服务器的端口,比如后端提供的是443端口的应用,你可以去检查80端口的状态来判断后端健康状况。默认是0,表示跟后端server提供真实服务的端口一样。该选项出现于Tengine-1.4.0。 123 Syntax: check_keepalive_requests request_numDefault: 1Context: upstream 该指令可以配置一个连接发送的请求数,其默认值为1,表示Tengine完成1次请求后即关闭连接。 123 Syntax: check_http_send http_packetDefault: "GET / HTTP/1.0\r\n\r\n"Context: upstream 该指令可以配置http健康检查包发送的请求内容。为了减少传输数据量,推荐采用"HEAD"方法。 当采用长连接进行健康检查时,需在该指令中添加keep-alive请求头,如:"HEAD / HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"。 同时,在采用"GET"方法的情况下,请求uri的size不宜过大,确保可以在1个interval内传输完成,否则会被健康检查模块视为后端服务器或网络异常。 123 Syntax: check_http_expect_alive [ http_2xx | http_3xx | http_4xx | http_5xx ]Default: http_2xx | http_3xxContext: upstream 该指令指定HTTP回复的成功状态,默认认为2XX和3XX的状态是健康的。 123 Syntax: check_shm_size sizeDefault: 1MContext: http 所有的后端服务器健康检查状态都存于共享内存中,该指令可以设置共享内存的大小。默认是1M,如果你有1千台以上的服务器并在配置的时候出现了错误,就可能需要扩大该内存的大小。 123 Syntax: check_status [html|csv|json]Default: check_status htmlContext: location 显示服务器的健康状态页面。该指令需要在http块中配置。 在Tengine-1.4.0以后,你可以配置显示页面的格式。支持的格式有: html、csv、 json。默认类型是html。 你也可以通过请求的参数来指定格式,假设‘/status’是你状态页面的URL, format参数改变页面的格式,比如: 123 /status?format=html/status?format=csv/status?format=json 同时你也可以通过status参数来获取相同服务器状态的列表,比如: 12 /status?format=html&status=down/status?format=csv&status=up 下面是一个状态也配置的范例: 12345678910 http { server { location /nstatus { check_status; access_log off; #allow IP; #deny all; } }} 配置完毕后,重启nginx。此时通过访问定义好的路径,就可以看到当前 realserver 实时的健康状态啦。效果如下图:realserver 都正常的状态: 一台 realserver 故障的状态: OK,以上nginx_upstream_check_module模块的相关信息,更多的信息大家可以去该模块的淘宝tengine页面和github上该项目页面去查看,下面是访问地址:http://tengine.taobao.org/document_cn/http_upstream_check_cn.html https://github.com/yaoweibin/nginx_upstream_check_module 在生产环境的实施应用中,需要注意的有 2 点:1、主要定义好type。由于默认的type是tcp类型,因此假设你服务启动,不管是否初始化完毕,它的端口都会起来,所以此时前段负载均衡器为认为该服务已经可用,其实是不可用状态。2、注意check_http_send值的设定。由于它的默认值是"GET / HTTP/1.0\r\n\r\n"。假设你的应用是通过http://ip/name访问的,那么这里你的check_http_send值就需要更改为"GET /name HTTP/1.0\r\n\r\n"才可以。针对采用长连接进行检查的,这里增加keep-alive请求头,即"HEAD /name HTTP/1.1\r\nConnection: keep-alive\r\n\r\n"。如果你后端的tomcat是基于域名的多虚拟机,此时你需要通过check_http_send定义host,不然每次访问都是失败,范例:check_http_send "GET /mobileapi HTTP/1.0\r\n HOST www.redhat.sx\r\n\r\n";三、ngx_http_healthcheck_module模块 除了上面两个模块,nginx官方在早期的时候还提供了一个 ngx_http_healthcheck_module 模块用来进行nginx后端节点的健康检查。nginx_upstream_check_module模块就是参照该模块的设计理念进行开发的,因此在使用和效果上都大同小异。但是需要注意的是,ngx_http_healthcheck_module 模块仅仅支持nginx的1.0.0版本,1.1.0版本以后都不支持了!因此,对于目前常见的生产环境上都不会去用了,这里仅仅留个纪念,给大家介绍下这个模块! 具体的使用方法,这里可以贴出几篇靠谱的博文地址以及官方地址: http://wiki.nginx.org/HttpHealthcheckModule https://github.com/cep21/healthcheck_nginx_upstreams/blob/master/README若转载请注明出处!若有疑问,请回复交流!
CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙。 1、关闭firewall: systemctl stop firewalld.service #停止firewall systemctl disable firewalld.service #禁止firewall开机启动 2、安装iptables防火墙 yum install iptables-services #安装 vi /etc/sysconfig/iptables #编辑防火墙配置文件 # Firewall configuration written by system-config-firewall # Manual customization of this file is not recommended. *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT :wq! #保存退出 systemctl restart iptables.service #最后重启防火墙使配置生效 systemctl enable iptables.service #设置防火墙开机启动若转载请注明出处!若有疑问,请回复交流!
nginx -s reload :修改配置后重新加载生效 nginx -s reopen :重新打开日志文件nginx -t -c /path/to/nginx.conf 测试nginx配置文件是否正确关闭nginx:nginx -s stop :快速停止nginx quit :完整有序的停止nginx其他的停止nginx 方式:ps -ef | grep nginxkill -QUIT 主进程号 :从容停止Nginxkill -TERM 主进程号 :快速停止Nginxpkill -9 nginx :强制停止Nginx启动nginx:nginx -c /path/to/nginx.conf平滑重启nginx:kill -HUP 主进程号 若转载请注明出处!若有疑问,请回复交流!
反向代理适用于很多场合,负载均衡是最普遍的用法。 nginx 作为目前最流行的web服务器之一,可以很方便地实现反向代理。 nginx 反向代理官方文档: NGINX REVERSE PROXY 当在一台主机上部署了多个不同的web服务器,并且需要能在80端口同时访问这些web服务器时,可以使用 nginx 的反向代理功能: 用 nginx 在80端口监听所有请求,并依据转发规则(比较常见的是以 URI 来转发)转发到对应的web服务器上。 例如有 webmail , webcom 以及 webdefault 三个服务器分别运行在 portmail , portcom , portdefault 端口,要实现从80端口同时访问这三个web服务器,则可以在80端口运行 nginx, 然后将 /mail 下的请求转发到 webmail 服务器, 将 /com下的请求转发到 webcom 服务器, 将其他所有请求转发到 webdefault 服务器。 假设服务器域名为example.com,则对应的 nginx http配置如下: http { server { server_name example.com; location /mail/ { proxy_pass http://example.com:protmail/; } location /com/ { proxy_pass http://example.com:portcom/main/; } location / { proxy_pass http://example.com:portdefault; } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 以上的配置会按以下规则转发请求( GET 和 POST 请求都会转发): 将 http://example.com/mail/ 下的请求转发到 http://example.com:portmail/ 将 http://example.com/com/ 下的请求转发到 http://example.com:portcom/main/ 将其它所有请求转发到 http://example.com:portdefault/ 需要注意的是,在以上的配置中,webdefault 的代理服务器设置是没有指定URI的,而 webmail 和 webcom 的代理服务器设置是指定了URI的(分别为 / 和 /main/)。 如果代理服务器地址中是带有URI的,此URI会替换掉 location 所匹配的URI部分。 而如果代理服务器地址中是不带有URI的,则会用完整的请求URL来转发到代理服务器。 官方文档描述: If the URI is specified along with the address, it replaces the part of the request URI that matches the location parameter. If the address is specified without a URI, or it is not possible to determine the part of URI to be replaced, the full request URI is passed (possibly, modified). 以上配置的转发示例: http://example.com/mail/index.html -> http://example.com:portmail/index.html http://example.com/com/index.html -> http://example.com:portcom/main/index.html http://example.com/mail/static/a.jpg -> http://example.com:portmail/static/a.jpg http://example.com/com/static/b.css -> http://example.com:portcom/main/static/b.css http://example.com/other/index.htm -> http://example.com:portdefault/other/index.htm 若转载请注明出处!若有疑问,请回复交流!
CentOS系统也是基于linux中的它的防火墙其实就是iptables了,下面我来介绍在CentOS防火墙iptables的配置教程,希望此教程对各位朋友会有所帮助。 iptables是与Linux内核集成的IP信息包过滤系统,其自带防火墙功能,我们在配置完服务器的角色功能后,需要修改iptables的配置。 配置CentOS和Ubuntu等Linux服务器时需要对服务器的iptables进行配置,以下是iptables常见的几种配置方法。 1.查看当前所有的iptables配置 代码如下 复制代码 iptables -L -n 2.添加允许INPUT访问规则,以下时常见服务的端口设置,如果需要拒绝访问,则将ACCEPT改为DROP即可 代码如下 复制代码 #SSH iptables -A INPUT -p tcp --dport 22 -j ACCEPT #HTTP iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 8080 -j ACCEPT #HTTPS iptables -A INPUT -p tcp --dport 443 -j ACCEPT #POP3 iptables -A INPUT -p tcp --dport 110 -j ACCEPT #SMTP iptables -A INPUT -p tcp --dport 25 -j ACCEPT #FTP iptables -A INPUT -p tcp --dport 21 -j ACCEPT iptables -A INPUT -p tcp --dport 20 -j ACCEPT #DNS iptables -A INPUT -p tcp --dport 53 -j ACCEPT 3.添加使用IP限制INPUT访问规则,这里拿SSH为例,192.168.0.100为允许的IP 代码如下 复制代码 #DELETE iptables -D INPUT -p tcp --dport 22 -j ACCEPT #ADD iptables -A INPUT -s 192.168.0.100 -p tcp --dport 22 -j ACCEPT 4.保存iptables的设置,修改完规则后记得保存 代码如下 复制代码 /etc/rc.d/init.d/iptables save 5.重启iptables 代码如下 复制代码 service iptables restart 6.开启/关闭 开机启动 代码如下 复制代码 chkconfig iptables on chkconfig iptables off 7 .打开iptables的配置文件: 代码如下 复制代码 vi /etc/sysconfig/iptables 通过/etc/init.d/iptables status命令查询是否有打开80端口,如果没有可通过两种方式处理: 8.修改vi /etc/sysconfig/iptables命令添加使防火墙开放80端口 代码如下 复制代码 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT 9.关闭/开启/重启防火墙 代码如下 复制代码 /etc/init.d/iptables stop #start 开启 #restart 重启 10.永久性关闭防火墙 代码如下 复制代码 chkconfig --level 35 iptables off /etc/init.d/iptables stop iptables -P INPUT DROP 11.打开主动模式21端口 代码如下 复制代码 iptables -A INPUT -p tcp --dport 21 -j ACCEPT 12.打开被动模式49152~65534之间的端口 代码如下 复制代码 iptables -A INPUT -p tcp --dport 49152:65534 -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT 注意: 一定要给自己留好后路,留VNC一个管理端口和SSh的管理端口 需要注意的是,你必须根据自己服务器的情况来修改这个文件。 全部修改完之后重启iptables: 代码如下 复制代码 service iptables restart 你可以验证一下是否规则都已经生效: 代码如下 复制代码 iptables -L 通过文章的介绍,我们清楚的知道了CentOS下配置iptables防火墙的过程若转载请注明出处!若有疑问,请回复交流!
目标:Nginx做为HttpServer,连接多个tomcat应用实例,进行负载均衡。 注:本例程以一台机器为例子,即同一台机器上装一个nginx和2个Tomcat且安装了JDK1.7。 1、安装Nginx安装Nginx教程 2、配置两个Tomcat在本机上配置两个Tomcat,分别为tomcat7-8081、tomcat7-8082。tomcat7-8081访问地址:http://localhost:8081,浏览显示内容:this is 8081 porttomcat7-8082访问地址:http://localhost:8082,浏览显示内容:this is 8082 port usr/loacl/tomcat/tomcat7-8081/webapps/ROOT/index.jsp文件内容为: <!DOCTYPE html> <html lang="en"> <head>this is 8081 port</head> </html>usr/loacl/tomcat/tomcat7-8082/webapps/ROOT/index.jsp文件内容为: <!DOCTYPE html> <html lang="en"> <head>this is 8082 port</head> </html> 在同一台服务器上配置多个Tomcat教程 这样我们就成功的搭建了一个nginx服务,成功的配置了两个tomcat应用实例。 3、Nginx+Tomcat负载均衡配置这里只需要修改Nginx的配置,让它通过tomcat来转发。a、nginx.conf配置文件 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 10; include extra/upstream01.conf; } b、extra/upstream01.conf文件,负载均衡配置信息 upstream mysite { server localhost:8081 weight=5; server localhost:8082 weight=5; } server { listen 80; server_name localhost; location / { proxy_pass http://mysite; } } 当有请求到localhost时,请求会被分发到对应的upstream设置的服务器列表上,每一次请求分发的服务器都是随机的。 接着在运行一次start nginx,当你不断刷新http://localhost的时候,浏览器上就会来回切换"this is 8081 port"和"this is 8082 port"。 这样说明负载均衡配置成功了!!!!!!若转载请注明出处!若有疑问,请回复交流!
转自:http://www.nginx.cn/install nginx可以使用各平台的默认包来安装,本文是介绍使用源码编译安装,包括具体的编译参数信息。 正式开始前,编译环境gcc g++ 开发库之类的需要提前装好,这里默认你已经装好。 ububtu平台编译环境可以使用以下指令 1 2 apt-get install build-essential apt-get install libtool centos平台编译环境使用如下指令 安装make: 1 yum -y install gcc automake autoconf libtool make 安装g++: 1 yum install gcc gcc-c++ 下面正式开始---------------------------------------------------------------------------一般我们都需要先装pcre, zlib,前者为了重写rewrite,后者为了gzip压缩。1.选定源码目录可以是任何目录,本文选定的是/usr/local/src 1 cd /usr/local/src 2.安装PCRE库ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 下载最新的 PCRE 源码包,使用下面命令下载编译和安装 PCRE 包: 1 2 3 4 5 6 7 cd /usr/local/src wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.37.tar.gz tar -zxvf pcre-8.39.tar.gz cd pcre-8.34 ./configure make make install 3.安装zlib库http://zlib.net/zlib-1.2.8.tar.gz 下载最新的 zlib 源码包,使用下面命令下载编译和安装 zlib包: 1 2 3 4 5 6 7 8 cd /usr/local/src wget http://zlib.net/zlib-1.2.8.tar.gz tar -zxvf zlib-1.2.8.tar.gz cd zlib-1.2.8 ./configure make make install 4.安装ssl(某些vps默认没装ssl) 1 2 3 cd /usr/local/src wget https://www.openssl.org/source/openssl-1.0.1t.tar.gz tar -zxvf openssl-1.0.1t.tar.gz 5.安装nginx Nginx 一般有两个版本,分别是稳定版和开发版,您可以根据您的目的来选择这两个版本的其中一个,下面是把 Nginx 安装到 /usr/local/nginx 目录下的详细步骤: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cd /usr/local/src wget http://nginx.org/download/nginx-1.4.2.tar.gz tar -zxvf nginx-1.4.2.tar.gz cd nginx-1.4.2 ./configure --sbin-path=/usr/local/nginx/nginx \ --conf-path=/usr/local/nginx/nginx.conf \ --pid-path=/usr/local/nginx/nginx.pid \ --with-http_ssl_module \ --with-pcre=/opt/app/openet/oetal1/chenhe/pcre-8.39 \ --with-zlib=/opt/app/openet/oetal1/chenhe/zlib-1.2.8 \ --with-openssl=/opt/app/openet/oetal1/chenhe/openssl-1.0.1t make make install --with-pcre=/usr/src/pcre-8.34 指的是pcre-8.34 的源码路径。--with-zlib=/usr/src/zlib-1.2.7 指的是zlib-1.2.7 的源码路径。 安装成功后 /usr/local/nginx 目录下如下 1 2 3 4 5 6 fastcgi.conf koi-win nginx.conf.default fastcgi.conf.default logs scgi_params fastcgi_params mime.types scgi_params.default fastcgi_params.default mime.types.default uwsgi_params html nginx uwsgi_params.default koi-utf nginx.conf win-utf 6.启动确保系统的 80 端口没被其他程序占用,运行/usr/local/nginx/nginx 命令来启动 Nginx, 1 netstat -ano|grep 80 如果查不到结果后执行,有结果则忽略此步骤(ubuntu下必须用sudo启动,不然只能在前台运行) 1 sudo /usr/local/nginx/nginx 打开浏览器访问此机器的 IP,如果浏览器出现 Welcome to nginx! 则表示 Nginx 已经安装并运行成功。 -----------------------------------------------------到这里nginx就安装完成了,如果只是处理静态html就不用继续安装了 如果你需要处理php脚本的话,还需要安装php-fpm。 下面安装排错 附:可能遇到的错误和一些帮助信息 1.1编译pcre错误 1 2 3 4 5 libtool: compile: unrecognized option `-DHAVE_CONFIG_H' libtool: compile: Try `libtool --help' for more information. make[1]: *** [pcrecpp.lo] Error 1 make[1]: Leaving directory `/usr/local/src/pcre-8.34' make: *** [all] Error 2 解决办法:安装g++,别忘了重新configure 1 2 3 4 5 apt-get install g++ apt-get install build-essential make clean ./configure make 1.2 make出错 1 2 3 4 5 make: *** No rule to make target `build', needed by `default'. Stop. ./configure: error: SSL modules require the OpenSSL library. You can either do not enable the modules, or install the OpenSSL library into the system, or build the OpenSSL library statically from the source with nginx by using --with-openssl=<path> option. 按照第4步的安装方法或ubuntu下 1 2 apt-get install openssl apt-get install libssl-dev centos下 1 yum -y install openssl openssl-devel 2.nginx编译选项 make是用来编译的,它从Makefile中读取指令,然后编译。 make install是用来安装的,它也从Makefile中读取指令,安装到指定的位置。 configure命令是用来检测你的安装平台的目标特征的。它定义了系统的各个方面,包括nginx的被允许使用的连接处理的方法,比如它会检测你是不是有CC或GCC,并不是需要CC或GCC,它是个shell脚本,执行结束时,它会创建一个Makefile文件。nginx的configure命令支持以下参数: --prefix=path 定义一个目录,存放服务器上的文件 ,也就是nginx的安装目录。默认使用 /usr/local/nginx。 --sbin-path=path 设置nginx的可执行文件的路径,默认为 prefix/sbin/nginx. --conf-path=path 设置在nginx.conf配置文件的路径。nginx允许使用不同的配置文件启动,通过命令行中的-c选项。默认为prefix/conf/nginx.conf. --pid-path=path 设置nginx.pid文件,将存储的主进程的进程号。安装完成后,可以随时改变的文件名 , 在nginx.conf配置文件中使用 PID指令。默认情况下,文件名 为prefix/logs/nginx.pid. --error-log-path=path 设置主错误,警告,和诊断文件的名称。安装完成后,可以随时改变的文件名 ,在nginx.conf配置文件中 使用 的error_log指令。默认情况下,文件名 为prefix/logs/error.log. --http-log-path=path 设置主请求的HTTP服务器的日志文件的名称。安装完成后,可以随时改变的文件名 ,在nginx.conf配置文件中 使用 的access_log指令。默认情况下,文件名 为prefix/logs/access.log. --user=name 设置nginx工作进程的用户。安装完成后,可以随时更改的名称在nginx.conf配置文件中 使用的 user指令。默认的用户名是nobody。 --group=name 设置nginx工作进程的用户组。安装完成后,可以随时更改的名称在nginx.conf配置文件中 使用的 user指令。默认的为非特权用户。 --with-select_module --without-select_module 启用或禁用构建一个模块来允许服务器使用select()方法。该模块将自动建立,如果平台不支持的kqueue,epoll,rtsig或/dev/poll。 --with-poll_module --without-poll_module 启用或禁用构建一个模块来允许服务器使用poll()方法。该模块将自动建立,如果平台不支持的kqueue,epoll,rtsig或/dev/poll。 --without-http_gzip_module — 不编译压缩的HTTP服务器的响应模块。编译并运行此模块需要zlib库。 --without-http_rewrite_module 不编译重写模块。编译并运行此模块需要PCRE库支持。 --without-http_proxy_module — 不编译http_proxy模块。 --with-http_ssl_module — 使用https协议模块。默认情况下,该模块没有被构建。建立并运行此模块的OpenSSL库是必需的。 --with-pcre=path — 设置PCRE库的源码路径。PCRE库的源码(版本4.4 - 8.30)需要从PCRE网站下载并解压。其余的工作是Nginx的./ configure和make来完成。正则表达式使用在location指令和 ngx_http_rewrite_module 模块中。 --with-pcre-jit —编译PCRE包含“just-in-time compilation”(1.1.12中, pcre_jit指令)。 --with-zlib=path —设置的zlib库的源码路径。要下载从 zlib(版本1.1.3 - 1.2.5)的并解压。其余的工作是Nginx的./ configure和make完成。ngx_http_gzip_module模块需要使用zlib 。 --with-cc-opt=parameters — 设置额外的参数将被添加到CFLAGS变量。例如,当你在FreeBSD上使用PCRE库时需要使用:--with-cc-opt="-I /usr/local/include。.如需要需要增加 select()支持的文件数量:--with-cc-opt="-D FD_SETSIZE=2048". --with-ld-opt=parameters —设置附加的参数,将用于在链接期间。例如,当在FreeBSD下使用该系统的PCRE库,应指定:--with-ld-opt="-L /usr/local/lib". 典型实例(下面为了展示需要写在多行,执行时内容需要在同一行) 1 2 3 4 5 6 7 ./configure --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_ssl_module --with-pcre=../pcre-4.4 --with-zlib=../zlib-1.1.3 若转载请注明出处!若有疑问,请回复交流!
使用mybatis配置映射文件比较的麻烦,但是有自动生成jar工具,方便加速开发速度,下面主要是该工具的使用以及相关的配置。 1、下载相关的资源 我们需要下载mybatis-generator-core-1.3.2.jar,MySQL-connector-Java-5.1.34.jar(对应相关数据库的驱动包),generator.xml(配置文件) 我的网盘全部相关下载地址:http://pan.baidu.com/s/1ntn48pb 文件结构为: 2、配置generator.xml文件 [html] view plain copy <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- 数据库驱动包位置 --> <classPathEntry location="D:\generator\mysql-connector-java-5.1.34.jar" /> <!-- <classPathEntry location="C:\oracle\product\10.2.0\db_1\jdbc\lib\ojdbc14.jar" />--> <context id="DB2Tables" targetRuntime="MyBatis3"> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 数据库链接URL、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/shop" userId="root" password="12345"> <!--<jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@localhost:1521:orcl" userId="msa" password="msa">--> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- 生成模型的包名和位置 --> <javaModelGenerator targetPackage="andy.model" targetProject="D:\generator\src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- 生成的映射文件包名和位置 --> <sqlMapGenerator targetPackage="andy.mapping" targetProject="D:\generator\src"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- 生成DAO的包名和位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="andy.dao" targetProject="D:\generator\src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 要生成那些表(更改tableName和domainObjectName就可以) --> <table tableName="user_info" domainObjectName="UserInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" /> <table tableName="course_info" domainObjectName="CourseInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" /> <table tableName="course_user_info" domainObjectName="CourseUserInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" /> </context> </generatorConfiguration> 需要修改对应数据库的驱动文件位置,以数据库名密码。 设置对应的生成表的表名以及对应的类名,这样就自动生成了model,dao,mappding配置文件。 3、生成配置文件 打开cmd,进入目录generator,执行命令 java -jar mybatis-generator-core-1.3.2.jar -configfile generator.xml -overwrite 执行完后就自动生成dao,mapping,model文件内容了。 4、另一种生成方式 和上面的类似,这种的是以项目运行来生成配置文件内容, 百度地址下载 转自: http://blog.csdn.net/fengshizty/article/details/43086833 若转载请注明出处!若有疑问,请回复交流!
安装mysql后,启动时候没有启动成功,查看了下日志报错如下:---------------------------------------------1 可以:初始化mysql:mysql_install_db2 目录权限问题chown -R mysql:mysql /var/lib/mysql[root@localhost local]# less /var/log/mysqld.log1、查看报错信息如下:[ERROR] Fatal error: Can't open and lock privilege tables: Table 'mysql.host' doesn't exist2、经过查阅资料得知。要敲如下命令解决:mysql_install_db –usrer=mysql datadir=/var/lib/mysqldatadir是我的mysql存放文件目录3、然后重启mysql还是不行:MySQL Daemon failed to start.正在启动 mysqld: [失败]4、然后试了下单独的命令,启动完成mysql_install_db5、启动mysql服务[root@mysql mysqld]# /etc/init.d/mysqld restart停止 mysqld: [确定]正在启动 mysqld: [确定]若转载请注明出处!若有疑问,请回复交流!
网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWidth (包括边线的宽) 网页可见区域高:document.body.offsetHeight (包括边线的宽) 网页正文全文宽:document.body.scrollWidth 网页正文全文高:document.body.scrollHeight 网页被卷去的高:document.body.scrollTop 网页被卷去的左:document.body.scrollLeft 网页正文部分上:window.screenTop 网页正文部分左:window.screenLeft 屏幕分辨率的高:window.screen.height 屏幕分辨率的宽:window.screen.width 屏幕可用工作区高度:window.screen.availHeight 屏幕可用工作区宽度:window.screen.availWidth HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth scrollHeight: 获取对象的滚动高度。 scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离 scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 scrollWidth:获取对象的滚动宽度 offsetHeight:获取对象相对于版面或由父坐标 offsetParent 属性指定的父坐标的高度 offsetLeft:获取对象相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置 offsetTop:获取对象相对于版面或由 offsetTop 属性指定的父坐标的计算顶端位置 event.clientX 相对文档的水平座标 event.clientY 相对文档的垂直座标 event.offsetX 相对容器的水平坐标 event.offsetY 相对容器的垂直坐标 document.documentElement.scrollTop 垂直方向滚动的值 event.clientX+document.documentElement.scrollTop 相对文档的水平座标+垂直方向滚动的量 IE,FireFox 差异如下: IE6.0、FF1.06+: clientWidth = width + padding clientHeight = height + padding offsetWidth = width + padding + border offsetHeight = height + padding + border IE5.0/5.5: clientWidth = width - border clientHeight = height - border offsetWidth = width offsetHeight = height (需要提一下:CSS中的margin属性,与clientWidth、offsetWidth、clientHeight、offsetHeight均无关) 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网页可见区域宽: document.body.offsetWidth (包括边线的宽)网页可见区域高: document.body.offsetHeight (包括边线的高)网页正文全文宽: document.body.scrollWidth网页正文全文高: document.body.scrollHeight网页被卷去的高: document.body.scrollTop网页被卷去的左: document.body.scrollLeft网页正文部分上: window.screenTop网页正文部分左: window.screenLeft屏幕分辨率的高: window.screen.height屏幕分辨率的宽: window.screen.width屏幕可用工作区高度: window.screen.availHeight屏幕可用工作区宽度: window.screen.availWidth ------------------- 技术要点本节代码主要使用了Document对象关于窗口的一些属性,这些属性的主要功能和用法如下。要得到窗口的尺寸,对于不同的浏览器,需要使用不同的属性和方法:若要检测窗口的真实尺寸,在Netscape下需要使用Window的属性;在IE下需要 深入Document内部对body进行检测;在DOM环境下,若要得到窗口的尺寸,需要注意根元素的尺寸,而不是元素。Window对象的innerWidth属性包含当前窗口的内部宽度。Window对象的innerHeight属性包含当前窗口的内部高度。Document对象的body属性对应HTML文档的标签。Document对象的documentElement属性则表示HTML文档的根节点。document.body.clientHeight表示HTML文档所在窗口的当前高度。document.body. clientWidth表示HTML文档所在窗口的当前宽度。实现代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>请调整浏览器窗口</title> <meta http-equiv="content-type" content="text/html; charset=gb2312"> </head> <body> <h2 align="center">请调整浏览器窗口大小</h2><hr> <form action="#" method="get" name="form1" id="form1"> <!--显示浏览器窗口的实际尺寸--> 浏览器窗口 的 实际高度: <input type="text" name="availHeight" size="4"><br> 浏览器窗口 的 实际宽度: <input type="text" name="availWidth" size="4"><br> </form> <script type="text/javascript"> <!-- var winWidth = 0; var winHeight = 0; function findDimensions() //函数:获取尺寸 { //获取窗口宽度 if (window.innerWidth) winWidth = window.innerWidth; else if ((document.body) && (document.body.clientWidth)) winWidth = document.body.clientWidth; //获取窗口高度 if (window.innerHeight) winHeight = window.innerHeight; else if ((document.body) && (document.body.clientHeight)) winHeight = document.body.clientHeight; //通过深入Document内部对body进行检测,获取窗口大小 if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) { winHeight = document.documentElement.clientHeight; winWidth = document.documentElement.clientWidth; } //结果输出至两个文本框 document.form1.availHeight.value= winHeight; document.form1.availWidth.value= winWidth; } findDimensions(); //调用函数,获取数值 window.onresize=findDimensions; //--> </script> </body> </html> 源程序解读 (1)程序首先建立一个表单,包含两个文本框,用于显示窗口当前的宽度和高度,并且,其数值会随窗口大小的改变而变化。 (2)在随后的JavaScript代码中,首先定义了两个变量winWidth和winHeight,用于保存窗口的高度值和宽度值。 (3)然后,在函数findDimensions ( )中,使用window.innerHeight和window.innerWidth得到窗口的高度和宽度,并将二者保存在前述两个变量中。 (4)再通过深入Document内部对body进行检测,获取窗口大小,并存储在前述两个变量中。 (5)在函数的最后,通过按名称访问表单元素,结果输出至两个文本框。 (6)在JavaScript代码的最后,通过调用findDimensions ( )函数,完成整个操作。若转载请注明出处!若有疑问,请回复交流!
var obj = document.getElementByIdx_x(”testSelect”); //定位id var index = obj.selectedIndex; // 选中索引 var text = obj.options[index].text; // 选中文本 var value = obj.options[index].value; // 选中值 jQuery中获得选中select值 第一种方式$('#testSelect option:selected').text();//选中的文本 $('#testSelect option:selected') .val();//选中的值 $("#testSelect ").get(0).selectedIndex;//索引 第二种方式$("#tesetSelect").find("option:selected").text();//选中的文本…….val();…….get(0).selectedIndex;若转载请注明出处!若有疑问,请回复交流!
说明:AMR格式是智能手机上的常用音频文件格式,比MP3格式的压缩比大。同样时长的AMR文件大概是MP3的十分之一,所以在移动互联项目中应用比较广泛。但目前AMR格式在个人电脑上应用较少,所以目前大部门播放器都不支持AMR,为了解决这个问题我们打算在服务器端将AMR转成MP3,以便在个人电脑上通过浏览器的方式进行播放。最近公司一款基于移动互联网的产品有个短暂的录音(留言)功能,因为录音需要传输到服务器上,所以为了用户体验及节省用户流量,我们采用了AMR的语音格式。 目前并没有找到合适的支持AMR转MP3的java的开发包,服务器环境为CentOS 6.2,所以我们采用了ffmpeg。FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。其官方网址为:http://www.ffmpeg.org/ 实现:1. 首先安装系统基础环境 # yum install -y automake autoconf libtool gcc gcc-c++ //RHEL & CentOS 系列 # apt-get install automake autoconf libtool gcc gcc-c++ //Debian & Ubuntu 系列 2. 编译所需源码包 yasm:http://yasm.tortall.net/Download.html(汇编器,新版本的ffmpeg增加了汇编代码) lame:http://lame.sourceforge.net/download.php(Mp3音频解码) OpenCore AMR:http://sourceforge.net/projects/opencore-amr AmrNB:http://www.penguin.cz/~utx/amr AmrWB:http://www.penguin.cz/~utx/amr FFMpeg:http://ffmpeg.org/download.html 分别解压缩并编译上述源码包 # tar xzvf *.tar.gz # tar xjvf *.tar.bz2 解压后直接使用 # ./configure # make # make install 命令进行编译安装。 编译FFMpef的时候稍微特殊一点: # ./configure --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-version3 --enable-shared # make # make install # ldconfig 最后写入config后,终端运行ffmpeg命令,出现success和已安装的扩展,则运行成功。 3.使用方法 # ffmpeg -i 1.mp3 -ac 1 -ar 8000 1.amr //MP3转换AMR # ffmpeg -i 1.amr 1.mp3 //AMR转换MP3 附录:附录1. ffmpeg默认安装目录为“/usr/local/lib”,有些64位系统下软件目录则为“/usr/lib64”,编译过程中可能会出现“ffmpeg: error while loading shared libraries: libmp3lame.so.0: cannot open shared object file: No such file or directory”等类似的错误,解决办法是建立软链接:# ln -s /usr/local/lib/libmp3lame.so.0.0.0 /usr/lib64/libmp3lame.so.0 附录2. 如果出现以下提示:ffmpeg: error while loading shared libraries: libavdevice.so.54: cannot open shared object file: No such file or directory可以通过如下方式查看ffmpeg的动态链接库哪些没有找到: # ldd `which ffmpeg` libavdevice.so.54 => not found libavfilter.so.3 => not found libavformat.so.54 => not found libavcodec.so.54 => not found libswresample.so.0 => not found libswscale.so.2 => not found libavutil.so.51 => not found libm.so.6 => /lib64/libm.so.6 (0x00002ab7c0eb6000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00002ab7c100b000) libc.so.6 => /lib64/libc.so.6 (0x00002ab7c1125000) /lib64/ld-linux-x86-64.so.2 (0x00002ab7c0d9a000) 如果类似于上面的输出内容,查找以上类库: # find /usr/local/lib/ | grep -E "libavdevice.so.54|libavfilter.so.3|libavcodec.so.54" /usr/local/lib/libavfilter.so.3.17.100 /usr/local/lib/libavcodec.so.54.59.100 /usr/local/lib/libavdevice.so.54 /usr/local/lib/libavcodec.so.54 /usr/local/lib/libavfilter.so.3 /usr/local/lib/libavdevice.so.54.2.101 会发现全部在/usr/local/lib/下 查看链接库配置文件 # more /etc/ld.so.conf | grep /usr/local/lib 如果不包含的话,需要编辑此文添加: /usr/local/lib /usr/local/lib64 运行配置命令 # ldconfig 转自:http://linux.it.net.cn/e/Linuxit/2014/0828/3980.html若转载请注明出处!若有疑问,请回复交流!
[java] view plain copy /** * 利用BufferedReader实现Inputstream转换成String <功能详细描述> * * @param in * @return String */ public static String Inputstr2Str_Reader(InputStream in, String encode) { String str = ""; try { if (encode == null || encode.equals("")) { // 默认以utf-8形式 encode = "utf-8"; } BufferedReader reader = new BufferedReader(new InputStreamReader(in, encode)); StringBuffer sb = new StringBuffer(); while ((str = reader.readLine()) != null) { sb.append(str).append("\n"); } return sb.toString(); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return str; } /** * 利用byte数组转换InputStream------->String <功能详细描述> * * @param in * @return * @see [类、类#方法、类#成员] */ public static String Inputstr2Str_byteArr(InputStream in, String encode) { StringBuffer sb = new StringBuffer(); byte[] b = new byte[1024]; int len = 0; try { if (encode == null || encode.equals("")) { // 默认以utf-8形式 encode = "utf-8"; } while ((len = in.read(b)) != -1) { sb.append(new String(b, 0, len, encode)); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 利用ByteArrayOutputStream:Inputstream------------>String <功能详细描述> * * @param in * @return * @see [类、类#方法、类#成员] */ public static String Inputstr2Str_ByteArrayOutputStream(InputStream in,String encode) { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; try { if (encode == null || encode.equals("")) { // 默认以utf-8形式 encode = "utf-8"; } while ((len = in.read(b)) > 0) { out.write(b, 0, len); } return out.toString(encode); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 利用ByteArrayInputStream:String------------------>InputStream <功能详细描述> * * @param inStr * @return * @see [类、类#方法、类#成员] */ public static InputStream Str2Inputstr(String inStr) { try { // return new ByteArrayInputStream(inStr.getBytes()); // return new ByteArrayInputStream(inStr.getBytes("UTF-8")); return new StringBufferInputStream(inStr); } catch (Exception e) { e.printStackTrace(); } return null; } ===================================== Android读取txt文件乱码解决方案: 读取inputsteam的时候以“GB2312”方式读取,注意单纯的利用retStr =EncodingUtils.getString(retStr.getBytes(), "GB2312");是不行的,实例化retStr的时候就应该以“GB2312”方式。 以下是转载的内容: 从SDCard保存的txt文件读取中文到android系统中会出现乱码问题,如何解决这个乱码问题,网上有不少解答方法,譬如说利用String temp1 =EncodingUtils.getString(strLine.getBytes(),"GB2312"); 但并非对所有的情况都适用,解决乱码问题首先要明白为什么会乱码。究其原因,是因为txt文件在win系统上保存时默认为ANSI格式,而android目前只支持UTF-8编码,因此将txt文件的中文读入android系统中会产生乱码。也有人说直接将txt另存为UTF-8编码格式来解决乱码问题,但这种方法指标不治本,不能要求用户手动去更改格式,客户第一嘛。因此还是需要想办法在程序中进行处理。 以下做了一些编码格式的测试: 测试文本: 122.11196,29.90573,北仑固废厂 测试代码段: reader=new BufferedReader(new FileReader(filename)); strLine=reader.readLine() ; String temp1 = EncodingUtils.getString(strLine.getBytes(),"GB2312"); String temp2 = EncodingUtils.getString(strLine.getBytes("utf-8"),"utf-8"); String temp3 = EncodingUtils.getString(strLine.getBytes(),"utf-8"); 将文件存成 Unicode 格式 将文件存成utf-8 格式 这种方式能得到非乱码的中文显示,但对于 utf-8 格式下取得的经纬度数字利用double lon = Double.parseDouble(lat); 报错 NumberFormatException,原因可能是 parseDouble(lat)方法不能处理存成utf-8格式的带标点小数。 将文件 存成 ANSI 格式 将代码改为: reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename),"GB2312")); strLine=reader.readLine() ; String temp1 = EncodingUtils.getString(strLine.getBytes(),"GB2312"); String temp2 = EncodingUtils.getString(strLine.getBytes("utf-8"),"utf-8"); String temp3 = EncodingUtils.getString(strLine.getBytes(),"utf-8"); 即解决了中文乱码问题,又解决了Double.parseDouble(lat)报错问题 转自: http://blog.csdn.net/iplayvs2008/article/details/11484627 若转载请注明出处!若有疑问,请回复交流!
检测对象中属性的存在与否可以通过几种方法来判断。 1.使用in关键字。 该方法可以判断对象的自有属性和继承来的属性是否存在。 var o={x:1}; "x" in o; //true,自有属性存在 "y" in o; //false "toString" in o; //true,是一个继承属性 2.使用对象的hasOwnProperty()方法。 该方法只能判断自有属性是否存在,对于继承属性会返回false。 var o={x:1}; o.hasOwnProperty("x"); //true,自有属性中有x o.hasOwnProperty("y"); //false,自有属性中不存在y o.hasOwnProperty("toString"); //false,这是一个继承属性,但不是自有属性 3.用undefined判断 自有属性和继承属性均可判断。 var o={x:1}; o.x!==undefined; //true o.y!==undefined; //false o.toString!==undefined //true 该方法存在一个问题,如果属性的值就是undefined的话,该方法不能返回想要的结果,如下。 var o={x:undefined}; o.x!==undefined; //false,属性存在,但值是undefined o.y!==undefined; //false o.toString!==undefined //true 4.在条件语句中直接判断 var o={}; if(o.x) o.x+=1; //如果x是undefine,null,false," ",0或NaN,它将保持不变 若转载请注明出处!若有疑问,请回复交流!
问题:SQL语句在查询分析器中可以执行,代码中不能执行 解答:sql中包含数据库的关键字,将关键字用[]括起来,可以解决。 后记:建数据库的时候尽量避免使用关键字。 例子: sql.Format("UPDATE oa2_user SET [name]='%s',[code]='%s',[fullname]='%s',[groupid] = %d,[state] = %d,[userjob]='%s',\ [AGENTPSN] =%d,[macaddress]='%s',[memo] ='%s',[Tel] ='%s',[mail] ='%s' ,[HANDPHONE] ='%s' where [ID]= %d", m_strUsername,m_strCode,m_sUserFullName,m_groupid,m_iUserState ,m_strJob, m_sAgentID,m_sMacAddr,m_sUserMemo,m_sUserPhone,m_sUserMail,m_sUserHPhone,m_nUserId);若转载请注明出处!若有疑问,请回复交流!
前些天在同事进行技术分享时,看到他竟然只输入了一行命令./test.sh就成功登陆了开发机,甚是惊异,于是回来搜索研究了一下,遂成此文。 shell脚本基础 在编写ssh自动登陆脚本之前,先说一下shell脚本的基础,此基础不是一些语法什么的,网上到处都是,这里总结了一下shell脚本的运行机制~ shell脚本的运行方式 首先要说一下shell的几种启动方式,正是踩了脚本启动的坑,才使用原来十分钟就搞定的脚本,花了两个小时才搞定。同时也使得我们运行shell,知其所以然。 通过文件名执行 shell脚本可以直接通过文件名执行,需要注意的是文件需要执行权限。通过 sudo chmod +x ./file_name.sh 来给文件添加执行权限; 指定脚本解释器来执行文件 我们常用的 sh file_name.sh 就是指定了脚本解释器 /bin/sh来解释执行脚本;常见的脚本解释器还有:/bin/bash等,我们可以使用ls -l /bin/*sh命令来查看当前可用的脚本解释器; 使用. ./file_name或source命令执行脚本 这种方式不会像前两种方式一样fork一个子进程去执行脚本,而是使用当前shell环境执行,用于 .bashrc或者.bash_profile被修改的时候,我们不必重启shell或者重新登录系统,就能使当前的更改生效。 shebang 我们写一个shell脚本时,总是习惯在最前面加上一行 #!/binbash,它就是脚本的shebang,至于为什么叫这么个奇怪的名字,C语言和Unix的开发者丹尼斯·里奇称它为可能是类似于"hash-bang"的英国风描述性文字; 贴一段wiki上的解释: 在计算机科学中,Shebang是一个由井号和叹号构成的字符串行,其出现在文本文件的第一行的前两个字符。 在文件中存在Shebang的情况下,类Unix操作系统的程序载入器会分析Shebang后的内容,将这些内容作为解释器指令,并调用该指令,并将载有Shebang的文件路径作为该解释器的参数。 简单的说,它指示了此脚本运行时的解释器,所以,使用文件名直接执行shell脚本时,必须带上shebang; 此外,我们还可以在shebang后面直接附加选项,执行时我们默认使用选项执行; 如 test.sh的shebang为 #!/bin/sh -x,那我们执行脚本时: ./test.sh hello 相当于: bin/sh -x ./test.sh hello; 而编写一个ssh自动登陆脚本,需要用到的shebang(解释器)为 /usr/bin/expect; 需要注意的是:在指定脚本解释器来执行脚本时,shebang会被指定的脚本解释器覆盖,即优先使用指定的脚本解释器来执行脚本(习惯性地用sh ./test.sh却提示command not found) expect解释器 expect是一个能实现自动和交互式任务的解释器,它也能解释常见的shell语法命令,其特色在以下几个命令: spawn命令: spawn command命令会fork一个子进程去执行command命令,然后在此子进程中执行后面的命令; 在ssh自动登陆脚本中,我们使用 spawn ssh user_name@ip_str,fork一个子进程执行ssh登陆命令; expect命令: expect命令是expect解释器的关键命令,它的一般用法为 expect "string",即期望获取到string字符串,可在在string字符串里使用 * 等通配符; string与命令行返回的信息匹配后,expect会立刻向下执行脚本; set timeout命令: set timeout n命令将expect命令的等待超时时间设置为n秒,在n秒内还没有获取到其期待的命令,expect 为false,脚本会继续向下执行; send命令: send命令的一般用法为 send "string",它们会我们平常输入命令一样向命令行输入一条信息,当然不要忘了在string后面添加上 \r 表示输入回车; interact命令: interact命令很简单,执行到此命令时,脚本fork的子进程会将操作权交给用户,允许用户与当前shell进行交互; 完成脚本 以下是一个完成版的脚本 test.sh: #!/usr/bin/expect // 指定shebang set timeout 3 // 设定超时时间为3秒 spawn ssh user_name@172.***.***.*** // fork一个子进程执行ssh命令 expect "*password*" // 期待匹配到 'user_name@ip_string's password:' send "my_password\r" // 向命令行输入密码并回车 send "sudo -s\r" send "cd /data/logs\r" // 帮我切换到常用的工作目录 interact // 允许用户与命令行交互 执行 sudo chmod +x ./test.sh命令给shell脚本添加执行权限; 运行 ./test.sh命令,一键登陆成功! 简单的几个命令,,搭配起来解决了与命令行的交互问题后,很多复杂的功能也不在话下了~ alias别名 脚本完成了,可是还是有些小瑕疵: 输入./file_name.sh命令太长。。。 只能在脚本目录中才能执行,不然使用绝对路径输出的命令更长。 这里我们想到了linux的alias命令: alias命令: alias命令使用方式为 alias alias_name="ori_command",将alias_name设置为ori_command的别名,这样我们输入执行alias_name,就相当于执行了ori_command; 可是,我们会发现,当你关闭当前shell后,再打开一个shell窗口,再使用alias_name,系统提示command not found; 有没有能保持命令的方式呢?编辑bash_profile文件。 bash_profile文件 我们编辑bash_profile文件,此文件会在终端窗口创建的时候首先执行一次,所以可以帮我们再设置一次别名; 执行命令vim ~./bash_profile,在文件内部添加: alias alias_name="/root_dir/../file_name.sh 保存后,再使用 . ~./bash_profile或source ~./bash_profile 在当前脚本执行一遍设置别名命令,完成设置; 这样,我们无论在哪个目录,只要输入alias_name命令,回车,真正的一键登陆! 总结 作为一个程序猿,时刻保持着偷懒意识(当然此偷懒非彼偷懒。。。),在类unix系统中,不要浪费了shell这种神奇的工具,让计算机为我们服务~ 一个多月没写博客了,最近在看APUE,UNP一套的书,C和Unix上入门尚浅,不敢乱写误人子弟;平常自己用记事本做的笔记也比较散乱,不成系统; 转自:http://www.cnblogs.com/zhenbianshu/p/5867440.html 心得:看到此文,亲身实践,顿觉收获颇丰,遂转载作为笔记!程序员就是要越简洁越好,提升效率! 若转载请注明出处!若有疑问,请回复交流!
在编程的过程中,经常会用到对文件的读写操作等。比如,找出某一个文件夹下的所有文件名等。 下面的程序给出了,获取某一给定文件夹下所有文件的绝对路径的程序。可以作为某一个模块,在需要的时候直接使用。 package src; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.Vector; public class FileList { private String dir_name=null; private String list_name=null; private BufferedWriter out = null; Vector<String> ver=null; public FileList(String dir_name,String list_name) throws IOException{ this.dir_name=dir_name; //文件夹地址 this.list_name=list_name; //保存文件列表的文件地址 ver=new Vector<String>(); //用做堆栈 } public void getList() throws Exception{ out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(list_name, true))); //以追加的方式写入到指定的文件 ver.add(dir_name); while(ver.size()>0){ File[] files = new File(ver.get(0).toString()).listFiles(); //获取该文件夹下所有的文件(夹)名 ver.remove(0); int len=files.length; for(int i=0;i<len;i++){ String tmp=files[i].getAbsolutePath(); if(files[i].isDirectory()) //如果是目录,则加入队列。以便进行后续处理 ver.add(tmp); else out.write(tmp+"\r\n"); //如果是文件,则直接输出文件名到指定的文件。 } } out.close(); } } 若转载请注明出处!若有疑问,请回复交流!
我们知道浮点数是无法在计算机中准确表示的,例如0.1在计算机中只是表示成了一个近似值,因此,对付点数的运算时结果具有不可预知性。 在进行数字运算时,如果有double或float类型的浮点数参与计算,偶尔会出现计算不准确的情况。如以下示例代码: [java] view plain copy print? package ex; public class BigDeciTest { public static void main(String[] args){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); } } 上述代码执行结果如下: [plain] view plain copy print? 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999 在大多数情况下,使用double和float计算的结果是准确的,但是在一些精度要求很高的系统中,这种问题是非常严重的。 在《Effective Java》中提到一个原则,那就是float和double只能用来作科学计算或者是工程计算,但在商业计算中我们要用java.math.BigDecimal,通过使用BigDecimal类我们可以解决上述问题,实例代码如下: [java] view plain copy print? package ex; import java.math.*; public class BigDecimalDemo { public static void main(String[] args){ System.out.println(ArithUtil.add(0.01, 0.05)); System.out.println(ArithUtil.sub(1.0, 0.42)); System.out.println(ArithUtil.mul(4.015, 100)); System.out.println(ArithUtil.div(123.3, 100)); } } class ArithUtil{ private static final int DEF_DIV_SCALE=10; private ArithUtil(){} public static double add(double d1,double d2){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.add(b2).doubleValue(); } public static double sub(double d1,double d2){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.subtract(b2).doubleValue(); } public static double mul(double d1,double d2){ BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.multiply(b2).doubleValue(); } public static double div(double d1,double d2){ return div(d1,d2,DEF_DIV_SCALE); } public static double div(double d1,double d2,int scale){ if(scale<0){ throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDecimal b1=new BigDecimal(Double.toString(d1)); BigDecimal b2=new BigDecimal(Double.toString(d2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } } 运行结果如下: [plain] view plain copy print? 0.06 0.58 401.5 1.233 详细,请参考API文档。 转自:http://blog.csdn.net/yinan9/article/details/17283081 若转载请注明出处!若有疑问,请回复交流!
方法一、 解决的办法自然是用相对路径代替绝对路径,其实log4j的FileAppender本身就有这样的机制,如:log4j.appender.logfile.File=${WORKDIR}/logs/app.log 其中“${WORKDIR}/”是个变量,会被System Property中的“WORKDIR”的值代替。这样,我们就可以在log4j加载配置文件之前,先用System.setProperty ("WORKDIR", WORKDIR);设置好根路径,此操作可通过一初始的servlet进行。 方法二、可以使用服务器环境变量 log4j的配置文件支持服务器的vm的环境变量,格式类似${catalina.home} log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=${catalina.home}/logs/logs_tomcat.log log4j.appender.R.MaxFileSize=10KB 其中的${catalina.home}并非windows系统的环境变量,这个环境变量就不需要在Windows系统的环境变量中设置。之所以 这样,你可以看看tomcat\bin\catalina.bat(startup,shutdown都是调用这个)里面自带有 -Dcatalina.home= "%CATALINA_HOME%" 。继承这个思想,所以你也可以自己设定一个参数-Dmylog.home="D:/abc/log"到对应的服务器java启动的vm参数中 方法三、通过servlet初始化init()方法中加载file属性实现相对路径 具体实现:做一个servlet,在系统加载的时候,就把properties的文件读到一个properties文件中.那个file的属性值 (我使用的是相对目录)改掉(前面加上系统的根目录),让后把这个properties对象设置到propertyConfig中去,这样就初始化了 log的设置.在后面的使用中就用不着再配置了 一般在我们开发项目过程中,log4j日志输出路径固定到某个文件夹,这样如果我换一个环境,日志路径又需要重新修改,比较不方便,目前我采用了动态改变日志路径方法来实现相对路径保存日志文件 (1).在项目启动时,装入初始化类: public class Log4jInit extends HttpServlet { static Logger logger = Logger.getLogger(Log4jInit.class); public Log4jInit() { } public void init(ServletConfig config) throws ServletException { String prefix = config.getServletContext().getRealPath("/"); String file = config.getInitParameter("log4j"); String filePath = prefix + file; Properties props = new Properties(); try { FileInputStream istream = new FileInputStream(filePath); props.load(istream); istream.close(); //toPrint(props.getProperty("log4j.appender.file.File")); String logFile = prefix + props.getProperty("log4j.appender.file.File");//设置路径 props.setProperty("log4j.appender.file.File",logFile); PropertyConfigurator.configure(props);//装入log4j配置信息 } catch (IOException e) { toPrint("Could not read configuration file [" + filePath + "]."); toPrint("Ignoring configuration file [" + filePath + "]."); return; } } public static void toPrint(String content) { System.out.println(content); } } 实际上log4j的配置文件log4j.properties如为默认名,可放置在JVM能读到的classpath里的任意地方,一般是放在 WEB- INF/classes目录下。当log4j的配置文件不再是默认名,则需要另外加载并给出参数,如上 “ropertyConfigurator.configure(props);//装入log4j配置信息” (2).Web.xml中的配置 <servlet> <servlet-name>log4j-init</servlet-name> <servlet-class>Log4jInit</servlet-class> <init-param> <param-name>log4j</param-name> <param-value>WEB-INF/classes/log4j.properties</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 注意:上面的load-on-startup设为0,以便在Web容器启动时即装入该Servlet。log4j.properties文件放在根的properties子目录中,也可以把它放在其它目录中。应该把.properties文件集中存放,这样方便管理。 (3).log4j.properties中即可配置log4j.appender.file.File为当前应用的相对路径. 以上是网上log4j日志文件的相对路径配置的三种方法(我能找到的就三种),分析: 方法一主要是扩展了log4j的RollingFileAppender类,其他的FileAppender同样道理。扩展的方法,就是用一个子类去覆盖setFile方法,这个方法在log4j读取配置文件生成appender的时候调用,传入的就是配 置文件中的路径,这样我就可以按照自己的想法在路径前面加上根路径了。这种方法可以在log4j.properties中用相对路径自由配置log4j.appender.A1.File属性来决定生成的日志相对web应用根 目录的位置。 方法二是利用服务器vm中已经存在的环境变量如${catalina.home}来设置相对于${catalina.home}的日志路径,日志只能放到服务器子目录里,而且如果是用的其它服务器,则要改对应的环境变量。此方法平台移植不方便。 方法三是扩展ActionServlet类,覆盖其init()方法,新方法中载入log4j.properties位置的参数,可以自由配置log4j的配置文件的名字和存放位置。也可自由配置log4j日志文件的相对于当前应用的路径。详 细代码如下: 程序代码 package wbb.bysxxglxt.util; import org.apache.struts.action.*; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log; import javax.servlet.ServletException; import java.util.Properties; import java.io.InputStream; import org.apache.log4j.PropertyConfigurator; import java.io.FileInputStream; import java.io.IOException; public class ExtendedActionServlet extends ActionServlet { private Log log = LogFactory.getLog(this.getClass().getName()); public ExtendedActionServlet() {} public void init() throws ServletException { log.info( "Initializing, My MyActionServlet init this System's Const Variable"); String prefix = this.getServletConfig().getServletContext().getRealPath( "/"); String file = this.getServletConfig().getInitParameter("log4j"); String filePath = prefix + file; Properties props = new Properties(); System.out.println(prefix); System.out.println(file); System.out.println(filePath); try { FileInputStream log4jStream = new FileInputStream(filePath); props.load(log4jStream); log4jStream.close(); String logFile = prefix + props.getProperty("log4j.appender.A1.File"); //设置路径 System.out.println(logFile); props.setProperty("log4j.appender.A1.File", logFile); PropertyConfigurator.configure(props); //装入log4j配置信息 } catch (IOException e) { e.printStackTrace(); } log.info("Initializing, end My Init"); super.init();//应用了struts,此方法不能省,ActionServlet覆盖了的此方法中有很多重要操作 } } **********************应用web.xml 关键部分*************************** 程序代码 <servlet> <servlet-name>action</servlet-name> <servlet-class>wbb.bysxxglxt.util.ExtendedActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>log4j</param-name> <param-value>properties\log4j.properties</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>application</param-name> <param-value>ApplicationResources</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> 注意log4j参数中相对路径的斜杠线的写法,而且log4j属性文件如放置在web-inf/classes目录或web-inf等目录中最好 改名,因为在加载此Servlet之前,服务器如tomcat启动时会自动搜索web-inf目录和web-inf/classes目录中 log4j.properties文件,如有则自动加载。log4j属性文件加载后,由于该属性文件中log4j.appender.A1.File的值 用的是相对路径,自动加载配置便会出错: log4j:ERROR setFile(null,true) call failed. java.io.FileNotFoundException: WEB-INF\logs\bysxxglxt.log (系统找不到指定的路径。) 不知道log4j为什么会这么早自动启动。尽管后面加载扩展的ActionServlet中正确设置了log4j属性文件并正常加载了,但报的这个错还是怪不爽的,于是只有更改log4j属性文件名字或者更改其存放位置,让其不能自动加载了,不过还是有两个警告: log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax). log4j:WARN Please initialize the log4j system properly. 这样做就算是掩耳盗铃了,如果你有更好的解决办法,希望能在此贴出来,大家一起研究。 ********************log4j.properties***************************** ### 设置logger级别 ### 程序代码 log4j.rootLogger=DEBUG,stdout,A1 ### appender.stdout输出到控制台 ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern= [%5p] [BYSXXGLXT] %d{yyyy-MM-dd HH:mm:ss}: %-4r [%-5p] [%t] ( %F,%L ) - %m%n ### appender.A1输出到日志文件 ### log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender log4j.appender.A1.File=WEB-INF\\logs\\bysxxglxt.log ##注意上面日志文件相对应用根目录路径的写法 log4j.appender.A1.DatePattern='.'yyyy-MM-dd'.log' log4j.appender.A1.Append=true ## 输出DEBUG级别以上的日志 log4j.appender.A1.Threshold=DEBUG log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern= [%5p] [BYSXXGLXT] %d{yyyy-MM-dd HH:mm:ss}: %-4r [%t] ( %F,%L ) - %m%n 若转载请注明出处!若有疑问,请回复交流!
《金字塔原理》 《数学模型》 《当我谈跑步时我谈些什么》 《影响力》若转载请注明出处!若有疑问,请回复交流!
1) 总带一本书 无论你花一年或者一周去读一本书,这都无所谓。随身带着它,当你有时间的时候就努力去阅读,通读。每天只需花挤出来的几分钟,一周就能读一本。那么一年至少就能读50本。 2) 建一个“要学习什么”的名单 我们都有需要做的事情的清单。这些就是我们需要完成的任务。努力建立一个”要学习什么”的清单。你可以把想要学习新领域的思路写在上面。或许你想掌握一门新语言,学习新技能,或者读莎士比亚全集。无论是什么激励你的,都要把它写下来。 3) 寻找更多明智的朋友 开始花更多的时间与那些善于思考的人在一起。并不仅因为他们聪明,而且是因为他们投入了很多时间学习新的技能。他们的好习惯也会在你的身上摩擦出火花。甚至更好的,他们可能会与你分享他的知识。 4) 指导自己的思想 爱因斯坦曾经说过:”任何读多思少的人都会养成懒惰思维的习惯”。只是简单的学习别人的东西,这样的智慧是不够的,你要在此之上建立自己的想法。多花点时间写日记,把你对这些学到的知识的思考和想法记录下来。 5) 付诸实践 如果不使用,学来的技能也是无用的。读一本C++的书,和写一个相同的程序,是完全不同的两码事。学画画可不是简单的拿起画笔。如果你的知识能被应用,那就付诸实践吧。 6) 教导别人 寓学于教。如果你能把知识教给别人,你也可以巩固学习。建立一个博客,开导别人或者与朋友们讨论想法。 7) 整理你的博客订阅 有些形式的学习很容易消化,但往往缺乏实质内容。我就经常定期清理我订阅的博客。伟大的博客就是一个新思路的巨大源泉。但每隔几个月,我就意识到我总是收到那些我不关注的博客的信息。每隔几个月,清理你们的订阅,就可以节省时间,注意重点。 8 ) 在群体中学习 终身学习并不意味着让自己陷于一堆落满灰尘的课本。加入教授技能的组织。这种群体学习和小组学习活动,都可以培养自己的乐趣和社会经验。 9) 将假设忘掉【把你脑中先入为主的观念忘掉】 杯子满了就不能再往里面倒水了。所以我总是尽量与任何想法保持距离。学到了太多的信念,就意味着太少产生新想法的机会。积极寻找那些能改变你的世界观的想法。 10) 找一份能鼓励多学习的工作 找一份能鼓励不断学习的工作。如果你的工作让你没有多少学习知识的自由,就该考虑换工作了。不要每周花40小时来做一项没有挑战的工作。 11) 开始的一个项目 列举一些你不知道该从何做起的事情。强迫这样去学习才能得到乐趣,并具有挑战性。如果你不懂电脑,尝试学一学。如果你认为你一个可怕的艺术家,那就试试画画。 12) 跟随你的直觉 终身学习有时感觉就好像在荒野中漫游。你不知道你在期望什么,而且心里也不是总有一个明确的最终目标。那就让你的直觉指引你吧,这样可以让自我教育更有乐趣。我们的生活已经被完全的逻辑思维所打破,以至于异想天开的想法不复存在了。 13) 早上15分钟 把早上的前15分钟定为学习期。如果你发现自己筋疲力尽,你也许想要等一会再学。但是不要把它推迟的过晚,因为某些紧急活动可能就会完全把它推之门外。 14) 获得回报 学习你可以使用的资料。了解一些基本的编程,其他人需要外界帮助才能完成的项目,我就可以独立完成。要知道能够利用你的学习成果,这可是值得自豪的。 15) 把它作为首要任务 很少有外部力量能说服你去学习。渴望应该来自内部。一旦你决定把终身学习作为一种习惯,你就应该把它作为你生命里的首要任务。 若转载请注明出处!若有疑问,请回复交流!
1. 努力是给自己看的,而不是看上去很努力; 2. 做好具体事务很重要; 3. 行业视野比具体事物更重要; 4. 个人打拼很重要; 5. 队伍建设比个人打拼更重要; 摘自知乎 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 尽量简单来说,这事说起来能说到天黑。简单点来说<br>1. 安逸的工作(公司)不要做。 2. 可以累的跟孙子一样,但是一定要能学到东西。 3. 有机会能进大公司(或你认为特别牛逼的公司),就是擦地板也要去。 4. 控制脾气、一定要控制。 5. 理想要好高骛远,实现理想脚踏实地 6. 记住!公司里每个大爷都当过孙子的时候。 7. 公司里别站队 8. 加班一定要做,加班费一定要拿(不给加班费的公司可以直接否掉) 9. 抓住在领导面前得瑟才能的机会,但是不要得瑟性格。 ------------------------------------------------------- 补充几点(为了60个赞而努力) 10. 再不靠谱的领导,身上都有些值得学的东西(会关注领导的小细节,会把工作都分配出去让自己清闲)。这些不一定要自己以后用在别人身上,以后可以多开这些 11. 可以和同事交朋友,也可以交心。但是不要交流太多公司吐槽事情(比如吐槽领导为人,谁谁谁吃回扣) 12. 办公室恋爱很好,但是也很容易断送这个公司的前程。如果有最好低调 13. 公司不是你的家,领导不是你父母。别跟回家那么自在,也别没事跟领导抱怨。 14. 头三年(一般我认为是30岁以前)别惦记薪水,惦记职业规划和能学到多少东西。(能力有了,票子自然就来了。同理女人漂亮了,追的男人就多了,自然优胜劣汰了) ------------------------------------------------------- 综述: 毕业生很少有心平气和,肯踏实工作的。大部分自我感觉可以改变全宇宙似地(往往这些基本没几个做得好的)。收起自己的性格,把才华都展示出来。同事也好领导也好,即使最后你离开了,以后也许会有人推荐你去他们朋友的公司或得到其他推荐的机会。 --------------------------------------------- 之前知乎有一个讲实习生的提问,你找找。里面有更多详细可用信息。 1 2 3 4 5 6 7 8 以下几点: 1. 大平台:第一份工作最好选择大公司。不是说没有可以锻炼人的小公司,而是要找到这样的小公司很难。大公司风险相对低,尤其对于刚步入职场眼光不够锐利的新人。而且大公司可以2提高你的眼界,让你了解行业标准。 2. 勤奋:接受并拥抱加班,自己给自己加班。前3年别考虑太多物质回报,能学到东西最重要。 3. 养成一些好习惯,比如 记日志:每周甚至每天记录、回顾、反思。学而不思则罔。 看书:看大师写的书,即真知灼见又往往很薄,值得反复读。思而不学则怠。 4. 人脉和人际关系:因人而异,如果自己性格不合适不用花太多功夫,不如把时间放在增强自己上。自己强大了,才会有强大的人和你交往。 5. 志存高远,脚踏实地:巨人都是头顶天看到远方,脚踩地落到实处。对于胸有大志的人,应更注重实干,做好能做的每件事,走好每一步。 摘自北邮人论坛 1、先做事,其他的不重要 能把事做好了,做成了,以后的收益肯定少不了。 看好自己做的事情,就安心去做,不用去考虑收益的问题。 十几年前跟着马云的那批人,不是因为马云给的钱多,而是因为马云讲的故事、事业吸引了他们。 至于钱,老板肯定会给想办法给你个中位值的,否则你就被挖走了。 2、不用纠结于一时 你还要工作3、40年,一两年的收入差距不是那么重要。把事做好了,能力提升了,后面跳一次可能把前几年的都补回来了。而且,再过10年看,现在的这10w块的差距,可能也就是个零头。 3、回过头看,安慰自己 就算现在回头看,当时给你这个offer,你接嘛? 4、论靠谱猎头的重要性 从HR主动给你调高的情况看,你要的可能真的太低了,哈哈哈。 路还长,不急,好好做事吧。 男人30如何算“立” 古语有云,“君子不患无位,患所以立”。 楼主所说的那些,都是“位”。古人把“立”和“位”区分开来,自然有他的道理。 那么,什么叫“立”呢?我觉得要做到如下几点。 1,对人类社会的运作有了基本的概念,明白金钱在社会上到底是如何流动的。 2,有了自己的职业,已经在自己努力的方向上开始耕耘,并且有一定成绩。 3,学会承担责任,懂诚信,懂社会规则,不再像年轻时一样冲动。 4,懂幽默,有自己固定的业余爱好。 5,找到自己的人生伴侣。 若转载请注明出处!若有疑问,请回复交流!