#
對數數組中的內容強排序
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class TestComparator {
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add(new Persion("lcl",28));
list.add(new Persion("fx",23));
list.add(new Persion("wqx",29));
Comparator comp = new Comparator(){
public int compare(Object o1,Object o2) {
Persion p1=(Persion)o1;
Persion p2=(Persion)o2;
if(p1.age<p2.age)
return 1;
else
return 0;
}
};
Collections.sort(list,comp);
for(int i=0;i<list.size();i++){
Persion p=(Persion) list.get(i);
System.out.println(p.age+"+"+p.name);
}
}
}
如果在Unity3D中或者Flex中訪問tomcat會出現訪問協議異常 做下面的配置即可解決
crossdomain.xml 位置 將這兩個文件放在tomcat主目錄下即 %TOMCAT_HOME%\webapps\ROOT 下可以避免不同項目相互訪問資源導致的權限問題。
web訪問位置http://your_host:port/crossdomain.xml,成功訪問該文件即可。
1.crossdomain.xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "./cross-domain-policy.dtd">
<cross-domain-policy> <site-control permitted-cross-domain-policies="all" />
<allow-access-from domain="*" />
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
2.cross-domain-policy.dtd
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Adobe DTD for cross-domain policy files -->
<!-- Copyright (c) 2008-2009, Adobe Systems Inc. -->
<!ELEMENT cross-domain-policy (site-control?,allow-access-from*,allow-http-request-headers-from*,allow-access-from-identity*)>
<!ELEMENT site-control EMPTY>
<!ATTLIST site-control permitted-cross-domain-policies (all|by-content-type|by-ftp-filename|master-only|none) #REQUIRED>
<!ELEMENT allow-access-from EMPTY>
<!ATTLIST allow-access-from domain CDATA #REQUIRED>
<!ATTLIST allow-access-from to-ports CDATA #IMPLIED>
<!ATTLIST allow-access-from secure (true|false) "true">
<!ELEMENT allow-http-request-headers-from EMPTY>
<!ATTLIST allow-http-request-headers-from domain CDATA #REQUIRED>
<!ATTLIST allow-http-request-headers-from headers CDATA #REQUIRED>
<!ATTLIST allow-http-request-headers-from secure (true|false) "true">
<!ELEMENT allow-access-from-identity (signatory)>
<!ELEMENT signatory (certificate)>
<!ELEMENT certificate EMPTY>
<!ATTLIST certificate fingerprint CDATA #REQUIRED>
<!ATTLIST certificate fingerprint-algorithm CDATA #REQUIRED>
<!-- End of file. -->
本文講述Hibernate的generator屬性的意義。Generator屬性有7種class,本文簡略描述了這7種class的意義和用法。
- <class name="onlyfun.caterpillar.User"
- table="USER">
- <id name="id" type="string" unsaved-value="null">
- <column name="USER_ID"/>
- <generator class="uuid.hex"/>
- </id>
- </class>
Hibernate的Generator屬性有7種class,本文簡略描述了這7種class的意義和用法。
1、identity:用于MySql數據庫。特點:遞增
- <id name="id" column="id">
- < generator class="identity"/>
- </id>
注:對于MySql數據庫使用遞增序列時需要在建表時對主鍵指定為auto_increment屬性。
2、sequence:用于Oracle數據庫
- <id name="id" column="id">
- <generator class="sequence">
- <param name="sequence">序列名</param>
- </generator>
- </id>
3、native:跨數據庫時使用,由底層方言產生。
Default.sequence為hibernate_sequence
- <id name="id" column="id">
- <generator class="native"/>
- </id>
注:使用native時Hibernate默認會去查找Oracle中的hibernate_sequence序列。
如果Oracle中沒有該序列,連Oracle數據庫時會報錯。
4、hilo:通過高低位合成id,先建表hi_value,再建列next_value。必須要有初始值。
- <id name="id" column="id">
- <generator class="hilo">
- <param name="table">high_val</param>
- <param name="column">nextval</param>
- <param name="max_lo">5</param>
- </generator>
- </id>
5、sequencehilo:同過高低位合成id,建一個sequence序列,不用建表。
- <id name="id" column="id">
- <generator class="hilo">
- <param name="sequence">high_val_seq</param>
- <param name="max_lo">5</param>
- </generator>
- </id>
6、assigned:用戶自定義id;
- <id name="id" column="id">
- <generator class="assigned"/>
- </id>
7、foreign:用于一對一關系共享主健時,兩id值一樣。
本文講解Hibernate中hbm的generator子元素的一些內置生成器的快捷名字。Generator子元素是一個非常簡單的接口;某些應用程序可以選擇提供他們自己特定的實現。
在*.hbm.xml必須聲明的< generator>子元素是一個Java類的名字,用來為該持久化類的實例生成唯一的標識。
- <generator class="sequence"/>
這是一個非常簡單的接口;某些應用程序可以選擇提供他們自己特定的實現。當然,Hibernate提供了很多內置的實現。下面是Generator子元素的一些內置生成器的快捷名字:
increment(遞增)
用于為long, short或者int類型生成唯一標識。只有在沒有其他進程往同一張表中插入數據時才能使用。 在集群下不要使用。
identity
對DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的內置標識字段提供支持。返回的標識符是long, short 或者int類型的。
sequence (序列)
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence),而在Interbase中使用生成器(generator)。返回的標識符是long, short或者 int類型的。
hilo (高低位)
使用一個高/低位算法來高效的生成long, short或者 int類型的標識符。給定一個表和字段(默認分別是是hibernate_unique_key 和next_hi)作為高位值得來源。高/低位算法生成的標識符只在一個特定的數據庫中是唯一的。在使用JTA獲得的連接或者用戶自行提供的連接中,不要使用這種生成器。
seqhilo(使用序列的高低位)
使用一個高/低位算法來高效的生成long, short或者 int類型的標識符,給定一個數據庫序列(sequence)的名字。
uuid.hex
用一個128-bit的UUID算法生成字符串類型的標識符。在一個網絡中唯一(使用了IP地址)。UUID被編碼為一個32位16進制數字的字符串。
uuid.string
使用同樣的UUID算法。UUID被編碼為一個16個字符長的任意ASCII字符組成的字符串。不能使用在PostgreSQL數據庫中
native(本地)
根據底層數據庫的能力選擇identity, sequence 或者hilo中的一個。
assigned(程序設置)
讓應用程序在save()之前為對象分配一個標示符。
foreign(外部引用)
使用另外一個相關聯的對象的標識符。和< one-to-one>聯合一起使用。
Generator子元素的用法:
- <class name="onlyfun.caterpillar.User" table="USER">
- <id name="id" type="string" unsaved-value="null">
- <column name="USER_ID"/>
- <generator class="uuid.hex"/>
- </id>
- </class>
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 用戶數據庫訪問的類
*@作者Administrator
*@createTime 2011-12-5 上午11:55:18
*@version 1.0
*/
public class DButil1 {
private Connection conn;
private Statement st;
private PreparedStatement pps;
private ResultSet rs;
public String url="jdbc:oracle:thin:@localhost:1521:orcl";
private String user="hyl";
private String password="hyl";
//加載驅動、放在靜態代碼塊中,保證驅動在整個項目中只加載一次,提高效率
static{
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 獲取連接的方法
* @return Connection 一個有效的數據庫連接
*/
public Connection getConnection()
{
try {
//注意鏈接時,要換成自己的數據庫名,數據庫用戶名及密碼
Connection con=DriverManager.getConnection(url,user,password);
return con;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 用于執行更新的方法,包括(insert delete update)操作
* @param sql String 類型的SQL語句
* @return Integer 表示受影響的行數
*/
public int update(String sql)
{
//定義變量用來判斷更新操作是否成功,如果返回-1說明沒有影響到更新操作的數據庫記錄條數,即更新操作失敗
int row=-1;
try {
//如果數據庫鏈接被關閉了,就要既得一個新的鏈接
if(conn==null||conn.isClosed()){
conn=getConnection();
}
//使用Connection對象conn的createStatement()創建Statement(數據庫語句對象)st
st=conn.createStatement();
//執行更新操作,返回影響的記錄條數row
row=st.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
finally{
close();
}
return row;
}
/**
* 基于PreparedStatement的修改方法 PreparedStatement:表示預編譯的 SQL 語句的對象
* @param sql String 類型的SQL語句(insert delete update)
* @param obj 存放動態參數的數組
* @return Integer 表示受影響的行數
*/
public int update(String sql,Object ...obj)
{
try {
//獲取鏈接
if(conn==null||conn.isClosed()){
conn=getConnection();
}
//創建預編譯的 SQL 語句對象
pps=conn.prepareStatement(sql);
//定義變量length代表數組長度,也就是預處理的sql語句中的參數個數
int length=0;
//ParameterMetaData:用于獲取關于 PreparedStatement 對象中每個參數的類型和屬性信息的對象
ParameterMetaData pmd=pps.getParameterMetaData();
length=pmd.getParameterCount();
//循環將sql語句中的?設置為obj數組中對應的值,注意從1開始,所以i要加1
for(int i=0;i<length;i++)
{
pps.setObject(i+1, obj[i]);
}
//執行更新操作
return pps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally{
close();
}
return -1;
}
/**
* 獲取一條記錄的方法,要依賴于下面的queryToList方法,注意泛型的使用
* @param sql
* @return Map<String,Object>
*/
public Map<String,Object> getOneRow(String sql)
{
//執行下面的queryToList方法
List<Map<String,Object>> list=queryToList(sql);
//三目運算,查詢結果list不為空返回list中第一個對象,否則返回null
return list.size()>0?list.get(0):null;
}
/**
* 返回查詢結果列表,形如:[{TEST_NAME=aaa, TEST_NO=2, TEST_PWD=aaa}, {TEST_NAME=bbb, TEST_NO=3, TEST_PWD=bbb}...]
* @param sql
* @return List<Map<String,Object>>
*/
public List<Map<String,Object>> queryToList(String sql)
{
//創建集合列表用以保存所有查詢到的記錄
List<Map<String, Object>> list=new LinkedList<Map<String, Object>>();
try {
if(conn==null||conn.isClosed()){
conn=getConnection();
}
st=conn.createStatement();
rs=st.executeQuery(sql);
//ResultSetMetaData 是結果集元數據,可獲取關于 ResultSet 對象中列的類型和屬性信息的對象 例如:結果集中共包括多少列,每列的名稱和類型等信息
ResultSetMetaData rsmd=rs.getMetaData();
//獲取結果集中的列數
int columncount=rsmd.getColumnCount();
//while條件成立表明結果集中存在數據
while(rs.next())
{
//創建一個HashMap用于存儲一條數據
HashMap<String, Object> onerow=new HashMap<String, Object>();
//循環獲取結果集中的列名及列名所對應的值,每次循環都得到一個對象,形如:{TEST_NAME=aaa, TEST_NO=2, TEST_PWD=aaa}
for(int i=0;i<columncount;i++)
{
//獲取指定列的名稱,注意orcle中列名的大小寫
String columnName=rsmd.getColumnName(i+1);
onerow.put(columnName, rs.getObject(i+1));
}
//將獲取到的對象onewrow={TEST_NAME=aaa, TEST_NO=2, TEST_PWD=aaa}放到集合列表中
list.add(onerow);
}
}catch (SQLException e) {
e.printStackTrace();
}
finally{
close();
}
return list;
}
/**
* 返回查詢結果列表,使用的是預編繹SQL 語句對象PreparedStatement
* 形如:[{TEST_NAME=aaa, TEST_NO=2, TEST_PWD=aaa}, {TEST_NAME=bbb, TEST_NO=3, TEST_PWD=bbb}]
* @param sql
* @param paramValues
* @return List<Map<String,Object>>
*/
public List<Map<String,Object>> queryWithParam(String sql,Object ...paramValues){
//創建集合列表用以保存所有查詢到的記錄
List<Map<String, Object>> list=new LinkedList<Map<String, Object>>();
try {
if(conn==null||conn.isClosed()){
conn=getConnection();
}
pps = conn.prepareStatement(sql);
for (int i = 0; i < paramValues.length; i++) {
pps.setObject(i + 1, paramValues[i]);
}
rs = pps.executeQuery();
//ResultSetMetaData 是結果集元數據,可獲取關于 ResultSet 對象中列的類型和屬性信息的對象 例如:結果集中共包括多少列,每列的名稱和類型等信息
ResultSetMetaData rsmd=rs.getMetaData();
//獲取結果集中的列數
int columncount=rsmd.getColumnCount();
//while條件成立表明結果集中存在數據
while (rs.next()) {
//創建一個HashMap用于存儲一條數據
HashMap<String, Object> onerow=new HashMap<String, Object>();
//循環獲取結果集中的列名及列名所對應的值,每次循環都得到一個對象,形如:{TEST_NAME=aaa, TEST_NO=2, TEST_PWD=aaa}
for(int i=0;i<columncount;i++)
{
//獲取指定列的名稱,注意orcle中列名的大小寫
String columnName=rsmd.getColumnName(i+1);
onerow.put(columnName, rs.getObject(i+1));
}
//將獲取到的對象onewrow={TEST_NAME=aaa, TEST_NO=2, TEST_PWD=aaa}放到集合列表中
list.add(onerow);
}
}catch (SQLException e) {
e.printStackTrace();
}
finally{
close();
}
return list;
}
/**
* 實現oracle分頁功能
* @param sql
* @param pagesize
* @param pagenow
* @return PageBean
*/
public PageBean getPage(String sql,int pagesize,int pagenow)
{
PageBean pb=new PageBean();
int end=pagenow*pagesize;
int start=end-pagesize+1;
String exesql="select a.* from (select t.*,rownum as rowindex from ("+sql+") t where rownum<="+end+" ) a where a.rowindex>="+start;
String countsql="select count(*) as rowcount from ("+sql+")";
pb.setResult(queryToList(exesql));
pb.setPagenow(pagenow);
pb.setPagesize(pagesize);
Map<String,Object> map=this.getOneRow(countsql);
int rows=Integer.parseInt(map.get("ROWCOUNT").toString());
pb.setRows(rows);
int pages=rows%pagesize==0?rows/pagesize:rows/pagesize+1;
pb.setPages(pages);
pb.setSql(sql);
return pb;
}
/**
* 關閉數據庫各種資源Connection Statement PreparedStatement ResultSet的方法
*/
private void close()
{
if(rs!=null)
{
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(st!=null)
{
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pps!=null){
try {
pps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
try {
if(conn!=null&&!conn.isClosed())
{
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
首先寫一個計數的類OnlineCounter
package accp.onlinecounter;
public class OnlineCounter {
private static long online = 0;
public static long getOnline() {
return online;
}
public static void raise() {
online++;
}
public static void reduce() {
online--;
}
}
之后寫一個實現HttpSessionEvent的類OnlineCounterListener
package accp.onlinecounter;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCounterListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent hse) {
OnlineCounter.raise();
}
public void sessionDestroyed(HttpSessionEvent hse) {
OnlineCounter.reduce();
}
}
在web.xml中寫listener的注冊信息
<listener>
<listener-class>
accp.onlinecounter.OnlineCounterListener
</listener-class>
</listener>
前臺界面寫上
<body>
在線人數: <%=OnlineCounter.getOnline() %><br/>
<a href="adcourse.jsp">添加課程add course</a><br/>
<a href="adds.jsp">添加學生add stu</a><br/>
<a href="findallcourse.jsp">查詢課程信息 select course</a><br/>
<a href="findallstudent.jsp">查詢學生信息 select student</a><br/>
<a href="addstudentcourse.jsp">添加選課信息add student course</a><br/>
<a href="querystucourse.jsp">查詢選課信息query student course</a><br/>
</body>
注意引入包即可
方法一、 解決的辦法自然是用相對路徑代替絕對路徑,其實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
首先導入兩個包: commons-logging.jar log4j-1.2.12.jar
在src下編寫3個 properties文件
1.log4j.properties 下面是內容
##LOGGERS
#define a logger
log4j.rootLogger=INFO,console,file
##APPENDERS
#define an appender named console
log4j.appender.console=org.apache.log4j.ConsoleAppender
#define an appender named file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=d:/demo_log.txt
#set the log's size
log4j.appender.file.MaxFileSize=1000KB
log4j.appender.file.MaxBackupIndex=20
##LAYOUTS
#assign a SimpleLayout to console appender
log4j.appender.console.layout=org.apache.log4j.SimpleLayout
#assign a PatternLayout to file appender
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}]%m%n
2.
simplelog.properties下面是內容
log.apache.commons.logging.simplelog.defaultlog=info
3.
commons-logging.properties下面是內容
##set Log as Log4J
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger