XMLHttpRequest的POST中文表单问题解决方案

Posted on

XMLHttpRequest的POST中文表单问题解决方案

esffor

2007-03-15

XMLHttpRequest的POST中文表单问题解决方案

由于XMLHttpRequest POST的内容是用UTF-8编码,所以在服务端要先把request的编码改为UTF-8. 而且客户端post的表单是x-www-form-urlencoded的,所以也要对post的内容进行编码encodeURIComponent()函数 escape() 只是为 ASCII字符 做转换工作,转换成的 %unnnn 这样的码,如果要用更多的字符如 UTF-8字符库 就一定要用 encodeURIComponent() 或 encodeURI() 转换才可以成 %nn%nn 还有 escape() 不编码这些字符: @//+ encodeURI() 不编码这些字符: [!@/#$&/()=:/;?+'](mailto:!@) encodeURIComponent() 不编码这些字符: !/*()'

还是推荐使用encodeURIComponent()函数来编码比较好。

代码如下:

在客户端的js脚本

JSP

<%@page language="java" contentType="text/html;charset=gbk"%> <% request.setCharacterEncoding("UTF-8"); System.out.println(request.getParameter("user")); %>

Log4j写入数据库详解

Posted on

Log4j写入数据库详解 - ziruobing的专栏 - CSDN博客

您还未登录!|登录|注册|帮助

ziruobing的专栏

黑暗中漫舞

*

公告:

原创 Log4j写入数据库详解 收藏

log4j是一个优秀的开源日志记录项目,我们不仅可以对输出的日志的格式自定义,还可以自己定义日志输出的目的地,比如:屏幕,文本文件,数据库,甚至能通过socket输出。本节主要讲述如何将日志信息输入到数据库(可以插入任何数据库,在此主要以MSSQL为例进行详解)。 用log4j将日志写入数据库主要用到是log4j包下的JDBCAppender类,它提供了将日志信息异步写入数据的功能,我们可以直接使用这个类将我们的日志信息写入数据库;也可以扩展JDBCAppender类,就是将JDBCAppender类作为基类。下面将通过一个实例来讲解log4j是如何将日志信息写入数据库的。 我们的需求:我们在软件开发的过程中需要将调试信息、操作信息等记录下来,以便后面的审计,这些日志信息包括用户ID、用户姓名、操作类、路径、方法、操作时间、日志信息。 设计思想:我们采用JDBCAppender类直接将日志信息插入数据库,所有只需要在配置文件配置此类就可以;要获得用户信息需要用过滤器来实现;(假如不需要用户的信息,就不需要设计过滤器,其实大部分情况下都是需要这些用户信息,尤其是在web应用开发中)在日志信息中获得用户信息,就的通过过滤器的request或session对象,从session中拿到用户信息怎样传到log4j呢,log4j为我们提供了MDC(MDC是log4j种非常有用类,它们用于存储应用程序的上下文信息(context infomation),从而便于在log中使用这些上下文信息。MDC内部使用了类似map的机制来存储信息,上下文信息也是每个线程独立地储存,所不同的是信息都是以它们的key值存储在”map”中。相对应的方法,

MDC.put(key, value); MDC.remove(key); MDC.get(key);

在配置PatternLayout的时候使用:%x{key}来输出对应的value)。有了MDC,我们可以在过滤器中先获得用户信息,再用MDC.Put(“key”)方法,log在执行sql语句时通过%x{key}来输出对应的value。

