日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

纠结的velocity log那些事(出现Permission denied)

發布時間:2025/3/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 纠结的velocity log那些事(出现Permission denied) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景  

  最近開始使用jetty做為我們的應用web容器,在遷移過程中發現一個比較隱晦的問題,原本在jboss容器跑的好好的應用,換到jetty容器上,直接不可用。出現一些莫名奇妙的錯誤。

?

現象

說明:我們應用中有代碼使用了velocity處理一些業務,比如模板輸出,自定義渲染引擎等。

?

使用例子:


1.RuntimeInstance ri = new RuntimeInstance(); 2. 3...... 4.ri.parse(new StringReader(script), name); //進行渲染腳本處理

換成jetty后,會莫名的出現一個異常信息,截取了一個異常描述:


1.caused by: java.lang.RuntimeException: Error configuring Log4JLogChute : 2. at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 3. at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 4. at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 5. at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 6. at org.apache.velocity.util.ExceptionUtils.createWithCause(ExceptionUtils.java:67) 7. at org.apache.velocity.util.ExceptionUtils.createRuntimeException(ExceptionUtils.java:45) 8. at org.apache.velocity.runtime.log.Log4JLogChute.initAppender(Log4JLogChute.java:133) 9. at org.apache.velocity.runtime.log.Log4JLogChute.init(Log4JLogChute.java:85) 10. at org.apache.velocity.runtime.log.LogManager.createLogChute(LogManager.java:157) 11. ... 33 more 12.Caused by: java.io.FileNotFoundException: velocity.log (Permission denied) 13. at java.io.FileOutputStream.openAppend(Native Method) 14. at java.io.FileOutputStream.(FileOutputStream.java:177) 15. at java.io.FileOutputStream.(FileOutputStream.java:102) 16. at org.apache.log4j.FileAppender.setFile(FileAppender.java:290) 17. at org.apache.log4j.RollingFileAppender.setFile(RollingFileAppender.java:194) 18. at org.apache.log4j.FileAppender.(FileAppender.java:109) 19. at org.apache.log4j.RollingFileAppender.(RollingFileAppender.java:72) 20. at org.apache.velocity.runtime.log.Log4JLogChute.initAppender(Log4JLogChute.java:118) 21. ... 35 more

換回jboss容器后,一切正常,沒有出現任何異常。

?

分析

?? 查找問題最好的利器就是debug,我也不例外。開啟remote debug,一步步跟蹤代碼,發現最后的問題出在RuntimeInstance.init()調用initializeLog()方法上,說白了就是velocity日志處理上。

?

展開分析之前,先大致了解下velocity的日志處理。

?

velocity的3個關于日志記錄的參數:

  • runtime.log.logsystem ????? (對應的logsystem實例)
  • runtime.log.logsystem.class (對應的logsystem實現類)
  • runtime.log? (日志文件名稱)

備注: logsystem是velocity 1.5版本以前早期的log一套實現接口,現在1.5以后建議都使用logchute,而且早的logsystem一套也不建議被使用,@deprecated Use LogChute instead!

?

類圖:


Log :? 對LogChute的一個delegate,提供一些遍歷的方法,比如info(),warn()不同級別的日志記錄方法。

LogChute:? velocity中定義的日志處理接口,目前支持各種類型的Log三方包,同時支持System.out,NullLog等特殊類型。

LogMananger : velocity管理Log對象的入口,里面有個方法updateLog(Log log, RuntimeServices rsvc),就是本次出問題的點。

?

針對每種LogChute實現,都有自己一些特殊的配置項, (大家都知道velocity配置項可以是通過velocity.properties進行配置)

?

比如log4j的配置項,代碼:Log4JLogChute

  • runtime.log.logsystem.log4j.logger (對應于log4j.xml配置中的Logger name,如果沒有就使用class獲取Logger,同時獲取runtime.log屬性作為日志輸出的文件)
  • runtime.log.logsystem.log4j.logger.level (轉化log4j的level到velocity log中,可覆蓋Logger)

?

