sundaym / blog Goto Github PK
View Code? Open in Web Editor NEWmy blog
my blog
两种方式:
完成2个功能:
引导层是配置和启动MyBatis 配置信息的方式。
MyBatis 提供两种方式来引导MyBatis :
HashSet判断两个元素相等的标准:两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
创建一个新tar文件 | tar cvf archive_name.tar dirname/ |
解包tar文件 | tar xvf archive_name.tar |
查看tar文件 | tar tvf archive_name.tar |
创建一个*.gz的压缩文件 | gzip test.txt |
解压*.gz文件 | gzip -d test.txt.gz |
显示压缩的比率 | gzip -l *.gz |
创建*.bz2压缩文件 | bzip2 test.txt |
解压*.bz2文件 | bzip2 -d test.txt.bz2 |
解压*.zip文件 | unzip test.zip |
查看*.zip文件的内容 | unzip -l jasper.zip |
查找指定文件名的文件(忽略大小写) | find 目录 -iname "MyProgram.c" |
查找home目录下的所有空文件 | find ~ -empty |
在文件中查找字符串(忽略大小写) | grep -i "the" demo_file |
输出成功匹配的行,以及该行之后的三行 | grep -A 3 -i "example" demo_text |
在一个文件夹中递归查询包含指定字符串的文件 | grep -r "ramesh" * |
以易读的方式显示文件大小(显示为MB,GB...) | ls -lh |
以最后修改时间升序列出文件 | ls -ltr |
在文件名后面显示文件类型 | ls -F |
当你将Dos系统中的文件复制到Unix/Linux后,这个文件每行都会以\r\n结尾,sed可以轻易将其转换为Unix格式的文件,使用\n结尾的文件 | sed 's/.$//' filename |
反转文件内容并输出 | sed -n '1!G; h; p' filename |
为非空行添加行号 | sed '/./=' thegeekstuff.txt |
以升序对文件内容排序 | sort names.txt |
以降序对文件内容排序 | sort -r names.txt |
以第三个字段对/etc/passwd的内容排序 | sort -t: -k 3n /etc/passwd | more |
命令默认显示文件最后的10行文本 | tail filename.txt |
-n选项指定要显示的行数 | tail -n N filename.txt |
-f选项进行实时查看 | tail -f ./catalina.out |
登录到远程主机 | ssh -l jsmith remotehost.example.com |
调试ssh客户端 | ssh -v -l jsmith remotehost.example.com |
显示ssh客户端版本 | ssh -V |
显示文件系统的磁盘使用情况,默认情况下df -k将以字节为单位输出磁盘的使用量 | df -k -h |
kill用于终止一个进程 | kill -9 7256 |
查看当前正在运行的所有进程 | ps -ef | more |
以树状结构显示当前正在运行的进程 | ps -efH | more |
查看和配置Linux系统的网络接口 | ifconfig -a |
使用up和down命令启动或停止某个接口 | ifconfig eth0 up 或 ifconfig eth0 down |
内核信息 | uname -a |
top命令会显示当前系统中占用资源最多的一些进程 | top |
显示某个特定用户的进程 | top -u root |
以其他单位输出内存使用量 | free -g |
查看所有内存的汇总 | free -t |
立即关机 | shutdown -h now |
10分钟后关机 | shutdown -h +10 |
重启 | shutdown -r now |
重启期间强制进行系统检查 | shutdown -Fr now |
比较的时候忽略空白字符 | diff -w name_list.txt name_list_new.txt |
输出跟字符串oracle匹配的环境变量 | export | grep ORACLE |
设置全局环境变量 | export ORACLE_HOME=/u01/app/oracle/product/10.2.0 |
设置系统时间 | date -s "10/04/2018 23:00:00" |
修改了系统时间,需要同步硬件时间和系统时间 | hwclock --systohc -utc |
下载文件 | wget http://example.com/xx.tar.gz |
下载文件并指定文件名保存 | wget -O a.tar.gz http://example.com/xx.tar.gz |
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4
官方概念,xmlns是xml namespace的缩写,是XML命名空间,xmlns属性可以在文档中定义一个或多个可供选择的命名空间。该属性可以放在文档内任何元素的开始标签中。该属性的值类似于URL,它定义了一个命名空间,浏览器会将此命名空间用于该属性所在元素内的所有内容。
如果是XHTML文档,他就需要一个XML命名空间来规范它的语法。XHTML是用XML的语法来规范的HTML语言。这个标准位于属性值的网址。
xmlns:xsi全名xml schema instance,表示使用xsi作为前缀的Namespace
指具体用到的schema资源
在JVM运行时区域的方法区中,有一块区域是运行时常量池,主要用来存储编译期生成的各种字面量和符号引用。
Java代码被Javac编译之后,文件结构中包含一部分的Constant Pool。.class文件中的常量池部分的内容,会在运行期被运行时常量池(Run-time Constant Pool)加载进去。
String str = new String("abc");
new String("abc")
执行的时候,要在Java堆中创建一个字符串对象,而这个对象所对应的字符串字面量是保存在字符串常量池中的。可以简单的理解为String s1 = "Hollis";和String s3 = new String("Hollis").intern();做的事情是一样的。
String s1 = "abc";
String s2 = new String("abc");
String s3 = new String("abc").intern();
System.out.println(s1 == s3); //true
s1和s3都是字符串常量池中的字面量的引用,所以s1==s3
s2的引用是堆中的对象,所以s2!=s1
对于字符串的拼接,纯字面量和字面量的拼接,会把拼接结果作为常量保存到字符串。"ab"+"cd"
在字符串拼接中,有一个参数是非字面量,而是一个变量的话,整个拼接操作会被编译成StringBuilder.append,这种情况编译器是无法知道其确定值的。只有在运行期才能确定。str1+str2
对于那种可能经常使用的字符串,使用intern进行定义,每次JVM运行到这段代码的时候,就会直接把常量池中该字面值的引用返回,这样就可以减少大量字符串对象的创建了。
假设有函数f(fn),fn为函数f的输入参数,并且fn = f(fn)
则fn = f(fn) = f(f(fn)) = f(f(f(fn)))
(define Y
(lambda (f)
(f (Y f))))
Y = λf.(λx.f (x x)) (λx.f (x x))
参考:
http://www.cppblog.com/wuwu/archive/2014/07/07/207556.aspx
作用:用来唯一标识jar、war这些构件。
Maven坐标包括:groupId、artifactId、version、packaging、classifier
快捷键 | 介绍 |
---|---|
Ctrl + , | 代码补全(个人修改后) |
Alt + 左右方向键 | 退回/前进到上一个操作的地方(个人修改) |
Alt + F7 | 查找光标所在的方法 / 变量 / 类被调用的地方 |
Alt + Insert | 代码自动生成,如生成对象的 set / get 方法,构造函数,toString() 等 |
Ctrl + Alt + L | 格式化代码,可以对当前文件和整个包目录使用 |
Ctrl + Alt + B | 在某个调用的方法名上使用会跳到具体的实现处,可以跳过接口 |
Ctrl + Alt + S | 打开Settings面板 |
Ctrl + Alt + F7 | 显示使用的地方。寻找被该类或是变量被调用的地方,用弹出框的方式找出来 |
web.xml(部署描述符文件)是Java web工程的一个配置文件,是在Servlet规范中定义的,用来初始化配置信息。主要用来配置:欢迎页(welcome-file-list)、servlet、filter、listener,启动加载级别等。
一个web工程可以没有web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext_*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<servlet>
<display-name>StatementTemplateSendServlet</display-name>
<servlet-name>StatementTemplateSendServlet</servlet-name>
<servlet-class>com.thtf.commons.quartz.StatementTemplateSendServlet</servlet-class>
<load-on-startup>4</load-on-startup>
</servlet>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
context-param元素
上下文参数:context-param 元素用来设定web应用的环境参数(context),它包含两个子元素:param-name和param-value。
filter元素
filter元素用于注册Web容器中的过滤器。
listener元素
listener元素用来注册一个监听器类,可以在Web应用中包含该类。
容器对于web.xml的加载过程:
context-param -> listener -> filter -> servlet
加载spring
比如filter 需要用到 bean ,但加载顺序是: 先加载filter 后加载spring,则filter中初始化操作中的bean为null;所以,如果过滤器中要使用到 bean,可以将spring 的加载 改成 Listener的方式:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
web.xml 的加载顺序是:[context-param -> listener -> filter -> servlet -> spring]
Filter链
一个web应用中可以开发多个Filter,这些Filter组合起来称为Filter链。web服务器根据Filter的注册顺序决定调用先调用哪个Filter。
Spring中的一些Filter
CharacterEncodingFilter
,从全局控制字符编码servlet的监听器实现了javax.servlet.ServletContextListener 接口,也是随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。
ServletContextListener接口的源代码:
public abstract interface ServletContextListener extends EventListener{
public abstract void contextInitialized(ServletContextEvent paramServletContextEvent);
public abstract void contextDestroyed(ServletContextEvent paramServletContextEvent);
}
Spring的ContextLoaderListener配置,用于加载Spring
<listener>
<listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
</listener>
一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。
线程池模式一般分为两种:
Java线程池使用的是阻塞队列
【入队】
非阻塞队列:当队列满的时候,放入数据,数据丢失
阻塞队列:当队列满了,进行等待,什么时候队列中有出队,那么等待数据再放入
【出队】
非阻塞队列:如现队列中没有元素,取数据,得到的是null
阻塞队列:等待,什么时候放进去,再去出来
参考:
https://zh.wikipedia.org/wiki/%E7%BA%BF%E7%A8%8B%E6%B1%A0
https://blog.csdn.net/u011974987/article/details/51027795
Java对象保存在堆内存中,一个Java对象包含3个部分:对象头、实例数据和对齐填充。
对象头中包含锁状态标志和线程持有的锁状态等标志。
对象在JVM中的表示。
在CPU和内存之间使用缓存的原因
由于CPU执行速度过快,而从内存中读写数据的过程与之差距过大,导致CPU每次操作内存都要耗费很多的等待时间。所以在CPU和内存之间增加了高速缓存。
程序执行过程,将CPU需要的数据从主存中复制一份到高速缓存中,CPU运算时直接从它的高速缓存读取/写入数据,当运算结束后,再将高速缓存中的数据刷新到主存当中。
使用缓存带来的问题
使用缓存在多核CPU多线程场景下,可能存在缓存一致性问题。在多核CPU中,每个核的自己的缓存中,关于同意数据的缓存内容可能不一致。
并发编程的问题
为了保证数据安全,必须保证一下三个特性:
volatile、synchronized、final、concurren包等。
synchronized保证方法和代码块的操作是原子性的。
volatile关键字 保证被其修饰的变量在被修改后可以立即同步到主内存,被其修饰的变量在每次使用之前都从主内存刷新。(可见性)
在Java中,可以使用synchronized和volatile来保证多线程之间操作的有序性。
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
//线程1
boolean stop = false;
while(!stop){
doSomething();
}
//线程2
stop = true;
下面解释一下这段代码为何有可能导致无法中断线程
每个线程在运行过程中都有自己的工作内存,那么线程1在运行的时候,会将stop变量的值拷贝一份放在自己的工作内存当中。那么当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。
volatile修饰之后
JMM并不像JVM内存结构一样真实存在,它是一个抽象概念。
JMM是JVM规范中定义的和多线程相关的一组规则,围绕多线程通信以及相关的一系列特性而建立的模型。在Java语言上的表现就是volatile、synchronized等关键字。
JVM内存结构,由JVM规范定义。描述Java程序执行过程中,由JVM管理的不同数据区域。
Java对象在JVM中存储有一定结构,Java对象自身的存储模型称之为Java对象模型。
JVM内存结构,和Java虚拟机的运行时区域有关。
Java内存模型,和Java的并发编程有关。
Java对象模型,和Java对象在虚拟机中的表现形式有关。
public boolean equals(Object obj) {
return (this == obj);
}
JDK的Object类中euqals()方法用于判断两个对象的地址是否相等,等价于“==”。
euqals()方法分为两类:
每个Java类都包含hashCode() 函数。但是,仅仅当创建某个“类"的散列表时,该类的hashCode() 才有用。更通俗地说就是创建包含该类的HashMap,Hashtable,HashSet集合时,hashCode() 才有用。因为HashMap,Hashtable,HashSet就是散列表集合。
hashCode()的作用:确定该类的每一个对象在散列表中的位置。
hashCode()方法分为两类:
JVM中每个线程都独占一块栈内存,其中包括局部变量、线程调用的每个方法的参数和返回值。其他线程无法读取到该栈内存块中的数据。在JVM中,堆内存是所有线程共享的。堆中只包含对象,没有其他东西。除了栈和堆,还有一部分数据可能保存在JVM中的方法区中,比如类的静态变量。方法区和栈类似,其中只包含基本类型和对象应用。和栈不同的是,方法区中的静态变量可以被所有线程访问到。
JVM中有两块内存区域可以被所有线程共享:
锁是通过监视器实现的,监视器主要功能是监控一段代码,确保在同一时间只有一个线程在执行。
同一个线程可以对同一个对象进行多次加锁。每个对象维护着一个记录着被锁次数的计数器。
在Java中,当有多个线程都必须要对同一个共享数据进行访问时,有一种协调方式叫做同步。Java语言提供了两种内置方式来使线程同步的访问数据:同步代码块和同步方法。
Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。
Spring创建代理的规则:
AOP编程,程序员只需要参与三个部分:
除了Spring提供的jar包,还需要额外下载两个jar包:aopalliance.jar和aspectjweaver.jar
XML实现方式:
//先定义一个接口
public interface HelloWorld
{
void printHelloWorld();
void doPrint();
}
//定义两个接口实现类
public class HelloWorldImpl1 implements HelloWorld
{
public void printHelloWorld()
{
System.out.println("Enter HelloWorldImpl1.printHelloWorld()");
}
public void doPrint()
{
System.out.println("Enter HelloWorldImpl1.doPrint()");
return ;
}
}
public class HelloWorldImpl2 implements HelloWorld
{
public void printHelloWorld()
{
System.out.println("Enter HelloWorldImpl2.printHelloWorld()");
}
public void doPrint()
{
System.out.println("Enter HelloWorldImpl2.doPrint()");
return ;
}
}
//横切关注点
public class TimeHandler
{
public void printTime()
{
System.out.println("CurrentTime = " + System.currentTimeMillis());
}
}
aop.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<bean id="helloWorldImpl1" class="com.xrq.aop.HelloWorldImpl1" />
<bean id="helloWorldImpl2" class="com.xrq.aop.HelloWorldImpl2" />
<bean id="timeHandler" class="com.xrq.aop.TimeHandler" />
<aop:config>
<aop:aspect id="time" ref="timeHandler">
<aop:pointcut id="addAllMethod" expression="execution(* com.xrq.aop.HelloWorld.*(..))" />
<aop:before method="printTime" pointcut-ref="addAllMethod" />
<aop:after method="printTime" pointcut-ref="addAllMethod" />
</aop:aspect>
</aop:config>
</beans>
public static void main(String[] args)
{
ApplicationContext ctx =
new ClassPathXmlApplicationContext("aop.xml");
HelloWorld hw1 = (HelloWorld)ctx.getBean("helloWorldImpl1");
HelloWorld hw2 = (HelloWorld)ctx.getBean("helloWorldImpl2");
hw1.printHelloWorld();
System.out.println();
hw1.doPrint();
System.out.println();
hw2.printHelloWorld();
System.out.println();
hw2.doPrint();
}
JDK动态代理的核心接口和方法
public interface InvocationHandler {
//proxy:被代理的类的实例
//method:调用被代理的类的方法
//args:该方法需要的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
//loader:被代理的类的类加载器
//interfaces:被代理类的接口数组
//invocationHandler:就是刚刚介绍的调用处理器类的对象实例
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
CGlib动态代理实现
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGlibAgent implements MethodInterceptor {
private Object proxy;
public Object getInstance(Object proxy) {
this.proxy = proxy;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.proxy.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
//回调方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(">>>>before invoking");
//真正调用
Object ret = methodProxy.invokeSuper(o, objects);
System.out.println(">>>>after invoking");
return ret;
}
public static void main(String[] args) {
CGlibAgent cGlibAgent = new CGlibAgent();
Apple apple = (Apple) cGlibAgent.getInstance(new Apple());
apple.show();
}
}
参考:
http://www.cnblogs.com/xrq730/p/4919025.html
http://www.cnblogs.com/puyangsky/p/6218925.html
字符类型char
布尔类型boolean
数值类型byte、short、int、long、float、double
实际上,Java中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。
基本数据类型 | 包装类型 |
---|---|
char | Char |
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
基本数据类型转换成包装类的过程就叫装箱(boxing)
包装类转换成基本数据类型的过程就叫做拆箱(unboxing)
自动将基本数据类型转换成包装类,或反之。
Integer i = 10; //替代Integer i = new Integer(10);
int j = i;
List<Integer> lst = new ArrayList<>();
for (int i = 1; i < 50; i ++){
lst.add(i);
它是Collection接口的父接口。
Collection接口有一个方法iterator()
返回一个Iterator迭代器对象。
Collection接口是Set、List、Queue接口的父接口。
Collection接口中定义了多种方法可以查看JDK文档。
主要用法有,添加元素、删除元素、返回Collection集合以及清空集合。
Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。
List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。
Queue用户模拟队列这种数据结构,队列通常是指“先进先出”(FIFO,first-in-first-out)的容器。
Map集合保存具有映射关系的数据。
参考:
https://www.jianshu.com/p/589d58033841
https://blog.csdn.net/zhengqiqiqinqin/article/details/8434132
Java所有类必须被装载到JVM中才能运行,装载工作由JVM的类装载器完成。类装载器所作的实质工作是把类文件从硬盘读取到内存中。JVM在装载类时,都是通过ClassLoader的loadClass()方法来装载class的,loadClass使用双亲委派模式。
public abstract class ClassLoader
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
类装载方式:
rpm -qa mysql
service mysqld status
service mysqld start
或用脚本/etc/init.d/mysql start
mysql -u root -h 127.0.0.1
mysql -u root -h 127.0.0.1 -p
首先进入mysql
update mysql.user set password=password("新密码") where User="root";
flush privileges;
quit;
show databases;
use test
原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性:事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
隔离性:多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性:已被提交的事务对数据库的修改应该永久保存在数据库中。
servlet是一个Java接口,定义的是一套处理网络请求的规范,不能处理请求,servlet不直接和客户端交互。servlet容器(如tomcat)负责和客户端交互,监听端口,将请求发送到对应的servlet处理,调用servlet的service方法,service方法返回response对象,tomcat在将response返回给客户端。
同步锁
Java中提供了多种同步锁的使用方式
public synchronized void doSomething(){}
public void increaseAmt(float increaseAmt){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (this) {
System.out.println(this);
amt+=increaseAmt;
}
}
public synchronized static void increaseAmt(float increaseAmt){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
amt+=increaseAmt;
}
synchronized (AccountSynchronizedClass.class) {
amt-=decreaseAmt;
}
synchronized有两种使用形式,同步方法和同步代码块。
同步方法的常量池中会有一个ACC_SYNCHRONIZED
标志。当某个线程要访问某个方法的时候,会检查是否有ACC_SYNCHRONIZED
,如果有设置,则需要先获得监视器锁,然后开始执行方法,方法执行之后再释放监视器锁。这时如果其他线程来请求执行方法,会因为无法获得监视器锁而被阻断住。值得注意的是,如果在方法执行过程中,发生了异常,并且方法内部并没有处理该异常,那么在异常被抛到方法外面之前监视器锁会被自动释放。
同步代码块使用monitorenter
和monitorexit
两个指令实现。可以把执行monitorenter
指令理解为加锁,执行monitorexit
理解为释放锁。 每个对象维护着一个记录着被锁次数的计数器。未被锁定的对象的该计数器为0,当一个线程获得锁(执行monitorenter
)后,该计数器自增变为 1 ,当同一个线程再次获得该对象的锁的时候,计数器再次自增。当同一个线程释放锁(执行monitorexit
指令)的时候,计数器再自减。当计数器为0的时候。锁将被释放,其他线程便可以获得锁。
参考:
http://www.hollischuang.com/archives/1876
http://www.hollischuang.com/archives/1883
Maven有两个settings.xml文件
路径分别是:%M2_HOME%/conf/settings.xml
和~/.m2/settings.xml
%M2_HOME%/conf/settings.xml
该配置为全局配置,影响所有用户~/.m2/settings.xml
该配置为用户范围~/.m2/
路径下作为用户范围的配置文件,MyBatis采用基于OGNL的表达式来淘汰其他大部分元素。
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
</select>
类似Java中的switch语句
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。
用于动态更新语句的解决方案叫做 set。set 元素可以用于动态包含需要更新的列,而舍去其它的。
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
和set元素等价的trim元素定义
<trim prefix="SET" suffixOverrides=",">
...
</trim>
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。比如:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
可以对类成员变量、setter方法及构造函数进行标注,完成自动装配的工作。
import org.springframework.beans.factory.annotation.Autowired;
public class Test {
@Autowired
private String user;
@Autowired
public void setUser(String user) {
this.user = user;
}
@Autowired
public Test(String user) {
this.user = user;
}
}
当容器中存在同样类型的多个bean时,可以使用 @qualifier 注解指定注入 Bean 的名称。
@qualifier 标注的是成员变量、方法入参、构造函数入参。
@Autowired
public void setSender(@Qualifier("cellphoneSender")Sender sender) {
this.sender = sender;
}
参考:
https://blog.csdn.net/u010648555/article/details/76299467
https://blog.csdn.net/soonfly/article/details/70023707
<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
servlet-name为这个servlet的名字,用于区分
load-on-startup标签为启动顺序,让这个servlet随servlet容器一起启动。
url-pattern为拦截规则,拦截.form
结尾的请求
在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
指明了配置文件的文件名,不使用默认配置文件名。
操作系统中两者的区别:
多进程与多线程
多进程指操作系统能同时运行多个任务(程序)
多线程指同一程序中有多个顺序流在执行
class Thread1 extends Thread {
private String name;
public Thread1(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "run:" + i);
try {
sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Thread1 mth1 = new Thread1("a");
Thread1 mth2 = new Thread1("b");
//start()方法调用,使线程变为可运行状态(Runnable),何时运行由操作系统决定
mth1.start();
mth2.start();
}
}
程序运行main方法时,JVM启动一个进程,主线程main在main()被调用时创建。接着调用两个start()方法,另外两个线程也启动了,这样整个应用就在多线程下运行。
覆盖run方法
class Thread2 implements Runnable {
private String name;
public Thread2(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + " run: " + i);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
new Thread(new Thread2("C")).start();
new Thread(new Thread2("D")).start();
}
}
所有的多线程代码都是通过运行Thread的start()方法来运行的。
在Java中,每次程序至少启动2个线程,一个是main线程,一个是垃圾收集线程。每当使用java命令执行一个类时,实际上都会启动一个JVM,每个JVM实际就是在操作系统中启动了一个进程。
static int MAX_PRIORITY //线程可以具有的最高优先级,取值为10
static int MIN_PRIORITY //线程可以具有的最低优先级,取值为1
static int NORM_PRIORITY //分配给线程的默认优先级,取值为5
Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级
线程的优先级有继承关系,比如A线程中创建了B线程,那么B和A具有相同的优先级
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
个人理解:在其他语言中,如Lisp可以将函数直接作为参数传递给函数(Lisp可以像处理数据一样处理自身代码),C中可以通过函数指针。Java无法直接将方法作为参数传递给方法,所以需要通过反射拿到关于类的信息并构造对象,通过这个包含类信息的对象,将可以实现把类中的方法作为参数传递给其他方法等功能。
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法
4.在运行时调用任意一个对象的方法
5.生成动态代理
【1】通过对象获取完整包名和类名
//实例化Class类,3种
Class demo0 = Class.forName("java.lang.String");
Class demo1 = new String().getClass();
Class demo2 = String.class;
//获取完整类名
System.out.println(demo0.getName());
运行结果:java.lang.String
【2】通过反射调用类中的方法
Class strClass = Class.forName("java.lang.String");
Method method = strClass.getMethod("toUpperCase");
System.out.println(method.invoke("asd"));
运行结果:ASD
invoke方法源码
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
数据在计算机中都是以0和1的序列进行存储的,根据需要可以将数据分开保存到文件这样一个小单位中。而文件系统(file system)就是文件在逻辑上的组织形式,它以一种清晰的方式来存放各个文件,防止文件杂乱无章。
文件系统使用文件和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,用户使用文件系统来保存数据不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个文件的所属目录和文件名。
常见文件系统:
dev //硬件设备文件
media //挂载媒体设备,光驱、U盘
mnt //让用户临时挂载别的文件系统
目的是为了写入文件系统
每个设备都叫一个文件,制定文件系统中的某个目录到某个设备就叫挂载。这个目录就叫挂载点。
参考:
https://zh.wikipedia.org/wiki/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F
https://www.cnblogs.com/vamei/archive/2012/09/09/2676792.html
统一存储所有Maven项目需要的构件(一般为jar包)
~/.m2/repository/
目录下)~/.m2/settings.xml
文件)pom.xml
文件)示例:
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.com/maven2/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
<layout>default</layout>
</repository>
</repositories>
repositories下可声明多个repository
http://maven.apache.org/download.cgi
apache-maven-3.5.4-bin.zip
解压apache-maven-3.5.4-bin.zip(如:D:\Maven\apache-maven-3.5.2)
添加环境变量
D:\Maven\apache-maven-3.5.2
%M2_HOME%\bin
正向代理:
反向代理:
lambda演算是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义、函数如何被应用以及递归的形式系统。Lambda演算作为一种广泛用途的计算模型,可以清晰地定义什么是一个可计算函数,而任何可计算函数都能以这种形式表达和求值。(由Alonzo Church引入以定义“可计算函数”)
lambda表达式用以下格式定义
λ变量.表达式体
lambda函数如何工作——归约。
规约有三种规则
λa b.a+b
和λx y.x+y
函数的功能并没有发生变化λa b.a+b
应用在传入的两个参数1和2,那么a和b分别就替换成1和2,表达式体中的a和b的位置也分别被替换成1和2λ1 2.1+2
lambda变量里不能调用一个外部的绑定名字的函数,当然Lambda函数本身也不能有名字(所以在某些编程语言里Lambda函数这个概念又叫做“匿名函数”)。
参考:
https://zh.wikipedia.org/wiki/%CE%9B%E6%BC%94%E7%AE%97
http://www.cppblog.com/wuwu/archive/2014/07/07/207556.aspx
public class Demo {
public static final int MONDAY =1;
public static final int TUESDAY=2;
public static final int WEDNESDAY=3;
public static final int THURSDAY=4;
public static final int FRIDAY=5;
public static final int SATURDAY=6;
public static final int SUNDAY=7;
}
enum Demo {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
编译器帮助生成了一个Day类(final,无法被继承),该类继承自java.lang.Enum类。编译器还帮助生成了7个Day类型的实例对象分别对应枚举中定义的7个日期。
static
{
//实例化枚举实例
MONDAY = new Day("MONDAY", 0);
TUESDAY = new Day("TUESDAY", 1);
WEDNESDAY = new Day("WEDNESDAY", 2);
THURSDAY = new Day("THURSDAY", 3);
FRIDAY = new Day("FRIDAY", 4);
SATURDAY = new Day("SATURDAY", 5);
SUNDAY = new Day("SUNDAY", 6);
$VALUES = (new Day[] {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
});
}
public enum Color {
RED, GREEN, BLANK, YELLOW
}
enum Signal {
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) {
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// get set 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆盖方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
//接口方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
参考:
https://blog.csdn.net/javazejian/article/details/71333103
http://www.hollischuang.com/archives/195
ArrayList实现了List接口,是顺序容器,允许放入null元素,底层通过数组实现。该类除未实现同步外,其余大部分和Vector大致相同。
remove(Object o)
删除第一个满足o.equals(elementData[index])
的元素。public E set(int index, E element) {
rangeCheck(index);//下标越界检查
E oldValue = elementData(index);
elementData[index] = element;//赋值到指定位置,复制的仅仅是引用
return oldValue;
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null; //clear to let GC do its work
return oldValue;
}
LinkedList同时实现了List和Deque接口,它既可以看作一个顺序容器,也可看作一个队列(Queue),还可看作一个栈(Stack)。底层通过双向链表实现,双向链表的每个节点用内部类Node()表示。LinkedList没有实现同步(synchronized),多线程并发访问,可以先用Collections.synchronizedList()
方法对其进行包装。
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
add(E e)
在末尾插入元素和add(int index, E element)
指定位置插入元素。remove(Object o)
删除和指定元素相等的第一个元素和remove(int index)
删除指定下标处元素。Java有Stack类和Queue接口,但当使用栈时,不推荐使用Stack,而是ArrayDeque,使用队列时也首选ArrayDeque。
ArrayDeque底层是有循环数组实现(circular array),数组的任何一点都可以看作起点或终点,ArrayDeque是非线程安全的,该容器不允许放入null元素。
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
当我们明确知道HashMap中元素的个数的时候,把默认容量设置成expectedSize / 0.75F + 1.0F 是一个在性能上相对好的选择。
用法: javap <options> <classes>
-help 帮助
-l 输出行和变量的表
-public 只输出public方法和域
-protected 只输出public和protected类和成员
-package 只输出包,public和protected类和成员,这是默认的
-p -private 输出所有类和成员
-s 输出内部类型签名
-c 输出分解后的代码,例如,类中每一个方法内,包含java字节码的指令,
-verbose 输出栈大小,方法参数的个数
-constants 输出静态final常量
分为两个部分
算法分析是理论研究,是关于计算机程序性能(computer program performance)和资源利用(resource usage)的研究。
首先需要关注性能;这里的资源代表如通信,存储器(内存或磁盘)
A: In programming, what is more important than performance?
Q: Correctness(正确性)...
A: Why do wo bother and why study algorithms and performance?
Q: 1. 通常性能的好与坏直接决定可行还是不可行。算法总是处于解决问题的最前沿,算法能够将不可行变成可行。
2. 算法是一种描述程序行为的语言,它已形成了一种广泛应用于计算机科学领域的语言,被所有实践者所采用的理论语言,它是一种让程序最为简洁的思考方式。
影响因素:
将依输入的规模将其参数化,之后会把运行时间看作待排列数据规模的函数
运行时间的上界,代表了对用户的承诺
渐进分析
不关注实际的运行时间,只关注它如何增长
渐进符号(asymptotic notation)
Θ-notation,drop low order terms and ignore leading constants
在公式中,弃去它的低阶项,并忽略前面的常数因子
例子: 公式3n^3+90n^2-5n+6046=Θ(n^3)
T(n)=O(f(n)),f(n)为算法执行次数与输入规模n的函数。
AVA程序启动时JVM都会分配一个初始内存和最大内存给这个应用程序。这个初始内存和最大内存在一定程度都会影响程序的性能。这个初始内存和最大内存在一定程度都会影响程序的性能。比如说在应用程序用到最大内存的时候,JVM是要先去做垃圾回收的动作,释放被占用的一些内存。
调整Tomcat的启动时初始内存和最大内存需要向JVM声明。
-Xms
和-Xmx
来调整应用程序的初始内存和最大内存。一般把-Xms和-Xmx设为一样大,堆的最大值受限于系统使用的物理内存。建议堆的最大值设置为可用内存的最大值的80%。
Windows下,在文件/bin/catalina.bat
JAVA_OPTS='-Xms【初始化内存大小】-Xmx【可以使用的最大内存】'
如JAVA_OPTS='-Xms256m-Xmx512m'
缓存的解释:
从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。
MyBatis默认情况下是没有开启缓存的,除了局部的session缓存。要开启二级缓存,需要在SQL映射文件中添加一行
<cache/>
这个简单语句的效果如下
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会 导致冲突。
可用的收回策略有:
参考:
http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache
显示所添加的jar包
在左边选择面板点击某个技术框架,右边将会显示这个框架的一些设置
项目的打包部署设置
exploded:在这里你可以理解为展开,不压缩的意思。也就是war、jar等产出物没压缩前的目录结构。建议在开发的时候使用这种模式,便于修改了文件的效果立刻显现出来。
输出目录理解:
点击运行tomcat时
Exception分为 运行时异常(RuntimeException)和非运行时异常,也称之为不检查异常(Unchecked Exception)和检查异常(Checked Exception)。
运行时异常都是RuntimeException类及其子类异常,如NullPointerException、 IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
非运行时异常是RuntimeException以外的异常,从程序语法角度讲是必须进行处理的异常,如果不 处理,程序就不能编译通过。
参考:
http://www.cnblogs.com/WayneZeng/archive/2012/09/23/2699177.html
快速排序使用分治法将一个序列(list)分成两个子序列
步骤:
public static void quickSort(int[] arr){
qsort(arr, 0, arr.length-1);
}
private static void qsort(int[] arr, int low, int high){
if (low < high){
int pivot=partition(arr, low, high); //将数组分为两部分
qsort(arr, low, pivot-1); //递归排序左子数组
qsort(arr, pivot+1, high); //递归排序右子数组
}
}
private static int partition(int[] arr, int low, int high){
int pivot = arr[low]; //枢轴记录
while (low<high){
while (low<high && arr[high]>=pivot) --high;
arr[low]=arr[high]; //交换比枢轴小的记录到左端
while (low<high && arr[low]<=pivot) ++low;
arr[high] = arr[low]; //交换比枢轴小的记录到右端
}
//扫描完成,枢轴到位
arr[low] = pivot;
//返回的是枢轴的位置
return low;
}
参考:
http://wiki.jikexueyuan.com/project/easy-learn-algorithm/fast-sort.html
https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F
http://blog.51cto.com/flyingcat2013/1281614
用来设置记录器级别,存放器,和布局
# 配置根Logger
log4j.rootLogger=[level],apenderName1,appenderName2,...
# 配置日志信息输出目的地Appender
log4j.appender.appenderName=fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.option1=valueN
# 配置日志信息的格式(布局)
log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1=value1
...
log4j.appender.appenderName.layout.optionN=valueN
[level]为日志输出级别,共有5级
FATAL 0 //
ERROR 3 //为严重错误 主要是程序的错误
WARN 4 //为一般警告,比如session丢失
INFO 6 //为一般要显示的信息,比如登录登出
DEBUG 7 //为程序的调试信息
Appender为日志输出目的地,Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
Layout:日志输出格式,Log4j提供的layout有以下几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
打印参数: Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,如下:
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss ,SSS},输出类似:2002年10月18日 22 : 10 : 28 , 921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java: 10 )
【配置文件】
### set log levels ###
log4j.rootLogger = debug , stdout , D , E
### 输出到控制台 ###
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 = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
### 输出到日志文件 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG ## 输出DEBUG级别以上的日志
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 保存异常信息到单独文件 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/error.log ## 异常日志文件名
log4j.appender.D.Append = true
log4j.appender.D.Threshold = ERROR ## 只输出ERROR级别以上的日志!!!
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
【代码中使用】
public class TestLog4j {
public static void main(String[] args) {
PropertyConfigurator.configure( " D:/Code/conf/log4j.properties " );
Logger logger = Logger.getLogger(TestLog4j. class );
logger.debug( " debug " );
logger.error( " error " );
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.