实现步骤: 1、在你的项目中要确保有log4j和commons-logging这两个jar文件; 2、设置要你要插入日志信息的表结构

  1. if exists (select /* from dbo.sysobjects where id = object_id(N'[dbo].[WDZLOG]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
  2. drop table [dbo].[WDZLOG]
  3. GO
  4. CREATE TABLE [dbo].[WDZLOG] (
  5. [WDZLOGID] [int] IDENTITY (1, 1) NOT NULL ,
  6. [LogName] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//用户ID
  7. [UserName] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//用户姓名
  8. [Class] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//类名
  9. [Mothod] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL //,方法名
  10. [CreateTime] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//产生时间
  11. [LogLevel] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,//日志级别
  12. [MSG] [varchar] (555) COLLATE Chinese_PRC_CI_AS NULL //日志信息
  13. ) ON [PRIMARY]
  14. GO
    if exists (select /* from dbo.sysobjects where id = object_id(N'[dbo].[WDZLOG]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [dbo].[WDZLOG] GO CREATE TABLE [dbo].[WDZLOG] ( [WDZLOGID] [int] IDENTITY (1, 1) NOT NULL , [LogName] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//用户ID [UserName] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//用户姓名 [Class] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//类名 [Mothod] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL //,方法名 [CreateTime] [varchar] (255) COLLATE Chinese_PRC_CI_AS NULL ,//产生时间 [LogLevel] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL ,//日志级别 [MSG] [varchar] (555) COLLATE Chinese_PRC_CI_AS NULL //日志信息 ) ON [PRIMARY] GO

3、配置文件(摘自我们的项目)后面将对此配置文件进行详细讲解,它也log4j的核心部分。

  1. log4j.properties
  2. log4j.rootLogger=INFO,stdout
  3. log4j.logger.org.springframework.web.servlet=INFO,db
  4. log4j.logger.org.springframework.beans.factory.xml=INFO
  5. log4j.logger.com.neam.stum.user=INFO,db
  6. log4j.appender.stdout=org.apache.log4j.ConsoleAppender
  7. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
  8. log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] - - <%m>%n
  9. log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
  10. log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/exppower.log
  11. log4j.appender.logfile.DatePattern=.yyyy-MM-dd
  12. log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
  13. log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] wang- <%m>%n
  14. /#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#
  15. /# JDBC Appender
  16. /#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#
  17. /#log4j.logger.business=INFO,db
  18. /#log4j.appender.db=com.neam.commons.MyJDBCAppender
  19. log4j.appender.db=JDBCExtAppender
  20. log4j.appender.db.BufferSize=10
  21. log4j.appender.db.sqlname=log
  22. log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver
  23. log4j.appender.db.URL=jdbc:jtds:SqlServer://localhost:1433;DatabaseName=pubs
  24. log4j.appender.db.user=sa
  25. log4j.appender.db.password=sa
  26. log4j.appender.db.sql=insert into WDZLOG (LogName,UserName,Class,Mothod,createTime,LogLevel,MSG) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m')
  27. log4j.appender.db.layout=org.apache.log4j.PatternLayout
    log4j.properties log4j.rootLogger=INFO,stdout log4j.logger.org.springframework.web.servlet=INFO,db log4j.logger.org.springframework.beans.factory.xml=INFO log4j.logger.com.neam.stum.user=INFO,db log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] - - <%m>%n log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/exppower.log log4j.appender.logfile.DatePattern=.yyyy-MM-dd log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] wang- <%m>%n /#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/# /# JDBC Appender /#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/# /#log4j.logger.business=INFO,db /#log4j.appender.db=com.neam.commons.MyJDBCAppender log4j.appender.db=JDBCExtAppender log4j.appender.db.BufferSize=10 log4j.appender.db.sqlname=log log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver log4j.appender.db.URL=jdbc:jtds:SqlServer://localhost:1433;DatabaseName=pubs log4j.appender.db.user=sa log4j.appender.db.password=sa log4j.appender.db.sql=insert into WDZLOG (LogName,UserName,Class,Mothod,createTime,LogLevel,MSG) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m') log4j.appender.db.layout=org.apache.log4j.PatternLayout

4、编写过滤器(ResFilter.java)

  1. import java.io.IOException;
  2. import javax.servlet.Filter;
  3. import javax.servlet.FilterChain;
  4. import javax.servlet.FilterConfig;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.ServletRequest;
  7. import javax.servlet.ServletResponse;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpSession;
  10. import org.apache.log4j.Logger;
  11. import org.apache.log4j.MDC;
  12. import com.neam.domain.User;
  13. public class ResFilter implements Filter{
  14. private final static double DEFAULT_USERID= Math.random()/*100000.0;
  15. public void destroy() {
  16. }
  17. public void doFilter(ServletRequest request, ServletResponse response,
  18. FilterChain chain) throws IOException, ServletException {
  19. HttpServletRequest req=(HttpServletRequest)request;
  20. HttpSession session= req.getSession();
  21. if (session==null){
  22. MDC.put("userId",DEFAULT_USERID);
  23. }
  24. else{
  25. User customer=(User)session.getAttribute("user");
  26. if (customer==null){
  27. MDC.put("userId",DEFAULT_USERID);
  28. MDC.put("userName",DEFAULT_USERID);
  29. }
  30. else
  31. {
  32. MDC.put("userId",customer.getName());
  33. MDC.put("userName",customer.getName());
  34. }
  35. }
  36. //logger.info("test for MDC.");
  37. chain.doFilter(request, response);
  38. }
  39. public void init(FilterConfig Config) throws ServletException {
  40. // this.filterConfig = Config;
  41. // String ccc = Config.getServletContext().getInitParameter("cherset");
  42. // this.targetEncoding = Config.getInitParameter("cherset");
  43. }
  44. }
    import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.apache.log4j.MDC; import com.neam.domain.User; public class ResFilter implements Filter{ private final static double DEFAULT_USERID= Math.random()/*100000.0; public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest)request; HttpSession session= req.getSession(); if (session==null){ MDC.put("userId",DEFAULT_USERID); } else{ User customer=(User)session.getAttribute("user"); if (customer==null){ MDC.put("userId",DEFAULT_USERID); MDC.put("userName",DEFAULT_USERID); } else { MDC.put("userId",customer.getName()); MDC.put("userName",customer.getName()); } } //logger.info("test for MDC."); chain.doFilter(request, response); } public void init(FilterConfig Config) throws ServletException { // this.filterConfig = Config; // String ccc = Config.getServletContext().getInitParameter("cherset"); // this.targetEncoding = Config.getInitParameter("cherset"); } }

5、在需要写入日志的地方引入

  1. private Log logger = LogFactory.getLog(this.getClass());
  2. 在具体方法中就可以写入日志
  3. logger.info("");
  4. logger.debug("");
  5. logger.warn("");
  6. logger.error("");
    private Log logger = LogFactory.getLog(this.getClass()); 在具体方法中就可以写入日志 logger.info(""); logger.debug(""); logger.warn(""); logger.error("");

配置文件详解: log4j.properties log4j.properties log4j.rootLogger=INFO,stdout

//配置根Logger,其语法为: log4j.rootLogger = [ level ] , appenderName1, appenderName2, … level : 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。 appenderName:就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。 例如:log4j.rootLogger=info,A1,B2,C3 配置了3个输出地方我们可以设置让A1在控制台输出;B2生产日志文件;C3让日志信息插入数据库中。 本例中是将所有的日志信息在控制台打印出来。 log4j.logger.org.springframework.web.servlet=INFO,db //设置将spring下包的某些类的日志信息写入数据库中,并且在控制台上打印出来。(是通过log4j.rootLogger=INFO,stdout来体现的)db是将日志信息写入数据库中 log4j.logger.org.springframework.beans.factory.xml=INFO //本实例中为了让某些包下的日志信息能写入数据库 log4j.logger.com.neam.stum.user=INFO,db //设置自己某个模块下的日志信息既在控制台上打印而且往数据库中保存 //下面是配置在控制台上打印日志信息,在这里就不再仔细描述了 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] - - <%m>%n //下面是配置将日志信息写入文件中,在这里也就不再仔细描述了 log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/exppower.log log4j.appender.logfile.DatePattern=.yyyy-MM-dd log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] wang- <%m>%n /#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/# /# JDBC Appender /#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/#/# /#log4j.appender.db=com.neam.commons.MyJDBCAppender //下面是配置将日志信息插入数据库, log4j.appender.db=org.apache.log4j.jdbc.JDBCAppender //配置输出目标为数据库(假如要将日志在控制台输出,配置为log4j.appender. stdout =org.apache.log4j.ConsoleAppender;将日志写入文件,配置为log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender 这样的配置在许多地方都要有,需要可查有关资料),当然你也可以自己扩展org.apache.log4j.jdbc.JDBCAppender这个类,只需要在这里配置就可以了例如我们配置我自己扩展的MyJDBCAppender,配置为/#log4j.appender.db=com.neam.commons.MyJDBCAppender log4j.appender.db.BufferSize=10 //设置缓存大小,就是当有10条日志信息是才忘数据库插一次 log4j.appender.db.driver=net.sourceforge.jtds.jdbc.Driver //设置要将日志插入到数据库的驱动
log4j.appender.db.URL=jdbc:jtds:SqlServer://localhost:1433;DatabaseName=pubs log4j.appender.db.user=sa log4j.appender.db.password=sa log4j.appender.db.sql=insert into WDZLOG (LogName,UserName,Class,Mothod,createTime,LogLevel,MSG) values ('%X{userId}','%X{userName}','%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%m') //设置要插入日志信息的格式和内容,%X{userId}是置取MDC中的key值,因为我们在过滤器中是将用户id和用户姓名放入MDC中,所有在这里可以用%X{userId}和%X{userName}取出用户的ID和用户姓名;'%C'表示日志信息是来自于那个类;%M表示日志信息来自于那个方法中;%d{yyyy-MM-dd HH:mm:ss}表示日志信息产生的时间,{yyyy-MM-dd HH:mm:ss}表示一种时间格式,你也可以直接写成%d;%p表示日志信息的级别(debug info warn error); %m表示你写入的日志信息 log4j.appender.db.layout=org.apache.log4j.PatternLayout

发表于 @ 2009年02月22日 01:05:00 | 评论( 5 )| 编辑| 举报| 收藏

旧一篇:正则表达式入门 | 新一篇:Hibernate的两种事务管理jdbc 和jta方式

-

查看最新精华文章 请访问博客首页相关文章 SQL计算表达式用SQL向/*.txt中追加文本儲存過程萬能分頁利用SQL移动硬盘文件改变SQLServer 数据库所有对象的所有者成dbolog4j把日志写入数据库详解

wofile 发表于Wed Sep 30 2009 12:13:26 GMT+0800 (China Standard Time) IP:举报回复删除tai hao le .... xie xie a ~~~luchangbin_66 发表于Thu Nov 19 2009 10:53:29 GMT+0800 (China Standard Time) IP:举报回复删除Filter在web.xml中过滤那些。。。。。liang_gdong 发表于Mon Nov 30 2009 16:06:18 GMT+0800 (China Standard Time) IP:举报回复删除好东西,支持mwj0103 发表于Wed Jan 06 2010 13:24:41 GMT+0800 (China Standard Time) IP:举报回复删除太让人感动了!~iceyrain 发表于Tue Jan 12 2010 10:22:37 GMT+0800 (China Standard Time) IP:举报回复删除很牛, 受教了 谢谢

专区推荐内容

热门招聘职位 【更多

log4j.properties参数

Posted on

log4j.properties参数 - 蓝色贝壳 - ITeye技术网站

首页 新闻 论坛 问答 博客 招聘 更多 ▼

群组 搜索

您还未登录 ! 我的应用 登录 注册

蓝色贝壳

永久域名 http://ff861.iteye.com

java中判断字符串是否为数字的方法 | 根据wsdl地址或文件生成webservice客户端

2009-09-01

log4j.properties参数

Java代码 收藏代码

  1. log4j.rootLogger=DEBUG,CONSOLE,DATABASE,FILE
  2. log4j.addivity.org.apache=true
  3. /# 应用于控制台
  4. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
  5. log4j.appender.CONSOLE.Threshold=INFO
  6. log4j.appender.CONSOLE.Target=System.out
  7. log4j.appender.CONSOLE.Encoding=GBK
  8. log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
  9. log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
  10. /# 用于数据库
  11. /#log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
  12. /#log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/ww
  13. /#log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
  14. /#log4j.appender.DATABASE.user=root
  15. /#log4j.appender.DATABASE.password=123
  16. /#log4j.appender.CONSOLE.Threshold=WARN
  17. /#log4j.appender.DATABASE.sql=INSERT INTO LOG4J(stamp,thread, infolevel,class,messages) VALUES ('%d{yyyy-MM-dd HH:mm:ss}', '%t', '%p', '%l', '%m')
  18. /# INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
  19. /# 写入数据库中的表LOG4J的Message字段中,内容%d(日期)%c: 日志信息所在地(类名)%p: 日志信息级别%m: 产生的日志具体信息 %n: 输出日志信息换行
  20. /#log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
  21. /#log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
  22. /# 每天新建日志
  23. log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
  24. log4j.appender.A1.File=C:/log4j/log
  25. log4j.appender.A1.Encoding=GBK
  26. log4j.appender.A1.Threshold=DEBUG
  27. log4j.appender.A1.DatePattern='.'yyyy-MM-dd
  28. log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  29. log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n
  30. /#应用于文件
  31. log4j.appender.FILE=org.apache.log4j.FileAppender
  32. log4j.appender.FILE.File=C:/log4j/file.log
  33. log4j.appender.FILE.Append=false
  34. log4j.appender.FILE.Encoding=GBK
  35. log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
  36. log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
  37. /# 应用于文件回滚
  38. log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
  39. log4j.appender.ROLLING_FILE.Threshold=ERROR
  40. log4j.appender.ROLLING_FILE.File=rolling.log
  41. log4j.appender.ROLLING_FILE.Append=true
  42. log4j.appender.CONSOLE_FILE.Encoding=GBK
  43. log4j.appender.ROLLING_FILE.MaxFileSize=10KB
  44. log4j.appender.ROLLING_FILE.MaxBackupIndex=1
  45. log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
  46. log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
  47. /#自定义Appender
  48. log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
  49. log4j.appender.im.host = mail.cybercorlin.net
  50. log4j.appender.im.username = username
  51. log4j.appender.im.password = password
  52. log4j.appender.im.recipient = corlin@cybercorlin.net
  53. log4j.appender.im.layout=org.apache.log4j.PatternLayout
  54. log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
  55. /#应用于socket
  56. log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
  57. log4j.appender.SOCKET.RemoteHost=localhost
  58. log4j.appender.SOCKET.Port=5001
  59. log4j.appender.SOCKET.LocationInfo=true
  60. /# Set up for Log Facter 5
  61. log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
  62. log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n
  63. /# Log Factor 5 Appender
  64. log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
  65. log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
  66. /# 发送日志给邮件
  67. log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
  68. log4j.appender.MAIL.Threshold=FATAL
  69. log4j.appender.MAIL.BufferSize=10
  70. log4j.appender.MAIL.From=web@www.wuset.com
  71. log4j.appender.MAIL.SMTPHost=www.wusetu.com
  72. log4j.appender.MAIL.Subject=Log4J Message
  73. log4j.appender.MAIL.To=web@www.wusetu.com
  74. log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
  75. log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
    log4j.rootLogger=DEBUG,CONSOLE,DATABASE,FILE log4j.addivity.org.apache=true /# 应用于控制台 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.Threshold=INFO log4j.appender.CONSOLE.Target=System.out log4j.appender.CONSOLE.Encoding=GBK log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n /# 用于数据库 /#log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender /#log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/ww /#log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver /#log4j.appender.DATABASE.user=root /#log4j.appender.DATABASE.password=123 /#log4j.appender.CONSOLE.Threshold=WARN /#log4j.appender.DATABASE.sql=INSERT INTO LOG4J(stamp,thread, infolevel,class,messages) VALUES ('%d{yyyy-MM-dd HH:mm:ss}', '%t', '%p', '%l', '%m') /# INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n') /# 写入数据库中的表LOG4J的Message字段中,内容%d(日期)%c: 日志信息所在地(类名)%p: 日志信息级别%m: 产生的日志具体信息 %n: 输出日志信息换行 /#log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout /#log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n /# 每天新建日志 log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender log4j.appender.A1.File=C:/log4j/log log4j.appender.A1.Encoding=GBK log4j.appender.A1.Threshold=DEBUG log4j.appender.A1.DatePattern='.'yyyy-MM-dd log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n /#应用于文件 log4j.appender.FILE=org.apache.log4j.FileAppender log4j.appender.FILE.File=C:/log4j/file.log log4j.appender.FILE.Append=false log4j.appender.FILE.Encoding=GBK log4j.appender.FILE.layout=org.apache.log4j.PatternLayout log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n /# 应用于文件回滚 log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender log4j.appender.ROLLING_FILE.Threshold=ERROR log4j.appender.ROLLING_FILE.File=rolling.log log4j.appender.ROLLING_FILE.Append=true log4j.appender.CONSOLE_FILE.Encoding=GBK log4j.appender.ROLLING_FILE.MaxFileSize=10KB log4j.appender.ROLLING_FILE.MaxBackupIndex=1 log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n /#自定义Appender log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender log4j.appender.im.host = mail.cybercorlin.net log4j.appender.im.username = username log4j.appender.im.password = password log4j.appender.im.recipient = corlin@cybercorlin.net log4j.appender.im.layout=org.apache.log4j.PatternLayout log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n /#应用于socket log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender log4j.appender.SOCKET.RemoteHost=localhost log4j.appender.SOCKET.Port=5001 log4j.appender.SOCKET.LocationInfo=true /# Set up for Log Facter 5 log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n /# Log Factor 5 Appender log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000 /# 发送日志给邮件 log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender log4j.appender.MAIL.Threshold=FATAL log4j.appender.MAIL.BufferSize=10 log4j.appender.MAIL.From=web@www.wuset.com log4j.appender.MAIL.SMTPHost=www.wusetu.com log4j.appender.MAIL.Subject=Log4J Message log4j.appender.MAIL.To=web@www.wusetu.com log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

java中判断字符串是否为数字的方法 | 根据wsdl地址或文件生成webservice客户端

评论

发表评论

表情图标

字体颜色: 标准深红红色橙色棕色黄色绿色橄榄青色蓝色深蓝靛蓝紫色灰色白色黑色 字体大小: 标准1 (xx-small)2 (x-small)3 (small)4 (medium)5 (large)6 (x-large)7 (xx-large) 对齐: 标准居左居中居右

提示:选择您需要装饰的文字, 按上列按钮即可添加上相应的标签

您还没有登录,请登录后发表评论(快捷键 Alt+S / Ctrl+Enter)

ff861的博客

ff861

搜索本博客

最近访客 >>更多访客

yahon的博客

yahon

spike2012的博客

spike2012 kirasun的博客

kirasun

q_wong的博客

q_wong

博客分类

其他分类

存档

  • 2010-05 (1)
  • 2010-04 (5)
  • 2010-02 (1)
  • 更多存档...

    评论排行榜

  • Rss

  • Rss_google 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者。 © 2003-2011 ITeye.com. All rights reserved. [ 京ICP证110151号 ]

Groovy创始人:Java面临终结 Scala将取而代之

Posted on

Groovy创始人:Java面临终结 Scala将取而代之

Groovy创始人James Strachan前日在其博客(地址在Blogspot,未架好梯子前请勿随便点击)上发表了一篇文章,题目为《Scala as the long term replacement for java/javac? 》。以下是正文部分的翻译:

不要误解我的意思——我在过去的这十来年里写了无数的Java代码,并且坚信它相对C++和Smalltalk来说是一个巨大的进步(当然,很多其它语言也很有帮助,像JavaScript,Ruby,Groovy,Python等)。但是我还是一直期待着能有javac的替代者出现。我甚至还自创了一门语言(编者注:此处指Groovy)好让我暂时满足一下这种期望。

Java是一种令人惊叹的复杂语言(它的语法规范长达600页,我怀疑到底有没有人能真正理解它),它有自动装箱(Autoboxing),空指针异常(NPE)往往就是这时抛出的。其中的基本类型(primitive type),字符串/文字/缓冲器/集合类(collections)以及数组缺乏多态性,以至于处理任何数据结构都需要冗长的语法;而且,由于Bean属性和对闭包支持的缺失(甚至在JDK 7里也仍然还不支持),这会让你的代码里充满了 try/catch/finally 这些语句(除非你使用框架和新的自定义API)。除了这些还有好多数不清的麻烦问题。Java倒是有类型推断(type inference)功能但却不用,使得我们要多输/读如此大量的代码。

这个问题在没有Java7后变得更加紧迫 (在Snorcle之后它变得更加重要:我不知道javac是不是要被jdkc 取而代之了?)。所以我猜javac可能已经走到了尽头,它看起来根本就没有什么进展或简化了。

那么,从长久来看,谁能取代javac 呢?当然,像Ruby,Groovy,Python,还有JavaScript这些动态语言在过去几年里很受欢迎——很多人喜欢他们。

我认为将来可能替代javac的就是Scala 。它实在太让我印象深刻了。我甚至可以诚实地说,如果有人在2003年把Martin Odersky,Lex Spoon以及Bill Venners写的那本《Programming in Scala》拿给我看了的话,那我根本就不会再去发明Groovy了。

那么,为什么我会看好Scala呢?Scala是静态类型的,它可以被编译成与Java同样快速的字节码,所以它的速度与Java不分上下(有时快一点,有时慢一点)。你可以看看 Scala 在与 groovy 或jruby一起进行测试时表现有多好。注意:速度并不是我们追求的唯一目标——有时候我们可能宁肯让代码慢上十倍,也要写得简洁一点;但是如果要取代javac,速度当然还是很重要的。

Scala已有类型推理(type inference)功能,因此它和Ruby/Groovy一样简洁,但是它完全是静态类型的。这是很有好处的,它使得理解代码、阅读代码以及编写文档都简单多了。在任何片段(token)/方法/符号上点击,你都可以跳转到相应的代码或文档中去浏览。不需要打那些怪异的补丁,也不用操心谁什么时候新增了一个方法——这对于那些需要一个团队一起长期开发的大项目是很有好处的。Scala似乎已经实现了动态语言(dynamic language)的那种简洁,而实际上它是完全静态类型的。所以,我根本不需要去记哪些魔术方法可用——或是在shell里运行脚本来查看这些对象——IDE/编译器在你编辑代码时就已经知道这些了。

Scala已经提供了对高阶函数和闭包的支持,另外还支持序列解析(sequence comprehensions) ,这样你就可以很容易用Scala写出漂亮简洁的代码。Scala还把函数式和面向对象的编程思想很好地统一到了一种语言里,它比Java要明显简单一些(虽然它的类型体系(type system)和泛型(generics)需要花费差不同一个数量级的时间去理解,但是,它通常是框架开发者才需要考虑的问题,应用程序开发人员并不需要涉及)。它也使得从传统的面向对象/Java编程模式向函数式编程的转变变得更加容易——这对于编写并行或异步程序的开发人员尤其意义重大(这是因为现在芯片的主频已经达到了数个GHz,很难再有提升了;而芯片集成的核心数则在快速增长。51CTO之前曾发布过哪种语言将统治多核时代 再看函数式语言特性一文,对于函数式语言在多核时代的潜力做了相当深入的分析)。你可以在最开始用面向对象的方法编程,然后当你需要它的好处时,就可以迁移到用不变状态(immutable state)函数式编程正变得越来越重要,因为我们总是希望能把问题变简单,并且在一个更高的层次上解决它(如闭包,高阶函数,模式匹配,单子(monad)等),同时我们还需要通过不变状态(immutable state)实现并发和异步。

Scala也有适当的混入(mixin)(特性(trait)) ,所以你不必去摆弄面向对象编程的缺陷来获得模块化的代码。如果你确实需要一些鸭子类型(duck typing),Scala甚至能为你提供构造类型(structural type)。

最让我印象深刻的一点就是它的核心语法极其精练简洁(它的语法手册只有大概Java的四分之一),但是其方式却更加强大和灵活,而且非常容易通过库来扩展,添加新的语义和功能。可以看看这个例子:Scala Actors。因此它非常适合用于创建嵌入式DSL或外部DSL 。有了它以后就真没必要再用Java,XPath ,XSLT,XQuery,JSP,JSTL,EL和SQL这些东西了——你可以在各种各样的场合使用DSL。

Scala确实需要花点时间去习惯——我承认第一次我看Scala时并不觉得顺眼——用了Java之后你就会习惯用一堆冗长的代码来做一点点事,刚开始时我们也都不会一看到几个符号就觉得有多惊讶。(我花了好长一段时间才习惯Scala里用_作“通配符”,因为在Scala里是用作标识符/方法)。

如果你一直在写Java,那么最开始确实会觉得Scala很不一样(如在声明方法/变量/参数时在类型或标识符上加上阶,虽然那样做的原因是为了能更方便地略去一多余的类型信息)。

例如,在Java中的写法:

List< String> list = new ArrayList< String>()

在Scala中的写法:

val list = new List[String]

或者,如果你要指定确切的类型的话:

val list : List[String] = new List[String]

但是如果你坚持用上一段时间,Scala优美的一在很快就显现出来。它对Java里的许多地方进行了简化,让你可以用非常简洁的代码就描述出意图,而不用花上大段代码去实现细节——同时还为你提供了一条迁移到函数式编程的不错途径,这对于编写并发和分布式程序是非常有利的。

我强烈建议你学习一下Scala:以开放的心态看看(当你的思维转过来后)你是否能发现它的美丽之处。

一些Scala资料的链接和在线演示文档

我强烈推荐由 Martin Odersky,Lex Spoon 和 Bill Venners编写的《Programming in Scala》 一书。它非常好地介绍了Scala的特点以及设计时的选择。这本书相当厚,但是你可以先跳着读,必要时再深入细节。

O'Reilly Scala book》这本书我只跳着读了一点,但是看起来也非常不错。

如果你想在短时间内就知道个大概语法,那么可以看看《Tour of Scala》。不过看了之后你也还得花上一些时间来真正理解为什么它跟Java会有这样那样的不同。

Martin Odersky 的JavaOne 2008上关于Scala的演说

Jonas BonérReal-World Scala上作的报告

Gert's的关于他如何创建 Apache Camel DSL for Scala 的介绍

用于JDBC类型安全查询的一个Scala版LINQ,顺便再了解下DBC

一份非常不错的报告,介绍了把Scala 和OSGi与DSL结合使用

如何使用Scala和XML ( 语言里已经自带了处理XML,XPath , XSLT, XQuery的简洁语法)

Scala的例子

Scala快速参考表

这个例子显示了如何创建的bean风格的属性(或C #风格的getter函数)

创建一个用Lift实现的聊天演示程序或查看Lift网站上的更详细介绍

如果你还有一些空余时间的话,这些视频资料也非常不错

Bill Venners所发表的The Feel of Scala

Lex Spoon所作的Scala: 把未来的语言带到JVM里来

好用的Scala框架和库

liftweb :Scala的rails

语言规范ScalaTest for BDD以及其它一些入门测试(literate testing)能让你体会到类型安全的DSL对于编写IDE友好 的简洁代码有多大帮助。

scalaz 是一个很有用的例程库。

HTTP /JSON服务进行调度

另外,顺便说一下,对于那些像我一样一喜欢JAXRS的,现在可以通过jersey-lift模块使用lift模板和Jersey了。

作为这的实例,你可以看看RestMQ,这是一个我最近也参与了的开源项目,它旨在为面向消息的中间件提供REST风格的API和Web控制台,它也是基于JAXRS(Jersey),Scala,Lift构建的。

至于开发工具方面,有Ant/Maven插件,它带有一个交互式Scala控制台(REPL)和一个用于IDEA的IDE插件,还有Eclipse,NetBeans,以及TextMate,Emacs这些通用编辑器,都可以供你选择。在IDE插件的丰富程度上与Java还是有差距的,但是这些工具所提供的代码导航和自动补全功能还是很有用的。

我试用过NetBeans,Eclipse和IDEA这几个IDE上的插件,它们都各有优劣。看起来,Scala的追随者也因为这些工具分裂成了几派。如果要代码导航和自动补全,那我发现IDEA非常不错。当你打开一个Maven pom.xml,它好像就能非常好地自动解析代码,找出Scala源,那样你就能很方便地在任意的类型/方法以及它们对应的文档/源代码中跳转浏览。(通常你必须在运行/调试任务里手动添加Scala)。不过IDEA在错误代码高亮上并不是最好的。在作上一些弥补后,它们都能变得与对应的Java工具一样好用。试试这几个工具吧,找出你最习惯的那个。

Scala Nit

任何一种语言都有你喜欢的一面,也有你不是那么热衷的一面。Scala给你的最初印象可能确实是符号太多了点,但是你并不需要使用所有的这些符号——如果你喜欢的话,你可以继续沿用很多Java里的东西。但我想到了那个时候最好还是用符号来实现“特殊任务”以避免标识符冲突。

我对嵌套的引入声明不太感冒,使用root.java.util..List来把一个”全局“引入和相对引入区别开来。我还更愿意使用子引入。例如,如果你引入了com.acme.cheese.model.Foo,然后,为了引入model.impl.FooImpl,我就更喜欢用一个明确的相对前缀,就像:import _.impl.FooImpl。这对简化任务有一些好处,对于保持和Scala的简洁性就更有帮助了。

然而,和Java里大把的毛病相比,再考虑到Scala的优美,简洁和强大,Scala的这一些负面因素和根本不算什么了。

结语:

既然 MrJava(Adam Bien),MrJRuby(Charles Nutter) 和 MrGroovy(作者本人) 都认为Scala将会是javac的的替代者,那肯定是有些原因的。那你还在等什么呢?赶快去买《Programming in Scala》 或 《O'Reilly Scala book》一探究竟吧!

这篇博文发布后,立刻有很多Scala,Groovy和Java开发者进行了回复。Scala的创始人Martin Odersky也对这篇文章发表了自己的赞赏之词。以下是Martin的留言:

James,感谢你的认可!这对我来说意义重大。我相信,如果我们一起努力向Java开发者们展示现在在JVM上更加美好的语言选择,我们大家都会因此而得到好处。感谢你在这方面带了个好头。

根据我对Groovy的了解(很可惜的,我的了解没有你了解Scala那样多),它看起来并非是意图填补同一块领域的。Groovy的吸引力在于它是一个语法接近Java的动态脚本语言。Scala的吸引力在于它是一个强类型的,静态的,结合函数式和面向对象的语言。

此外还有很多精彩的评论,51CTO译者对这些评论进行了一些筛选,挑出部分翻译如下:

Scala的体验

去年,我在做一些调查项目时把Scala引进到了我的小Java车间里。

如今Scala成为了我们最主要的编程语言。

通过使用Scala,我们现在可以构建类型系统(type system),跟踪总结以前所做项目的经验教训,并用它来替代我们过去以模型为导向(model-driven)的开发方式。然后,我们利用函数分发(pass around functions)的特性来改进组件的参数化。

总之,对于建立可重用的组件,Scala提供了一套比Java更好的机制。

C/#和Java?

我觉得你可以去看看C/#。它解决了你在Java中遇到的许多问题。如果你不喜欢微软的话,就可以试试.NET的开源替代版本Mono。

有关Scala和F/#

其实,在.NET平台里与Scala对应的语言并不是C/#,而是F/#。不管什么时候,我都更倾向于使用Scala,而不是F/#,原因如下:

1 )在F/#文化里,面向对象看起来并不重要。在所有讲F/#的书里,都必定有一章介绍类,然后,剩余部分就是专门讲解函数式。相比之下,Odersky在发明Scala时,并没有照搬Java的这一套机制,而是通过对象类型、特性(trait)、增强的可见性规则(visibility rule)等概念扩展并超过了Java的这一套机制。Scala使得像我这样有根深蒂固面向对象思想的开发人员觉得很舒适,它提供的函数式语法特性让我可以用来把代码变得非常简洁。

2 )F/#比Scala看起来更接近人类语言,初看起来这似乎是好事。不幸的是,由于开发者很少需要写类型说明(type annotation),大部分代码里也都没写,这就使得代码变得更加难于理解。在Scala里,至少要声明参数类型,而且最好也声明一个方法的返回类型,除了那些一目了然的情况。

3 )F/#一直力求尽量往OCAML的语法靠拢,所以它在语法也真是没有什么创新之处。而Scala则是博取众长,吸纳了各种语言的优点。此外,它还让人感觉有些机制并不是必须的,而是为了让开发者更好地表达意图而加入的。通过加入隐式转换(implicit conversion),析取器(extractor)这些功能,Martin从我这里得到了很大的帮助。

4 )在我看来,Java程序员学会Scala比从C/#到F/#的过渡要容易得多。大体上来说,原因是Java程序员不需要花很大的代价入门,Scala可以直接被当作一门少了些模板(boilerplate)的Java使用。当程序员渐渐熟练后,他就可以开始发掘函数式编程的威力了。在其它任何的面向对象/函数式编程语言里我都找不出可以这样过渡学习的。

Groovy盖棺定论了?

James,我一直在留意你的博客,这篇文章写得棒极了,堪称高超。你发过一份声明说不会再继续把Groovy开发得更强大了(51CTO编者注:James Strachan在写这篇博文之前很久已经离开了Groovy开发团队),这份声明影响力很大,而且几乎可以说是给Groovy盖棺定论了。

我们有一个面向最终用户的数据处理软件,然后我们选择的是Groovy (而没用Jython和JRuby )来作为实现各种功能扩展(从对变量编写公式到编写脚本)的途径。你们在开发Groovy所写的代码很多都是粘合代码(glue code)(对核心语言起补充作用)。我们充分利用Groovy所支持的这些特性与MS Office产品和Web服务进行整合。我真的希望,如果你们的开发团队更中意Scala的话,也请尽量让我们到时候在Scala里也能用上这些有用的库。

James Strachan对上文的回复

我不认为任何一种主要的JVM语言会消失,肯定会一直有一大帮人继续维护Groovy, Jruby, Cojure, Jython, Rhino等。

JVM中最大的一点好处就是这些语言很容易共存,重用另一种语言的代码也非常容易。因此,只要相信大众的选择,就不用担心会选错开发语言。

而且我也并不认为Scala会是Ruby/Groovy/Fan这些动态语言的替代者;大多数情况下性能还是很重要的。对于一个快速、静态类型的编译器来说,过去Java显然是第一选择——但是现在,Scala才是首选——这是因为Java已经显出老态了。(它可能永远也不会支持闭包,永远也不会考虑支持类型推断等新特性)。

自从发现了类型推断的威力之后,我实际上越来越觉得动态类型(就是很简洁的代码实现功能)的动机变得越来越难以琢磨了。比如说,你可以用Scala写一些脚本,它就会像Ruby/Groovy一样进入”读取-执行-打印 循环“(Read-Evaluate-Print Loop, REPL)。

但是我发这篇文章的目的并不是要挑起Scala拥护者和Ruby/Grovy/Clojure/JavaScript这些动态语言支持者之间的战争——我只是想让被Java一叶障目的开发者们意识到,这个世上已经有了比Java更好的静态类型语言:这门语言有他们所想要的全部功能(还附带有Java最需要增强的功能)。所有这一切,都能在这门语言里用简洁、优美的代码表示出来(尽管这门语言和Java确定有些不太一样,并且需要你经历一个学习曲线)。

附录:有关Scala编程语言的其他言论

Java的不足可以比作大量的毛疣,那么同样在Scala中,这些地方正是表现了Scala的美、简化和强大。——James Strachan

在一个社区(java.net booth)举办的和James Gosling对话会议上,一个与会者问了一个非常有意思的问题:“除了Java,现在你会把哪种语言运行于JVM之上?”。答案是惊人地快速简洁:Scala。——Java之父James Gosling

我必须说Scala看起来是是现在Java王座的继承人。其他在JVM的语言看起来不可能有Scala那样的能力来取代Java,Scala背后的推动力是无可置疑的。Scala还不是一个动态语言,但是它有许多流行动态语言的特性,例如它的灵活富类型系统,稀疏和简洁的语法,函数式语言和面向对象范式的完美结合。Scala的缺点:“太复杂”或者“太丰富”,但这些可以通过编码规范很好避免,从而构建更健壮的编辑器和工具,以及指导多语言开发者明白如何更好地使用Scala。Scala是JVM上静态语言的重生,它也像JRuby那样延伸平台的性能,这些都是Java做不到的。——JRuby核心开发者Charles Nutter

【CSDN小百科】

James Strachan

James Strachan,Groovy创始人,是Apache ActiveMQ、Apache Camel、Apache ServiceMix等开源项目创始人之一。现工作于FuseSource。

原文链接:http://developer.51cto.com/art/200907/134785.htm

发表评论 29条 】

相关文章 敏捷宣言创始人:十年之后看“修炼” JavaEye创始人:为什么要用非关系数据库? Go语言创始人对Java、C++的复杂性不满 Groovy 1.7.3发布 值得关注的新功能 IDC:Oracle面临Java管理挑战 Groovy框架 Grails 1.2 发布 网友评论(共29条评论).. Groovy创始人:Java面临终结 Scala将取而代之

  • deping_chen 2013-05-11 10:32:28

这么多大牛推荐,必有可取之处啊。

回复(0) 支持(0) 反对(1) 举报(0) | 0条回复..

  • kuailelxl 2010-08-12 19:16:33

我的第一反应是,把.NET当空气了。 看了前面几段,基本上看不懂啥意思,也许他说的非常专业的技术名词,但是在商业领域上,目前JAVA除了速度慢点外没发现其他大缺点,尤其是在可读性上,简化了功能的java在可读性上要比C/C++以及C/#强大许多。

回复(8) 支持(1) 反对(2) 举报(0) | 8条回复..

  • FrankHB1989 2010-11-08 22:35:03

批量培养民工的成本减低了,似乎是优点,但也有可能是缺点……

回复(2) 支持(1) 反对(0) 举报(0)

  • luoxiafei 2010-11-23 12:53:47 引用内容FrankHB1989 2010-11-08 22:35:03批量培养民工的成本减低了,似乎是优点,但也有可能是缺点……..

你还别看不起民工,谁不是从代码民工来的?难道你脑子天生威武牛逼的一塌糊涂,生来就能为卫星写代码。做人做事能别带色不?

回复(1) 支持(1) 反对(2) 举报(0)

  • FrankHB1989 2010-11-24 20:13:22 引用内容luoxiafei 2010-11-23 12:53:47你还别看不起民工,谁不是从代码民工来的?难道你脑子天生威武牛逼的一塌糊涂,生来就能为卫星写代码。做人做事能别带色不?..

不要把初学者和代码民工混为一谈。

回复(0) 支持(3) 反对(0) 举报(0)

  • dda_dda_dda 2010-12-29 14:18:08 引用内容FrankHB1989 2010-11-08 22:35:03批量培养民工的成本减低了,似乎是优点,但也有可能是缺点……..

编程语言只不过是一种表达方式,和你用户普通话,英语说话没有什么区别。会写程序即不说明你聪明,也不会说明你笨。重要的是你是否能够用程序实现你的想法,能够做出什么的作品。马云不会写程序,但是可以弄一个淘宝,很多学习了大量语言的人,可能连一个最简单的作品都没有。

回复(1) 支持(0) 反对(1) 举报(0)

  • FrankHB1989 2010-12-31 16:51:50 引用内容dda_dda_dda 2010-12-29 14:18:08编程语言只不过是一种表达方式,和你用户普通话,英语说话没有什么区别。会写程序即不说明你聪明,也不会说明你笨。重要的是你是..

学习语言仅仅就只是学习使用语言么?于是会说普通话就让中文系的全喝西北风? 学习语言从来都不是学习语言本身。对于自然语言,文化背景是重要组成部分,因为在某些情况下可能极大地影响语义。对于程序设计语言,语言的设计、实现、历史背景都是重要且复杂的知识(当然对你而言有用没用另当别论),不会因为你无视而不存在。 认识到语言是工具,不应被工具束缚而阻碍你需要利用工具解决的问题——你了解了一个常识;认为语言只是工具——你无视了另一个常识。

回复(2) 支持(1) 反对(0) 举报(0)

  • sytu_hzj 2011-01-01 18:28:49

可读性比C/#强?你傻B了吧,我用了三年C/#,一年Java,没发现Java什么地方可读性比C/#强

回复(0) 支持(3) 反对(4) 举报(0)

  • kevin_zhang1983 2012-08-17 16:43:10 引用内容FrankHB1989 2010-12-31 16:51:50学习语言仅仅就只是学习使用语言么?于是会说普通话就让中文系的全喝西北风? 学习语言从来都不是学习语言本身。对于..

部分同意ls观点,语言就是个工具,用来赚钱即可,对于自己钻研的语言也别装高端了, 各种语言就是谋生手段, 大家都是混饭吃。 不用扯那些忽悠外行的人的东西,还什么文化背景,想吐的心都有了。

回复(0) 支持(0) 反对(0) 举报(0)

  • z742698 2012-11-13 17:12:24 引用内容FrankHB1989 2010-12-31 16:51:50学习语言仅仅就只是学习使用语言么?于是会说普通话就让中文系的全喝西北风? 学习语言从来都不是学习语言本身。对于..

初学者和民工。中文系的人也是从会说普通话开始的。 这家伙搞C++的,自以为脱离民工阶层,属于高端应用领域。其实眼界不过还局限在自己的语言中了。需求和发展都看不到的给人打工的可怜虫罢了。

回复(0) 支持(0) 反对(0) 举报(0)

  • xiazaihaoma123 2011-03-14 14:27:58

那些什么代码优美性能优越对你没作用,最重要的能让你拿上更高的工资,或者让你技术更上一个层次。至于别的不多说。

回复(0) 支持(1) 反对(0) 举报(0) | 0条回复..

  • xiazaihaoma123 2011-03-14 14:26:14

工作用java, 非得把C搞熟练 ,这什么新语言一天出一个,妈的谁沙比才跟风 除非真的你有眼光,这语言马上会火能让你拿高薪,那就去学吧。不然你是浪费时间打酱油,个人意见别扔砖头。

回复(0) 支持(1) 反对(0) 举报(0) | 0条回复..

  • marqio 2010-08-12 16:29:45

相信有98%的遗留系统(java开发的)需要升级呢,他们才不愿去用新的语言开发新的系统,宁愿少花点钱去升级维护,重要的适用,没有新的高级需求是不会考虑的。语言的发展也是需要客户的认可的,你用新语言开发的系统再好,客户就是不愿意使用有屁用。

回复(3) 支持(5) 反对(3) 举报(0) | 3条回复..

  • lixkyx 2010-10-31 21:33:40

Scala的好处是它可以与Java无缝衔接,遗留系统你可以不必管它,在新增或者修改部分用上Scala就好了。

回复(1) 支持(0) 反对(0) 举报(0)

  • lifeofxiaoxin 2010-11-23 18:21:41 引用内容lixkyx 2010-10-31 21:33:40Scala的好处是它可以与Java无缝衔接,遗留系统你可以不必管它,在新增或者修改部分用上Scala就好了。..

真的?

回复(1) 支持(0) 反对(0) 举报(0)

  • lixkyx 2011-01-22 11:05:11 引用内容lifeofxiaoxin 2010-11-23 18:21:41真的?..

不敢100%保证无缝衔接,但是绝大多数情况下是没有问题的。Scala本来就是工作在JVM上的,增加的Scala部分与原有的Java部分不冲突。而且,Scala专门内置了与Java的互操作部分。

回复(0) 支持(0) 反对(0) 举报(0)

  • vargs 2011-01-12 15:09:31

java刚上路这无议于晴天霹雳...

回复(0) 支持(0) 反对(0) 举报(0) | 0条回复..

  • ajjpool 2010-12-09 12:49:57

晕,保护自己

回复(0) 支持(0) 反对(0) 举报(0) | 0条回复..

  • hansonjan 2010-09-02 10:19:30

看了此文,才真知道是天外有天.呵呵! 其实,本人在用java的时候也对那一堆堆的try{}catch(Exception ex){}感到无语. 看到有这么好的语言出来.需要时再好好学习一下.呵呵!

回复(1) 支持(0) 反对(0) 举报(0) | 1条回复..

  • lifeofxiaoxin 2010-11-23 18:22:24

一直抛出就行了.管它什么.我都是这么干的.哈哈.

回复(0) 支持(1) 反对(0) 举报(0)

  • FrankHB1989 2010-11-08 22:33:44

mixin能避免“面向对象编程的缺陷”?这叫“有根深蒂固面向对象思想”? 这家伙不是被“纯OOP”洗脑了就是基础没学好。虽然从语气看起来也许比偏执狂James Gosling要靠谱一些。

回复(1) 支持(1) 反对(0) 举报(0) | 1条回复..

  • lifeofxiaoxin 2010-11-23 18:20:58

我感觉你最不靠谱,你写几篇让我们欣赏下呗.

回复(0) 支持(0) 反对(0) 举报(0)

  • simpleframework 2010-08-13 14:44:21

国内javaweb框架 code.google.com/p/simpleframework/

回复(0) 支持(0) 反对(1) 举报(0) | 0条回复..

  • SunJava2 2010-08-13 10:39:17

如何用Scala访问Oracle数据库?

回复(0) 支持(0) 反对(0) 举报(0) | 0条回复..

  • guojun828 2010-08-12 23:59:47

立刻开始Scala的旅程。。。

回复(0) 支持(0) 反对(0) 举报(0) | 0条回复..

  • chengyingqi0512 2010-08-12 20:48:14

这还得等上一段时间呢

回复(0) 支持(0) 反对(0) 举报(0) | 0条回复..

  • Lee_Dewyze 2010-08-11 21:34:55

编程语言都是相通的 学会了Java学其他面向对象的语言很会很容易上手 我还是认为Java的前景还是很好的

回复(1) 支持(5) 反对(2) 举报(0) | 1条回复..

  • mapeiqi2009 2010-08-12 17:26:01

这是个商业问题,主要是为了维护现有的java代码,要转成另一种语言的话,花费的成本太大了! 而不是什么语言相通的问题....

回复(0) 支持(1) 反对(0) 举报(0)

  • gaolinwu 2010-08-12 00:47:27

支持上面的说法

回复(0) 支持(2) 反对(1) 举报(0) | 0条回复.. 第一页上一页1下一页最末页

Scala Tour

Posted on

Scala Tour

5月1日是劳动的日子,笔者做了一个学习Scala精彩特性的网站Scala-Tour。在学习Scala是时候,遇到很多令人激动的特性,主要函数式编程和并发。相比下Java已经老态龙钟,步履躇跚。或许Scala不会成为替代Java语言,但的确给后来者设立了标杆。所以做了这个网站,顺着一个一个例子,由浅入深,由表及里。逐渐学会Scala,尽管不会因此成为一个熟练Scala的开发者,但是对函数式编程的也会相当了然。这篇文章精选了Scala-Tour上了一些章节,想快速了解的朋友可以看看这篇文章,当然想详细看就上上Scala-Tour吧。

不再需要Close

在Java里面,使用完资源(文件句柄,数据库连接)等之后,必须手动Close。否则发生泄漏后,程序只有被迫重启。Scala可以通过函数式实现自动close。 import scala.reflect.io.File

import java.util.Scanner

def withScanner(f: File, op: Scanner => Unit) = { val scanner = new Scanner(f.bufferedReader)

try {
    op(scanner)

} finally {
    scanner.close()

}

}

withScanner(File("/proc/self/stat"),

scanner => println("pid is " + scanner.next()))

这个例子是从/proc/self/stat文件中读取当前进程的pid。withScanner封装了try-finally块,所以调用者不用再close。

按名称传递参数

我们熟悉的参数传递方式是按值传递。按名称传递的方式,可以理解为直接传递参数名字,等到实际调用的时候,再去取值。在Java代码中,往往充斥着if(log.isDebug()){log.debug(...)}这样语句。之前的if调用是很有必要的,因为在之后的debug语句中往往有字符串拼接的操作。在不需要打Log的时候,字符串拼接也有可能发生异常抛出。而Scala可以通过按名称传递解决这个问题,这样就不再需要if(log.isDebug())这样的语句了。 val logEnable = false

def log(msg: => String) =

if (logEnable) println(msg)

val MSG = "programing is running"

log(MSG + 1 / 0)

鸭子类型

“走起来像鸭子,叫起来像鸭子,就是鸭子。”这个例子中使用{ def close(): Unit }作为参数类型。因此任何含有close()的函数的类都可以作为参数。这样的做法比使用接口要好很多,因为可以不引入任何依赖。这个withClose方法单独编译,随处使用。 def withClose(closeAble: { def close(): Unit }, op: { def close(): Unit } => Unit) {

try {
    op(closeAble)

} finally {
    closeAble.close()

}

}

class Connection {

def close() = println("close Connection")

}

val conn: Connection = new Connection()

withClose(conn, conn => println("do something with Connection"))

Trait

Traits就像是有函数体的Interface,使用with关键字来混入。单个Traits就像是一块乐高积木,一个插件。就像下面的JsonAble,当使用一个对象的时候,可以随时随地把它插在他上面。这个对接就具备了toJson的能力。不用创建一个类,或者写组合的代码,非常干脆。这样也可以使代码有很高的正交性。不再会为了一个很小的需求,去修改一个被广泛使用的类。 trait ForEachAble[A] {

def iterator: java.util.Iterator[A] def foreach(f: A => Unit) = {

val iter = iterator
while (iter.hasNext)

  f(iter.next)

}

}

trait JsonAble { def toJson() =

scala.util.parsing.json.JSONFormat.defaultFormatter(this)

}

val list = new java.util.ArrayListInt with ForEachAble[Int]

list.add(1); list.add(2)

println("For each: "); list.foreach(x => println(x)) //println("Json: " + list.toJson())

函数式真正的威力

通过将函数作为参数,可以使程序极为简洁。 函数式除了能简化代码外,更重要的是他关注的是Input和Output,函数本身没有副作用。 就是Unix pipeline一样,简单的命令可以组合在一起。 List的filter方法接受一个过滤函数,返回一个新的List 如果你喜欢Unix pipeline的方式,你一定也会喜欢函数式编程。 这个例子是用函数式的代码模拟“cat file | grep 'warn' | grep '2013' | wc”的行为。相比于Ruby等动态语言,这威力来自于科学而不是魔法 val file = List("warn 2013 msg", "warn 2012 msg", "error 2013 msg", "warn 2013 msg")

println("cat file | grep 'warn' | grep '2013' | wc : "

+ file.filter(_.contains("warn")).filter(_.contains("2013")).size)

再见 NullException

每个Java程序员都被NullException折磨过。因为Java中每个对象都可能为Null,所以要么到处检查null的问题,要么到处try/cache。 Scala提供了Option机制来解决,代码中不断检查null的问题。这个例子包装了getProperty方法,使其返回一个Option。 这样就可以不再漫无目的地null检查。只要Option类型的值即可。使用pattern match来检查是常见做法。也可以使用getOrElse来提供当为None时的默认值。给力的是Option还可以看作是最大长度为1的List,List的强大功能都可以使用。 不是每个对象都可以为Null了,只有Option可以为None。这样的做法显示区分了可能为Null的情况,可以和NullException说再见了。 def getProperty(name: String): Option[String] = {

val value = System.getProperty(name) if (value != null) Some(value) else None

}

val osName = getProperty("os.name")

osName match { case Some(value) => println(value)

case _ => println("none") }

println(osName.getOrElse("none"))

osName.foreach(print _)

并行集合

这个例子是访问若干URL。但确可以并行访问,比非并行的做法可以快一倍。要想让访问并行,只要调用List.par就可以了。 val urls = List("http://scala-lang.org",

"https://github.com/yankay/scala-tour")

def fromURL(url: String) = scala.io.Source.fromURL(url) .getLines().mkString("\n")

val t = System.currentTimeMillis()

urls.par.map(fromURL(_)) println("time: " + (System.currentTimeMillis - t) + "ms")

是不是非常的简单?并行集合支持大部分集合的功能。不增加程序复杂性,却能大幅提高并发的能力。

远程Actor

Actor是并发模型,也使用于分布式。这个例子创建一个时间服务器,通过alive来监听TCP端口,register来注册自己。调用时通过select创建client。其余使用方式和普通Actor一样。 将单机并发和分布式抽象成一种模型。简化了程序复杂性。虽然多核编程并不广泛,但调用外部接口的情况越来越多。Actor模型非常适用于这样的异步环境。 import scala.actors.remote.RemoteActor._

import scala.actors.Actor._ import scala.actors.remote.Node

val port = 31241

val echoServer = actor {

alive(port) register('echoServer, self)

loop { react {

  case msg => {
    reply("replay " + msg)

  }
}

} }

val timeServerClient = select(Node("127.0.0.1", port), 'echoServer)

timeServerClient !? "hi" match {

case replay: String => println(replay) }

抽取器

抽取器可以进行解构。这个例子是构建一个Email抽取器,只要实现unapply函数就可以了。 Scala的正则表达式会自带抽取器,可以抽取出一个List。List里的元素是匹配()里的表达式。 抽取器很有用,短短的例子里就有两处使用抽取器:

  • 通过 case user :: do main :: Nil 来解构List
  • 通过 case Email(user, domain) 来解构Email。 import scala.util.matching.Regex

object Email {

def unapply(str: String) = new Regex("""(./)@(./)""") .unapplySeq(str).get match {

case user :: domain :: Nil => Some(user, domain)
case _ => None

} }

"user@domain.com" match {

case Email(user, domain) => println(user + "@" + domain) }

DSL

DSL是Scala最强大武器,可以使一些描述性代码变得极为简单。这个例子是使用DSL生成JSON。Scala很多看似是语言级的特性也是用DSL做到的。 自己编写DSL有点复杂,但使用起来非常方便。这样可以使Scala可以嵌入XML,嵌入Json,嵌入SQL。而其他语言中这些都只是字符串而已。 import org.json4s._

import org.json4s.JsonDSL. import org.json4s.jackson.JsonMethods.

import java.util.Date

case class Twitter(id: Long, text: String, publishedAt: Option[java.util.Date])

var twitters = Twitter(1, "hello scala", Some(new Date())) :: Twitter(2, "I like scala tour", None) :: Nil

var json = ("twitters"

-> twitters.map( t => ("id" -> t.id)

  ~ ("text" -> t.text)
  ~ ("published_at" -> t.publishedAt.toString())))

println(pretty(render(json)))

Simple Build Tool

SBT是Scala的最佳编译工具,在他的帮助下,你甚至不需要安装除JRE外的任何东西,来开发Scala。 例如你想在自己的机器上执行Scala-Tour,可以执行下面的命令 /#Linux/Mac(compile & run):

git clone https://github.com/yankay/scala-tour-zh.git cd scala-tour-zh

./sbt/sbt stage ./target/start

/#Windows(can only compile):

git clone https://github.com/yankay/scala-tour-zh.git cd scala-tour-zh

sbt\sbt stage

结语

这几个例子精选自Scala-Tour,这个网站中还有介绍了很多其他好的特性,比如模式匹配和隐式转换,就不逐一介绍了。这个项目Host在GitHub上,如果你也有精彩的用法的话,大家交流交流吧。 Share the post "Scala Tour - 精选"