再來理一下,velocity整個初始化日志過程:

  • new RuntimeInstance(),屬性Log log = new Log(), 默認創建一個HoldingLogChute()做為LogChute,(該LogChute臨時記錄日志到內存對象上)
  • RuntimeInstance.init() 進行velocity系統初始化
  • 順序調用initializeProperties(), 讀取velocity.properties默認配置,合并自定義的properties。
  • 順序調用initializeLog() ,調用LogManager.updateLog(),進行Log初始化
  • LogManager.createLogChute()會首先讀取runtime.log.logsystem配置,看看是否有存在自定義的LogChute實例對象,如果有則直接使用,并返回
  • 在沒有對應的LogChute實例對象配置,繼續讀取runtime.log.logsystem.class,看看似乎否有logsystem的配置,就是前面類圖中的一對LogChute,LogSystem的實現類。
    1.runtime.log.logsystem.class = org.apache.velocity.runtime.log.AvalonLogChute,org.apache.velocity.runtime.log.Log4JLogChute,org.apache.velocity.runtime.log.CommonsLogLogChute,org.apache.velocity.runtime.log.ServletLogChute,org.apache.velocity.runtime.log.JdkLogChute
  • ?按照順序,逐一加載LogChute實現類,如果class裝載成功,則進行初始化,并返回
  • LogManager,針對createLogChute,將系統初始時HoldingLogChute記錄的內容,輸出到新的LogChute上,最后完成了log的初始化

  • ?

    了解了velocity的整套log機制后,再來看該問題: 

    • 使用時沒有設置velocity log的任何參數,因為系統中存在Log4j的包,所以會使用Log4jChute做為Log記錄的對象返回。
    • 在初始化Log4jChute時,沒有設置logger.name,初始化Logger時,會使用默認的velocity.log做為文件輸出路徑
    • File file = new File("velocity.log"),大家知道這樣的文件創建,是基于當前jvm的current work,也就是user.dir屬性。(可以通過jinfo $pid | grep user.dir進行查看)

    ok,現在的問題已經很明了,異常中提示velocity.log無權限,只需要check一下當前jvm進程的user.dir屬性。

    最后檢查結果:

    • jboss作為web容器時,user.dir=/home/ljh/web-deploy/bin? (當前的啟動腳本所在目錄)
    • jetty作為web容器時,user.dir = /usr/local/program/jetty-7.2.0 (所指定的jetty.home變量路徑)

    剛好我用的是linux系統,軟件安裝路徑的權限都是root用戶,運行web應用的都是普通用戶,所以也讓我撞上了這個問題。

    ?

    ?

    說明:jboss和jetty我都是通過調用自帶的run.sh和jetty.sh進行啟動,存在這樣的差異也是讓我很無語的,幾點建議。

    • 大家盡量在寫代碼時做到容器無關性
    • 盡量避免使用相對目錄

    解決

    深入了解了velocity log機制后,解決方案就有很多種了

    ?

    方案一:暴力型,啥都不輸出


    1.RuntimeInstance ri = new RuntimeInstance(); 2........ 3.if (!ri.isInitialized()) { 4. // 設置空的log,避免使用velocity默認的veloicyt.log 5. ri.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new NullLogChute()); 6. ri.init(); 7. }

    說明:針對應用中的渲染引擎,可以直接使用NullLogChute(),不做任何的日志輸出。

    ?

    方案二:統一型,融合到現有的log框架


    1.RuntimeInstance ri = new RuntimeInstance(); 2....... 3.if (!ri.isInitialized()) { 4. ....... 5. // 自定義LogChute,代理到應用的Log對象上,統一使用Log4j.xml進行管理 6. ri.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new LogChute() { 7. public void init(RuntimeServices runtimeServices) { 8. } 9. 10. public void log(int level, String message) { 11. log(level, message, null); 12. } 13. 14. public void log(int level, String message, Throwable t) { 15. switch (level) { 16. case TRACE_ID: 17. getLogger().trace(message, t); 18. break; 19. 20. case DEBUG_ID: 21. getLogger().debug(message, t); 22. break; 23. 24. case INFO_ID: 25. getLogger().info(message, t); 26. break; 27. 28. case WARN_ID: 29. getLogger().warn(message, t); 30. break; 31. 32. case ERROR_ID: 33. getLogger().error(message, t); 34. break; 35. 36. default: 37. } 38. } 39. 40. public boolean isLevelEnabled(int level) { 41. switch (level) { 42. case TRACE_ID: 43. return getLogger().isTraceEnabled(); 44. 45. case DEBUG_ID: 46. return getLogger().isDebugEnabled(); 47. 48. case INFO_ID: 49. return getLogger().isInfoEnabled(); 50. 51. case WARN_ID: 52. return getLogger().isWarnEnabled(); 53. 54. case ERROR_ID: 55. return getLogger().isErrorEnabled(); 56. 57. default: 58. return false; 59. } 60. } 61. }); 62. 63. ri.init(); 64. }

    說明:使用內部匿名類,將LogChute代理到當前class類的getLogger對象上,這樣實現和當前web容器的整合,可以統一使用log4j.xml進行管理,只需要設置好Velocity 包裝class的logger即可。

    ?


    ?

    現在還有比較流行Slf4jLog,同樣可以寫一個Slf4jLogChute。一個小建議:對WARN以下level不記錄異常的詳細stack詳情 ── 避免Velocity在找不到資源時會打印異常,直接打印e.getMessage()

    ?

    異常的stack打印還是比較消耗性能的,具體可以看下我同事的一篇分析文章,使用異常耗性能到底耗在哪一塊http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html。


    總結

    以上是生活随笔為你收集整理的纠结的velocity log那些事(出现Permission denied)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 91看片国产| 午夜免费网址 | 亚洲国产精品成人午夜在线观看 | 久久久久久九九 | 天天舔天天操 | 日本免费一区二区三区 | 超碰在线国产 | 麻豆av一区二区三区 | 国产欧美一区二区在线 | 免费看黄色的网站 | 日韩有码在线播放 | a黄色一级片 | av一级大片 | 欧美一区二区二区 | 欧美色图1 | 经典三级视频 | 五月天一区二区 | 夜色在线影院 | 国产精品无码成人网站视频 | 天天操夜夜操视频 | 人日人视频 | 大又大又粗又硬又爽少妇毛片 | 日韩美女视频在线观看 | 影音先锋一区 | 日韩人妻精品一区二区三区视频 | missav | 免费高清av在线看 | 翔田千里在线播放 | 日韩欧美在线视频 | 国产精品高清在线 | 精品少妇人妻av一区二区 | 久久人妻免费视频 | 麻豆av一区二区三区 | 中文字幕人成人乱码亚洲电影 | 黄色片视频 | 亚洲综合天堂 | 午夜精品久久 | eeuss一区二区 | 黄色调教视频 | 少妇一夜三次一区二区 | chinese麻豆新拍video | 国产精品成人免费精品自在线观看 | 亚洲一区 欧美 | 国内毛片毛片毛片毛片 | 久操视频精品 | 欧美性生活精品 | 国产精品第5页 | 欧美小视频在线观看 | 国产免费福利视频 | 嫩草研究院在线 | 郑艳丽三级 | aa免费视频 | 一级肉体全黄裸片中国 | 久草视频首页 | 半推半就一ⅹ99av | 久久频| 2025中文字幕| 老司机久久 | 亚洲自拍偷拍一区 | 美女主播在线观看 | 婚后打屁股高h1v1调教 | 日韩色图在线观看 | 国产精品黄色片 | 久久蜜臀精品av | 人人妻人人澡人人爽人人欧美一区 | 国产免费看av | 国产精品无码久久久久一区二区 | 欧美日韩亚洲在线观看 | 国产精品一区二区无码对白 | 亚洲AV无码成人片在线观看 | 人人干人人舔 | 午夜视频福利在线观看 | 三度诱惑免费版电影在线观看 | 野外吮她的花蒂高h在线观看 | 久久久久国产精品一区 | 91香蕉视频在线看 | 青青草伊人网 | 一本一道久久 | 久久黄色精品视频 | 亚洲色图综合网 | 中文字幕二区在线观看 | 三级免费毛片 | 在线观看的毛片 | 国产精品一区二区在线免费观看 | 麻豆91精品 | 午夜视频日韩 | 99视频国产精品 | 国产精品熟妇一区二区三区四区 | 国产欧美日韩综合精品 | 久久中文字幕国产 | 欧美日韩黄色 | av手机在线观看 | 精品久久久久久无码中文野结衣 | 人妻一区二区三区在线 | 粉嫩久久99精品久久久久久夜 | 国产精品第六页 | 国产伦乱视频 | 午夜一级黄色片 | 九色视频国产 | 日韩毛片在线看 |