温馨提示:您的每一次转载,体现了我写此文的意义!!!烦请您在转载时注明出处http://www.blogjava.net/sxyx2008/谢谢合作!!!

雪山飞鹄

温馨提示:您的每一次转载,体现了我写此文的意义!!!烦请您在转载时注明出处http://www.blogjava.net/sxyx2008/谢谢合作!!!

BlogJava 首页 新随笔 联系 聚合 管理
  215 Posts :: 1 Stories :: 674 Comments :: 0 Trackbacks

#

package com.xmlpull;

import java.io.File;
import java.io.FileOutputStream;

import org.kxml2.io.KXmlSerializer;
import org.xmlpull.v1.XmlSerializer;


public class XmlPullCreateXML {
    
    
public static void main(String[] args) throws Exception{
        XmlSerializer xmlSerializer
=new KXmlSerializer();
        xmlSerializer.setOutput(
new FileOutputStream(new File("D:\\workspace\\demo\\src\\students.xml")), "utf-8");
        xmlSerializer.startDocument(
nulltrue);
        xmlSerializer.startTag(
null"data");
        
for (int i = 0; i < 10; i++) {
            xmlSerializer.startTag(
null"student");
            xmlSerializer.attribute(
null"id"""+(i+1));
            
            xmlSerializer.startTag(
null"name");
            xmlSerializer.text(
"student"+i);
            xmlSerializer.endTag(
null"name");
            
            xmlSerializer.startTag(
null"age");
            xmlSerializer.text((i
+10)+"");
            xmlSerializer.endTag(
null"age");
            
            
            xmlSerializer.startTag(
null"sex");
            
if(i%2==0){
                xmlSerializer.text(
"");
            }
else{
                xmlSerializer.text(
"");
            }
            xmlSerializer.endTag(
null"sex");
            
            
            xmlSerializer.startTag(
null"address");
            xmlSerializer.text(
"陕西西安");
            xmlSerializer.endTag(
null"address");
            
            xmlSerializer.endTag(
null"student");
        }
        
        xmlSerializer.endTag(
null"data");
        
        xmlSerializer.endDocument();
        
        xmlSerializer.flush();
        
    }

}
运行后生成的xml文件:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<data>
    
<student id="1">
        
<name>student0</name>
        
<age>10</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="2">
        
<name>student1</name>
        
<age>11</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="3">
        
<name>student2</name>
        
<age>12</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="4">
        
<name>student3</name>
        
<age>13</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="5">
        
<name>student4</name>
        
<age>14</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="6">
        
<name>student5</name>
        
<age>15</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="7">
        
<name>student6</name>
        
<age>16</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="8">
        
<name>student7</name>
        
<age>17</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="9">
        
<name>student8</name>
        
<age>18</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
    
<student id="10">
        
<name>student9</name>
        
<age>19</age>
        
<sex></sex>
        
<address>陕西西安</address>
    
</student>
</data>
代码叫简单,不做过多解释。
posted @ 2011-08-23 15:46 雪山飞鹄 阅读(529) | 评论 (0)编辑 收藏

//调用浏览器

Uri uri 
= Uri.parse("");
Intent it 
= new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);

//显示某个坐标在地图上

Uri uri 
= Uri.parse("geo:38.899533,-77.036476");
Intent it 
= new Intent(Intent.Action_VIEW,uri);
startActivity(it); 

//显示路径

Uri uri 
= Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");
Intent it 
= new Intent(Intent.ACTION_VIEW,URI);
startActivity(it);

//拨打电话

Uri uri 
= Uri.parse("tel:10086");
Intent it 
= new Intent(Intent.ACTION_DIAL, uri); 
startActivity(it); 

Uri uri 
= Uri.parse("tel.10086");
Intent it 
=new Intent(Intent.ACTION_CALL,uri);
需要添加 
<uses-permission id="android.permission.CALL_PHONE" /> 这个权限到androidmanifest.xml

//发送短信或彩信

Intent it 
= new Intent(Intent.ACTION_VIEW); 
it.putExtra(
"sms_body""The SMS text"); 
it.setType(
"vnd.android-dir/mms-sms"); 
startActivity(it); 

//发送短信

Uri uri 
= Uri.parse("smsto:10086"); 
Intent it 
= new Intent(Intent.ACTION_SENDTO, uri); 
it.putExtra(
"sms_body""cwj"); 
startActivity(it); 

//发送彩信

Uri uri 
= Uri.parse("content://media/external/images/media/23"); 
Intent it 
= new Intent(Intent.ACTION_SEND); 
it.putExtra(
"sms_body""some text"); 
it.putExtra(Intent.EXTRA_STREAM, uri); 
it.setType(
"image/png"); 
startActivity(it); 

//发送邮件 
Uri uri = Uri.parse("mailto:android123@163.com");
Intent it 
= new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);

Intent it 
= new Intent(Intent.ACTION_SEND); 
it.putExtra(Intent.EXTRA_EMAIL, android123@
163.com); 
it.putExtra(Intent.EXTRA_TEXT, 
"The email body text"); 
it.setType(
"text/plain"); 
startActivity(Intent.createChooser(it, 
"Choose Email Client")); 

Intent it
=new Intent(Intent.ACTION_SEND); 
String[] tos
={"me@abc.com"}; 
String[] ccs
={"you@abc.com"}; 
it.putExtra(Intent.EXTRA_EMAIL, tos); 
it.putExtra(Intent.EXTRA_CC, ccs); 
it.putExtra(Intent.EXTRA_TEXT, 
"The email body text"); 
it.putExtra(Intent.EXTRA_SUBJECT, 
"The email subject text"); 
it.setType(
"message/rfc822"); 
startActivity(Intent.createChooser(it, 
"Choose Email Client")); 

//播放媒体文件

Intent it 
= new Intent(Intent.ACTION_VIEW);
Uri uri 
= Uri.parse("file:///sdcard/cwj.mp3");
it.setDataAndType(uri, 
"audio/mp3");
startActivity(it);

Uri uri 
= Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); 
Intent it 
= new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it); 

//卸载APK

Uri uri 
= Uri.fromParts("package", strPackageName, null); 
Intent it 
= new Intent(Intent.ACTION_DELETE, uri); 
startActivity(it);

//卸载apk 2
Uri uninstallUri = Uri.fromParts("package""xxx"null);
returnIt 
= new Intent(Intent.ACTION_DELETE, uninstallUri);

//安装APK
Uri installUri = Uri.fromParts("package""xxx"null);
returnIt 
= new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

//播放音乐

Uri playUri 
= Uri.parse("file:///sdcard/download/sth.mp3");
returnIt 
= new Intent(Intent.ACTION_VIEW, playUri);

//发送附近

Intent it 
= new Intent(Intent.ACTION_SEND); 
it.putExtra(Intent.EXTRA_SUBJECT, 
"The email subject text"); 
it.putExtra(Intent.EXTRA_STREAM, 
"file:///sdcard/cwj.mp3"); 
sendIntent.setType(
"audio/mp3"); 
startActivity(Intent.createChooser(it, 
"Choose Email Client"));

//market上某个应用信,pkg_name就是应用的packageName

Uri uri 
= Uri.parse("market://search?q=pname:pkg_name"); 
Intent it 
= new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it); 


//market上某个应用信息,app_id可以通过www网站看下

Uri uri 
= Uri.parse("market://details?id=app_id"); 
Intent it 
= new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it); 

//调用搜索

Intent intent 
= new Intent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,
"android123")
startActivity(intent);
posted @ 2011-08-17 11:10 雪山飞鹄 阅读(520) | 评论 (0)编辑 收藏

本人在web ui设计这块一直很菜。花了一天时间,基于jquery easy ui整了一个后台管理界面。程序的核心在页面布局这块。底层跟数据库交互,这块为了简易起见,使用Apache Commons DbUtils来做了简单的处理。兼容IE6、IE7、IE8、IE9、firefox4、firefox5、chrom、搜狗浏览器等。有心的朋友可以在其他浏览器上测试一下。
登录页面

管理页面

下载地址 http://struts2typeconverter.googlecode.com/files/sitemesh.zip
posted @ 2011-07-23 10:53 雪山飞鹄 阅读(11480) | 评论 (7)编辑 收藏

Cron expressions are comprised of 6 required fields and one optional field separated by white space. The fields respectively are described as follows:

Field Name   Allowed Values   Allowed Special Characters
Seconds   0-59   , - * /
Minutes   0-59   , - * /
Hours   0-23   , - * /
Day-of-month   1-31   , - * ? / L W
Month   1-12 or JAN-DEC   , - * /
Day-of-Week   1-7 or SUN-SAT   , - * ? / L #
Year (Optional)   empty, 1970-2199   , - * /

The '*' character is used to specify all values. For example, "*" in the minute field means "every minute".

The '?' character is allowed for the day-of-month and day-of-week fields. It is used to specify 'no specific value'. This is useful when you need to specify something in one of the two fields, but not the other.

The '-' character is used to specify ranges For example "10-12" in the hour field means "the hours 10, 11 and 12".

The ',' character is used to specify additional values. For example "MON,WED,FRI" in the day-of-week field means "the days Monday, Wednesday, and Friday".

The '/' character is used to specify increments. For example "0/15" in the seconds field means "the seconds 0, 15, 30, and 45". And "5/15" in the seconds field means "the seconds 5, 20, 35, and 50". Specifying '*' before the '/' is equivalent to specifying 0 is the value to start with. Essentially, for each field in the expression, there is a set of numbers that can be turned on or off. For seconds and minutes, the numbers range from 0 to 59. For hours 0 to 23, for days of the month 0 to 31, and for months 1 to 12. The "/" character simply helps you turn on every "nth" value in the given set. Thus "7/6" in the month field only turns on month "7", it does NOT mean every 6th month, please note that subtlety.

The 'L' character is allowed for the day-of-month and day-of-week fields. This character is short-hand for "last", but it has different meaning in each of the two fields. For example, the value "L" in the day-of-month field means "the last day of the month" - day 31 for January, day 28 for February on non-leap years. If used in the day-of-week field by itself, it simply means "7" or "SAT". But if used in the day-of-week field after another value, it means "the last xxx day of the month" - for example "6L" means "the last friday of the month". When using the 'L' option, it is important not to specify lists, or ranges of values, as you'll get confusing results.

The 'W' character is allowed for the day-of-month field. This character is used to specify the weekday (Monday-Friday) nearest the given day. As an example, if you were to specify "15W" as the value for the day-of-month field, the meaning is: "the nearest weekday to the 15th of the month". So if the 15th is a Saturday, the trigger will fire on Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you specify "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary of a month's days. The 'W' character can only be specified when the day-of-month is a single day, not a range or list of days.

The 'L' and 'W' characters can also be combined for the day-of-month expression to yield 'LW', which translates to "last weekday of the month".

The '#' character is allowed for the day-of-week field. This character is used to specify "the nth" XXX day of the month. For example, the value of "6#3" in the day-of-week field means the third Friday of the month (day 6 = Friday and "#3" = the 3rd one in the month). Other examples: "2#1" = the first Monday of the month and "4#5" = the fifth Wednesday of the month. Note that if you specify "#5" and there is not 5 of the given day-of-week in the month, then no firing will occur that month. If the '#' character is used, there can only be one expression in the day-of-week field ("3#1,6#3" is not valid, since there are two expressions).


Here are some full examples:

Expression   Meaning
"0 0 12 * * ?"   Fire at 12pm (noon) every day
"0 15 10 ? * *"   Fire at 10:15am every day
"0 15 10 * * ?"   Fire at 10:15am every day
"0 15 10 * * ? *"   Fire at 10:15am every day
"0 15 10 * * ? 2005"   Fire at 10:15am every day during the year 2005
"0 * 14 * * ?"   Fire every minute starting at 2pm and ending at 2:59pm, every day
"0 0/5 14 * * ?"   Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day
"0 0/5 14,18 * * ?"   Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day
"0 0-5 14 * * ?"   Fire every minute starting at 2pm and ending at 2:05pm, every day
"0 10,44 14 ? 3 WED"   Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.
"0 15 10 ? * MON-FRI"   Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday
"0 15 10 15 * ?"   Fire at 10:15am on the 15th day of every month
"0 15 10 L * ?"   Fire at 10:15am on the last day of every month
"0 15 10 ? * 6L"   Fire at 10:15am on the last Friday of every month
"0 15 10 ? * 6L"   Fire at 10:15am on the last Friday of every month
"0 15 10 ? * 6L 2002-2005"   Fire at 10:15am on every last Friday of every month during the years 2002, 2003, 2004 and 2005
"0 15 10 ? * 6#3"   Fire at 10:15am on the third Friday of every month

 

Pay attention to the effects of '?' and '*' in the day-of-week and day-of-month fields!

posted @ 2011-07-18 13:33 雪山飞鹄 阅读(415) | 评论 (0)编辑 收藏

Log4j XML Configuration Primer

Basic example

Below is a basic xml configuration file for log4j that will get you started:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="console" class="org.apache.log4j.ConsoleAppender"> 
    <param name="Target" value="System.out"/> 
    <layout class="org.apache.log4j.PatternLayout"> 
      <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/> 
    </layout> 
  </appender> 

  <root> 
    <priority value ="debug" /> 
    <appender-ref ref="console" /> 
  </root>
  
</log4j:configuration>

This will print all debug or higher messages to the console/screen. Items of note:

  • The appender is defined first, with a name (in this case "console"). A layout is defined for the appender (in this case  PatternLayout ), and a pattern is defined for the layout. What is required for the layout is layout specific, so check the javadoc description for the layout class you choose to use ( PatternLayout  is used most commonly).

  • No loggers are defined in this example, but the configuration for the "root" logger is defined. It is configured to level debug, and the appender named "console" is attached to it. All loggers inherit from root, so in this example, all debug or higher messages from all loggers will be printed to the console appender.

XML Configuration Format

In order to better understand the more detailed examples, it is useful to understand the expected format for the xml configuration files. This is defined by the log4j.dtd which is located in the log4j distribution jar in the package org.apache.log4j.xml. The contents of this file will not be listed in its entirety, so please feel free to open/print the file yourself. If you are not familiar with xml dtd file formats, then you should go find a good book on that subject first.

Near the beginning of the file is the following declaration:

<!ELEMENT log4j:configuration (renderer*, appender*,(category|logger)*,root?, categoryFactory?)>

This element defines the expected structure of the xml configuration file: 0 or more renderer elements, followed by 0 or more appender elements, followed by 0 or more logger elements, followed by 0 or 1 root element, followed by 0 or 1 categoryFactory element. If this order is not followed, then errors will be printed by the xml parser at the time the xml file is read in. Also, as a note, the "category" element is the same as the logger element. Prior to log4j version 1.2, loggers were known as category. Much of the documentation still refers to category. Just understand that they are the same thing.

Further along in the log4j.dtd is the following declaration which defines the allowed attributes:

<!ATTLIST log4j:configuration
  xmlns:log4j              CDATA #FIXED "http://jakarta.apache.org/log4j/"  
  threshold                (all|debug|info|warn|error|fatal|off|null) "null" 
  debug                    (true|false|null)  "null" 
>
  • debug - Probably the most important attribute for log4:configuration, setting it to "true" will print out information as the configuration file is read and used to configure the log4j environment. Very useful when trying to fiure out why your configuration file is not doing what you expect.

  • threshold - <yet to be described>

Understanding the expected structure of the xml configuration file makes it easier to concentrate on the specific elements one needs to configure.

Appender Configuration

One can instrument all the code one writes to output useful debug trace messages, but if log4j is not configured to have at least one appender, all will be for naught. None of the useful messages will be displayed anywhere.

Looking again to the log4j.dtd, appender elements are declared to be:

<!ELEMENT appender (errorHandler?, param*, layout?, filter*, appender-ref*)>
<!ATTLIST appender
  name          ID      #REQUIRED
  class         CDATA   #REQUIRED
>

An appender element must have name and class attributes. The name is the value used to reference the appender in the rest of the configuration file. The class attribute should be the fully qualified class name of the appender class to use (ie  org.apache.log4j.ConsoleAppender ).

An appender element can also contain child elements:

  • 0 or 1 errorHandler element - <yet to be described>

  • 0 or more param elements - Each appender can be configured with setting specific to the functioning of the appender. This is implemented by getter and setter methods in the appender class. The param element is used to access the setter methods. The format for param elements is simple; they are atomic elements with a name attribute and a value attribute. The name attribute should be the name of the setter method with the "set" part of the method name omitted (ie method name "setTarget" would be "Target"). The value attribute is the value the setter method should be set with.

  • 0 or 1 layout element - Not all appenders use or require a layout. For appenders that do, the layout element defines what layout class to use. The layout element has one attribute, class, which is the fully qualified class name of the layout class to use. Similar to the appender element, the layout element is allowed to have 0 or more param child elements. Again, the param elements are used to set specific values for the layout class, which varies based on what layout class is used.

  • 0 or more filter elements - See the Filter Configuration section below for more details.

  • 0 or more appender-ref elements - <yet to be described>

So, from the above, the simple example of the appender named "console" from the basic example starts to make more sense:

  <appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out"/>
    <layout class="org.apache.log4j.PatternLayout"> 
      <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/> 
    </layout> 
  </appender> 

The name of of the appender is "console" and this is the name that is used to refer to the appender in the rest of the configuration file. The class to use for the appender is  org.apache.log4j.ConsoleAppender .

The console appender has one param element defined. Looking at the javadoc for  ConsoleAppender , the  setTarget  method is used to choose which console stream to print messages to, System.out or System.err. The example configures the appender to use System.out.

The console appender also has a layout element defined which uses  org.apache.log4j.PatternLayout . Looking at the javadoc for  PatternLayout , the setConversionPattern method takes a string describing the layout for messages. The details of this format can also be found in the javadoc.

The details of the configuration for a specific appender class vary from class to class. Your best bet is to review the javadoc for the appender class you want to use. Pay particular attention to the setter property methods and the values they expect. Each setter method can be accessed using the param element in the xml configuration.

Currently, the following appender classes exist:

Logger Configuration

Now the appenders are configured. But how to configure loggers to output messages at a certain level? How to configure loggers to output to specific appender? Welcome to logger configuration.

The most important logger you need to configure is the root logger. From the simple example, this was done with the following configuration:

  <root> 
    <priority value ="debug" /> 
    <appender-ref ref="console" /> 
  </root> 

The root logger is configured to output log message at level "debug" or higher to the appender named "console". All loggers inherit their settings from the root logger, so with no other configuration settings, all loggers will output all of their messages to the "console" appender automatically. This may be fine for simple debugging, but eventually more specific logger configuration is going to be required.

Looking again to the log4j.dtd, logger elements are declared to be:

<!ELEMENT logger (level?,appender-ref*)>
<!ATTLIST logger
  name          ID      #REQUIRED 
  additivity    (true|false) "true"   
>

A logger element must have a name attribute. This is the name of the logger used when creating the Logger instance(usually the fully qualified class name). It can also have an optional additivity attribute. More on this later.

A logger element can also contain child elements:

  • 0 or 1 level element - This defines the level of log messages that will be allowed to be logged for this logger. Normal usage has a value of "debug", "info", "warn", "error", or "fatal". Only that level or above will be reported to the log.

  • 0 or more appender-ref elements - This references a defined appender that log messages from this logger should be directed to. Appender-ref elements are simple elements that have a ref attribute. The value for this attribute should be the name of the appender.

A typical logger configuration element would look similar to this:

<logger name="com.mycompany.apackage.MyClass">
  <level value="info"/> 
</logger>

Logger Inheritance

<yet to be described>

Additivity

The output of a log statement of logger C will go to all the appenders in C and its ancestors. This is the meaning of the term "appender additivity".

However, if an ancestor of logger C, say P, has the additivity flag set to false, then C's output will be directed to all the appenders in C and it's ancestors upto and including P but not the appenders in any of the ancestors of P.

Loggers have their additivity flag set to true by default.

Example config;

<logger name="com.eatmutton.muttonsite.torque" additivity="false">
   <level value="info" />
   <appender-ref ref="local-torque" />
</logger>

Additivitiy section taken from http://logging.apache.org/log4j/docs/manual.html.

Converting Configuration Files To XML format

I have converted the configuration examples from the log4j manual to xml format. Hopefully people can use this to convert their own configuration files.

Example 1

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <!-- A1 is set to be a ConsoleAppender -->
  <appender name="A1" class="org.apache.log4j.ConsoleAppender">
    <!-- A1 uses PatternLayout -->
    <layout class="org.apache.log4j.PatternLayout"> 
      <param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n"/> 
    </layout> 
  </appender> 
  <root> 
    <!-- Set root logger level to DEBUG and its only appender to A1 -->
    <priority value ="debug" /> 
    <appender-ref ref="A1" /> 
  </root>
</log4j:configuration>

Example 2

log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

# Print the date in ISO 8601 format
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n

# Print only messages of level WARN or above in the package com.foo.
log4j.logger.com.foo=WARN

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="A1" class="org.apache.log4j.ConsoleAppender"> 
    <layout class="org.apache.log4j.PatternLayout"> 
      <!-- Print the date in ISO 8601 format -->
      <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/> 
    </layout> 
  </appender> 
  <logger name="com.foo">
    <!-- Print only messages of level warn or above in the package com.foo -->
    <level value="warn"/> 
  </logger>
  <root> 
    <priority value ="debug" /> 
    <appender-ref ref="A1" /> 
  </root>
</log4j:configuration>

Example 3

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> 
    <layout class="org.apache.log4j.PatternLayout"> 
      <!-- Pattern to output the caller's file name and line number -->
      <param name="ConversionPattern" value="%5p [%t] (%F:%L) - %m%n"/> 
    </layout> 
  </appender> 
  <appender name="R" class="org.apache.log4j.RollingFileAppender"> 
    <param name="file" value="example.log"/>
    <param name="MaxFileSize" value="100KB"/>
    <!-- Keep one backup file -->
    <param name="MaxBackupIndex" value="1"/>
    <layout class="org.apache.log4j.PatternLayout"> 
      <param name="ConversionPattern" value="%p %t %c - %m%n"/> 
    </layout> 
  </appender> 
  <root> 
    <priority value ="debug" /> 
    <appender-ref ref="stdout" /> 
    <appender-ref ref="R" /> 
  </root>
</log4j:configuration>

Filter Configuration

Filters can be defined at appender level. For example, to filter only certain levels, the LevelRangeFilter can be used like this:

        <appender name="TRACE" class="org.apache.log4j.ConsoleAppender">
                <layout class="org.apache.log4j.PatternLayout">
                        <param name="ConversionPattern" value="[%t] %-5p %c - %m%n" />
                </layout>
                <filter class="org.apache.log4j.varia.LevelRangeFilter">
                        <param name="levelMin" value="DEBUG" />
                        <param name="levelMax" value="DEBUG" />
                </filter>
        </appender>

Advanced Topics

<yet to be described>

More examples

(Please feel free to add your own configuration examples here)

Note that TimeBasedRollingPolicy can only be configured with xml, not log4j.properties

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<!-- Note that this file is refreshed by the server every 60seconds, as specified in web.xml -->

<log4j:configuration debug="true">

        <appender name="ROLL" class="org.apache.log4j.rolling.RollingFileAppender">
                <!-- The active file to log to -->
                <param name="file" value="/applogs/myportal/portal.log" />
                <param name="append" value="true" />
                <param name="encoding" value="UTF-8" />

                <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
                        <!-- The file to roll to, this is a fairly intelligent parameter, if the file
                        ends in .gz, it gzips it, based on the date stamp it rolls at that time, 
                        default is yyyy-MM-dd, (rolls at midnight)
                        See: http://logging.apache.org/log4j/companions/extras/apidocs/org/apache/log4j/rolling/TimeBasedRollingPolicy.html -->
                        <param name="FileNamePattern" value="/applogs/myportal/portal.%d.log.gz" />
                </rollingPolicy>

                <layout class="org.apache.log4j.PatternLayout">
                        <!-- The log message pattern -->
                        <param name="ConversionPattern" value="%5p %d{ISO8601} [%t][%x] %c - %m%n" />
                </layout>
        </appender>
        
        <!-- Loggers to filter out various class paths -->

        <logger name="org.hibernate.engine.loading.LoadContexts" additivity="false">
                <level value="error"/>
                <appender-ref ref="ROLL" />
        </logger>
        
        <!-- Debugging loggers -->
        
        <!-- Uncomment to enable debug on calpoly code only -->
        <!--
        <logger name="edu.calpoly">
                <level value="debug"/>
                <appender-ref ref="ROLL" />
        </logger>
        -->
        
        <root>
                <priority value="info" />
                <appender-ref ref="ROLL" />
        </root>
        
</log4j:configuration>
posted @ 2011-07-18 11:24 雪山飞鹄 阅读(1813) | 评论 (0)编辑 收藏

自定义标签库并不是 JSP 2 才出现的,JSP 1.1 版中已经增加了自定义标签库规范,自定义标签库是一种非常优秀的表现层组件技术。通过使用自定义标签库,可以在简单的标签中封装复杂的功能。

为什么要使用自定义标签呢?主要是为了取代丑陋的 JSP 脚本。在 HTML 页面中插入 JSP 脚本有如下几个坏处:

  • JSP 脚本非常丑陋,难以阅读。
  • JSP 脚本和 HTML 代码混杂,维护成本高。
  • HTML 页面中嵌入 JSP 脚本,导致美工人员难以参与开发。

出于以上三点的考虑,我们需要一种可在页面中使用的标签,这种标签具有和 HTML 标签类似的语法,但由可以完成 JSP 脚本的功能——这种标签就是 JSP 自定义标签。

在 JSP1.1 规范中开发自定义标签库比较复杂,JSP 2 规范简化了标签库的开发,在 JSP 2 中开发标签库只需如下几个步骤:

  1. 开发自定义标签处理类;
  2. 建立一个 *.tld 文件,每个 *.tld 文件对应一个标签库,每个标签库对应多个标签;
  3. 在 JSP 文件中使用自定义标签。

开发自定义标签类

标签库和实际开发

标签库是非常重要的技术,通常来说,初学者、普通开发人员自己开发标签库的机会很少,但如果希望成为高级程序员,或者希望开发通用框架,就需要大量开发自定义标签了。所有的 MVC 框架,如 Struts 2、SpringMVC、JSF 等都提供了丰富的自定义标签。

当我们在 JSP 页面使用一个简单的标签时,底层实际上由标签处理类提供支持,从而可以使用简单的标签来封装复杂的功能,从而使团队更好地协作开发(能让美工人员更好地参与 JSP 页面的开发)。

早期 JSP 自定义标签类开发过程略微复杂一些,但 JSP 2 已经简化了这个过程,它只要自定义标签类都必须继承一个父类:javax.servlet.jsp.tagext.SimpleTagSupport,除此之外,JSP 自定义标签类还有如下要求。

  • 如果标签类包含属性,每个属性都有对应的 getter 和 setter 方法。
  • 重写 doTag() 方法,这个方法负责生成页面内容。

下面开发一个最简单的自定义标签,该标签负责在页面上输出 HelloWorld。

// 标签处理类,继承 SimpleTagSupport 父类
public class HelloWorldTag extends SimpleTagSupport 
{ 
    // 重写 doTag 方法,该方法在标签结束生成页面内容
    public void doTag()throws JspException, 
        IOException 
    { 
        // 获取页面输出流,并输出字符串
        getJspContext().getOut().write("Hello World"); 
    } 
} 

上面这个标签处理类非常简单,它继承了 SimpleTagSupport 父类,并重写 doTag() 方法,而 doTag() 方法则负责输出页面内容。该标签没有属性,因此无须提供 setter 和 getter 方法。


建立 TLD 文件

TLD 是 Tag Library Definition 的缩写,即标签库定义,文件的后缀是 tld,每个 TLD 文件对应一个标签库,一个标签库中可包含多个标签,TLD 文件也称为标签库定义文件。

标签库定义文件的根元素是 taglib,它可以包含多个 tag 子元素,每个 tag 子元素都定义一个标签。通常我们可以到 Web 容器下复制一个标签库定义文件,并在此基础上进行修改即可。例如 Tomcat6.0,在 webapps\examples\WEB-INF\jsp2 路径下包含了一个 jsp2-example-taglib.tld 文件,这就是示范用的标签库定义文件。

将该文件复制到 Web 应用的 WEB-INF/ 路径,或 WEB-INF 的任意子路径下,并对该文件进行简单修改,修改后的 mytaglib.tld 文件代码如下:

<?xml version="1.0" encoding="GBK"?>
<taglib 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 web-jsptaglibrary_2_0.xsd"
    version="2.0">
    <tlib-version>1.0</tlib-version>
    <short-name>mytaglib</short-name>
    <!-- 定义该标签库的URI -->
    <uri>http://www.crazyit.org/mytaglib</uri>
    <!-- 定义第一个标签 -->
    <tag>
        <!-- 定义标签名 -->
        <name>helloWorld</name>
        <!-- 定义标签处理类 -->
        <tag-class>lee.HelloWorldTag</tag-class>
        <!-- 定义标签体为空 -->
        <body-content>empty</body-content>
    </tag>
</taglib>

上面标签库定义文件也是一个标准的 XML 文件,该 XML 文件的根元素是 taglib 元素,因此我们每次编写标签库定义文件都直接添加该元素即可。

taglib 下有三个子元素:

  • tlib-version:指定该标签库实现的版本,这是一个作为标识的内部版本号,对程序没有太大的作用。
  • short-name:该标签库的默认短名,该名称通常也没有太大的用处。
  • uri:这个属性非常重要,它指定该标签库的 URI,相当于指定该标签库的唯一标识。如上粗体字代码所示,JSP 页面中使用标签库时就是根据该 URI 属性来定位标签库的。

除此之外,taglib 元素下可以包含多个 tag 元素,每个 tag 元素定义一个标签,tag 元素下至少应包含如下三个子元素:

  • name:该标签库的名称,这个属性很重要,JSP 页面中就是根据该名称来使用此标签的。
  • tag-class:指定标签的处理类,毋庸置疑,这个属性非常重要,指定了标签由哪个 Java 类来处理。
  • body-content:这个属性也很重要,它指定标签体内容。该元素的值可以是如下几个:
    • tagdependent:指定标签处理类自己负责处理标签体。
    • empty:指定该标签只能作用空标签使用。
    • scriptless:指定该标签的标签体可以是静态 HTML 元素,表达式语言,但不允许出现 JSP 脚本。
    • JSP:指定该标签的标签体可以使用 JSP 脚本。

实际上由于 JSP 2 规范不再推荐使用 JSP 脚本,所以 JSP 2 自定义标签的标签体中不能包含 JSP 脚本。所以实际上 body-content 元素的值不可以是 JSP。

定义了上面的标签库定义文件后,将标签库文件放在 Web 应用的 WEB-INF 路径,或任意子路径下,Java Web 规范会自动加载该文件,则该文件定义的标签库也将生效。


使用标签库

在 JSP 页面中确定指定标签需要 2 点:

  • 标签库 URI:确定使用哪个标签库。
  • 标签名:确定使用哪个标签。

使用标签库分成以下两个步骤:

  1. 导入标签库:使用 taglib 编译指令导入标签库,就是将标签库和指定前缀关联起来。
  2. 使用标签:在 JSP 页面中使用自定义标签。

taglib 的语法格式如下:

<%@ taglib uri="tagliburi" prefix="tagPrefix" %> 

其中 uri 属性确定标签库的 URI,这个 URI 可以确定一个标签库。而 prefix 属性指定标签库前缀,即所有使用该前缀的标签将由此标签库处理。

使用标签的语法格式如下:

<tagPrefix:tagName tagAttribute=”tagValue” … > 
	<tagBody/> 
</tagPrefix:tagName> 

如果该标签没有标签体,则可以使用如下语法格式:

<tagPrefix:tagName tagAttribute=”tagValue” … /> 

上面使用标签的语法里都包含了设置属性值,前面我们介绍的 HelloWorldTag 标签没有任何属性,所以使用该标签只需用 <mytag:helloWorld/> 即可。其中 mytag 是 taglib 指令为标签库指定的前缀,而 helloWorld 是标签名。

下面是使用 helloWorld 标签的 JSP 页面代码:

<%@ page contentType="text/html; charset=GBK"%>
<!-- 导入标签库,指定mytag前缀的标签,
	由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<html>
<head>
<title>自定义标签示范</title>
</head>
<body bgcolor="#ffffc0">
<h2>下面显示的是自定义标签中的内容</h2>
<!-- 使用标签 ,其中mytag是标签前缀,根据taglib的编译指令,
	mytag前缀将由http://www.crazyit.org/mytaglib的标签库处理 -->
<mytag:helloWorld/><BR>
</body>
</html>

上面页面中第一行粗体字代码指定了 http://www.crazyit.org/mytaglib 标签库的前缀为 mytag,第二行粗体字代码表明使用 mytag 前缀对应标签库里的 helloWorld 标签。浏览该页面将看到如图 1 所示效果:


图 1. 简单标签
图 1. 简单标签

带属性的标签

前面的简单标签既没有属性,也没有标签体,用法、功能都比较简单。实际上还有如下两种常用的标签:

  • 带属性的标签。
  • 带标签体的标签。

正如前面介绍的,带属性标签必须为每个属性提供对应的 setter 和 getter 方法。带属性标签的配置方法与简单标签也略有差别,下面介绍一个带属性标签的示例:

public class QueryTag extends SimpleTagSupport
{
    //标签的属性
    private String driver;
    private String url;
    private String user;
    private String pass;
    private String sql;
    //执行数据库访问的对象 
    private Connection conn = null;
    private Statement stmt = null;
    private ResultSet rs = null;
    private ResultSetMetaData rsmd = null;
    //标签属性driver的setter方法
    public void setDriver(String driver) {
        this.driver = driver; 
    }
        //标签属性url的setter方法
    public void setUrl(String url) {
        this.url = url; 
    }
        //标签属性user的setter方法
    public void setUser(String user) {
        this.user = user; 
    }
        //标签属性pass的setter方法
    public void setPass(String pass) {
        this.pass = pass; 
    }
        //标签属性driver的getter方法
    public String getDriver() {
        return (this.driver); 
    }
        //标签属性url的getter方法
    public String getUrl() {
        return (this.url); 
    }
        //标签属性user的getter方法
    public String getUser() {
        return (this.user); 
    }
        //标签属性pass的getter方法
    public String getPass() {
        return (this.pass); 
    }
        //标签属性sql的getter方法
    public String getSql() {
        return (this.sql); 
    }
        //标签属性sql的setter方法
    public void setSql(String sql) {
        this.sql = sql; 
    }
    public void doTag()throws JspException,
        IOException
    {
           try
        {
            //注册驱动
            Class.forName(driver);
            //获取数据库连接
            conn = DriverManager.getConnection(url,user,pass);
            //创建Statement对象
            stmt = conn.createStatement();
            //执行查询
            rs = stmt.executeQuery(sql);
            rsmd = rs.getMetaData();
            //获取列数目
            int columnCount = rsmd.getColumnCount();
            //获取页面输出流
            Writer out = getJspContext().getOut();
            //在页面输出表格
            out.write("<table border='1' bgColor='9999cc' width='400'>");
            //遍历结果集
            while (rs.next())
            {
                out.write("<tr>");
                //逐列输出查询到的数据
                for (int i = 1 ; i <= columnCount ; i++ )
                {
                    out.write("<td>");
                    out.write(rs.getString(i));
                    out.write("</td>");
                }
                out.write("</tr>");
            }
        }
        catch(ClassNotFoundException cnfe)
        {
            cnfe.printStackTrace();
            throw new JspException("自定义标签错误" + cnfe.getMessage());
        }
        catch (SQLException ex)
        {
            ex.printStackTrace();
            throw new JspException("自定义标签错误" + ex.getMessage());
        }
        finally
        {
            //关闭结果集
            try
            {
                if (rs != null)
                    rs.close();
                if (stmt != null)
                    stmt.close();
                if (conn != null)
                    conn.close();
            }
            catch (SQLException sqle)
            {
                sqle.printStackTrace();
            }
        }
    }
}

上面这个标签稍微复杂一点,它包含了 5 个属性,如程序中粗体字代码所示,则程序需要为这 5 个属性提供 setter 和 getter 方法。

该标签输出的内容依然由 doTag() 方法决定,该方法会根据 SQL 语句查询数据库,并将查询结果显示在当前页面中。

对于有属性的标签,需要为 tag 元素增加 attribute 子元素,每个 attribute 子元素定义一个属性,attribue 子元素通常还需要指定如下几个子元素:

  • name:设置属性名,子元素的值是字符串内容。
  • required:设置该属性是否为不需属性,该子元素的值是 true 或 false。
  • fragment:设置该属性是否支持 JSP 脚本、表达式等动态内容,子元素的值是 true 或 false。

为了配置上面的 QueryTag 标签,我们需要在 mytaglib.tld 文件中增加如下配置片段:

<!-- 定义第二个标签 -->
<tag>
    <!-- 定义标签名 -->
    <name>query</name>
    <!-- 定义标签处理类 -->
    <tag-class>lee.QueryTag</tag-class>
    <!-- 定义标签体为空 -->
    <body-content>empty</body-content>
    <!-- 配置标签属性:driver -->
    <attribute>
        <name>driver</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
    <!-- 配置标签属性:url -->
    <attribute>
        <name>url</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
    <!-- 配置标签属性:user -->
    <attribute>
        <name>user</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
    <!-- 配置标签属性:pass -->
    <attribute>
        <name>pass</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
    <!-- 配置标签属性:sql -->
    <attribute>
        <name>sql</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
</tag>

上面 5 行粗体字代码分别为该标签配置了 driver、url、user、pass 和 sql 等 5 个属性,并指定这 5 个属性都是必填属性、而且属性值支持动态内容。

配置完毕后,就可在页面中使用标签,先导入标签库,然后使用标签。使用标签的 JSP 页面片段如下:

<!-- 导入标签库,指定mytag前缀的标签,
    由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
...
<!-- 其他HTML内容 -->
<!-- 使用标签 ,其中mytag是标签前缀,根据taglib的编译指令,
    mytag前缀将由http://www.crazyit.org/mytaglib的标签库处理 -->
<mytag:query
    driver="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/javaee"
    user="root"
    pass="32147"
    sql="select * from newsinf"/>

在浏览器中浏览该页面,效果如图 2 所示。


图 2. 使用带属性的标签执行查询
图 2. 使用带属性的标签执行查询

图 2 中看到从数据库里查询到 2 条记录,当然这也需要底层 javaee 数据库里包含 newsinf 数据表,且该数据表里包含这两条记录才行。

在 JSP 页面中只需要使用简单的标签,即可完成“复杂”的功能:执行数据库查询,并将查询结果在页面上以表格形式显示。这也正是自定义标签库的目的——以简单的标签,隐藏复杂的逻辑。

当然,并不推荐在标签处理类中访问数据库,因为标签库是表现层组件,它不应该包含任何业务逻辑实现代码,更不应该执行数据库访问,它只应该负责显示逻辑。


带标签体的标签

带标签体的标签,可以在标签内嵌入其他内容(包括静态的 HTML 内容和动态的 JSP 内容),通常用于完成一些逻辑运算,例如判断和循环等。下面以一个迭代器标签为示例,介绍带标签体标签的开发过程。

一样先定义一个标签处理类,该标签处理类的代码如下:

public class IteratorTag extends SimpleTagSupport
{
    //标签属性,用于指定需要被迭代的集合
    private String collection;
    //标签属性,指定迭代集合元素,为集合元素指定的名称
    private String item;
    //collection属性的setter和getter方法
    public void setCollection(String collection)
    {
        this.collection = collection;
    }
    public String getCollection()
    {
        return this.collection;
    }
    //item属性的setter和getter方法
    public void setItem(String item)
    {
        this.item = item;
    }
    public String getItem()
    {
        return this.item;
    }
    //标签的处理方法,简单标签处理类只需要重写doTag方法
    public void doTag() throws JspException, IOException
    {
        //从page scope中获取属性名为collection的集合
        Collection itemList = (Collection)getJspContext().
            getAttribute(collection);
        //遍历集合
        for (Object s : itemList)
        {
            //将集合的元素设置到page 范围
            getJspContext().setAttribute(item, s );
            //输出标签体
            getJspBody().invoke(null);
        }
    }
}

上面标签处理类与前面处理类并没有太大的不同,该处理类包含 2 个属性,并为这两个属性提供了 setter 和 getter 方法。标签处理类的 doTag 方法首先从 page 范围内获取了指定名称的 Collection 对象,然后遍历 Collection 对象的元素,每次遍历都调用了 getJspBody() 方法,如程序中粗体字代码所示,该方法返回该标签所包含的标签体:JspFragment 对象,执行该对象的 invoke() 方法,即可输出标签体内容。该标签的作用是:遍历指定集合,每遍历一个集合元素,即输出标签体一次。

因为该标签的标签体不为空,配置该标签时指定 body-content 为 scriptless,该标签的配置代码片段如下代码所示:

<!-- 定义第三个标签 -->
<tag>
    <!-- 定义标签名 -->
    <name>iterator</name>
    <!-- 定义标签处理类 -->
    <tag-class>lee.IteratorTag</tag-class>
    <!-- 定义标签体支持JSP脚本 -->
    <body-content>scriptless</body-content>
    <!-- 配置标签属性:collection -->
    <attribute>
        <name>collection</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
    <!-- 配置标签属性:item -->
    <attribute>
        <name>item</name> 
        <required>true</required>
        <fragment>true</fragment>
    </attribute>
</tag>

上面配置片段中粗体字代码指定该标签的标签体可以是静态 HTML 内容,也可以是表达式语言。

为了测试在 JSP 页面中使用该标签的效果,我们首先把一个 List 对象设置成 page 范围的属性,然后使用该标签来迭代输出 List 集合的全部元素。

JSP 页面代码如下:

<%@ page import="java.util.*"%>
<%@ page contentType="text/html; charset=GBK"%>
<!-- 导入标签库,指定mytag前缀的标签,
    由http://www.crazyit.org/mytaglib的标签库处理 -->
<%@ taglib uri="http://www.crazyit.org/mytaglib" prefix="mytag"%>
<html>
    <head>
        <title>带标签体的标签-迭代器标签</title>
    </head>
    <body>
        <h2>带标签体的标签-迭代器标签</h2>
        <hr>
        <%
        //创建一个List对象
        List<String> a = new ArrayList<String>();
        a.add("hello");
        a.add("world");
        a.add("java");
        //将List对象放入page范围内
        pageContext.setAttribute("a" , a);
        %>
        <table border="1" bgcolor="aaaadd" width="300">
        <!-- 使用迭代器标签,对a集合进行迭代 -->
        <mytag:iterator collection="a" item="item">
            <tr>
                <td>${pageScope.item}</td>
            <tr>
        </mytag:iterator>
        </table>
    </body>
</html>

上面页面代码中粗体字代码即可实现通过 iterator 标签来遍历指定集合,浏览该页面即看到如图 3 所示界面:


图 3. 带标签体的标签
图 3. 带标签体的标签

图 3 显示了使用 iterator 标签遍历集合元素的效果,从 iteratorTag.jsp 页面的代码来看,使用 iterator 标签遍历集合元素比使用 JSP 脚本遍历集合元素要优雅得多,这就是自定义标签的魅力。

实际上 JSTL 标签库提供了一套功能非常强大标签,例如普通的输出标签,像我们刚刚介绍的迭代器标签,还有用于分支判断的标签等等,JSTL(JSP 标准标签库)都有非常完善的实现。除此之外,Apache 下还有一套 DisplayTags 的标签库实现,做得也非常不错。
本文转自:http://www.ibm.com/developerworks/cn/java/j-lo-jsp2tag/index.html

posted @ 2011-07-14 16:06 雪山飞鹄 阅读(389) | 评论 (0)编辑 收藏

说明一下目录结构
 
Spring配置文件
<?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:p
="http://www.springframework.org/schema/p"
    xmlns:context
="http://www.springframework.org/schema/context"
    xsi:schemaLocation
="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>
    
<context:component-scan
        
base-package="com.spring.action" />
    
<!--  
        org.springframework.web.servlet.view.ResourceBundleViewResolver
        用于多个视图集成时,ResourceBundleViewResolver是通过解析资源文件来解析请求输出文件的。
        <property name="basename" value="views"></property>,即表示在/WEB-INF/classes路径下有一个
        views.properties文件,本例中views.properties的内容为
        welcome.(class)=org.springframework.web.servlet.view.velocity.VelocityView
        welcome.url=welcome.vm
        freemarker.(class)=org.springframework.web.servlet.view.freemarker.FreeMarkerView
        freemarker.url=freemarker.ftl
    
-->
    
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
        
<property name="basename" value="views"></property>
        
<!-- 
            <property name="order" value="0"></property>
        
-->
    
</bean>
    
    
<!-- jsp视图解析器 -->
    
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        
<property name="prefix" value="/"/>
        
<property name="suffix" value=".jsp"/>
    
</bean>        
    
    
<!-- velocity视图解析器 -->
    
<bean id="velocityViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        
<property name="cache" value="true"/>
        
<property name="prefix" value="/"/>
        
<property name="suffix" value=".vm"/>
    
</bean>
    
    
<!-- velocity环境配置 -->
    
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        
<!-- velocity配置文件路径 -->
        
<property name="configLocation" value="/WEB-INF/velocity.properties"/>
        
<!-- velocity模板路径 -->
        
<property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
    
</bean>
    
    
<!-- FreeMarker环境配置 -->
    
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        
<!-- freemarker模板位置 -->
        
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
    
</bean>
    
    
<!-- FreeMarker视图解析 -->
    
<bean id="freeMarkerViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        
<property name="cache" value="true"/>
        
<property name="prefix" value="/"/>
        
<property name="suffix" value=".ftl"/>
    
</bean>
</beans>
views.properties
#welcome为modelAndView.setViewName("welcome");中的welcome   .(class)固定写法
welcome.(class)=org.springframework.web.servlet.view.velocity.VelocityView
#welcome.url 路径 welcome.vm模板名称
welcome.url
=welcome.vm

#freemarker为modelAndView.setViewName(
"freemarker");中的freemarker   .(class)固定写法
freemarker.(class)=org.springframework.web.servlet.view.freemarker.FreeMarkerView
#freemarker.url 路径 freemarker.ftl模板名称
freemarker.url
=freemarker.ftl
点我下载示例代码
posted @ 2011-07-13 17:14 雪山飞鹄 阅读(12813) | 评论 (4)编辑 收藏

package com.ipmotor.sm.db;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;


/**
 * 利用HttpClient,模拟https连接
 * 使用4.1版本
 * 
@since 2011.7.7
 
*/
public class Test{
    
    
/**
     * 运行主方法
     * 
@param args
     * 
@throws Exception
     
*/
    
public static void main(String[] args) throws Exception {
      
//获得httpclient对象
      HttpClient httpclient = new DefaultHttpClient();
      
//获得密匙库
      KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
      FileInputStream instream 
= new FileInputStream(new File("D:/zzaa"));
      
//密匙库的密码
      trustStore.load(instream, "123456".toCharArray());
      
//注册密匙库
      SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
      
//不校验域名
      socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
      Scheme sch 
= new Scheme("https"800, socketFactory);
      httpclient.getConnectionManager().getSchemeRegistry().register(sch);
      
//获得HttpGet对象
      HttpGet httpGet = null;
      httpGet 
= new HttpGet("https://10.15.32.176:800/cgi-bin/service.cgi?session=caef0c3742c8f8ef4c98772e860c9fd2&rand=128&domain=sun.com&type=domain&cmd=disable");
      
//发送请求
      HttpResponse response = httpclient.execute(httpGet);
      
//输出返回值
      InputStream is = response.getEntity().getContent();
      BufferedReader br 
= new BufferedReader(new InputStreamReader(is));
      String line 
= "";
      
while((line = br.readLine())!=null){
          System.out.println(line);
      }
    }
}
依赖的jar包
commons-codec-1.4.jar
commons-logging-1.1.1.jar
httpclient-4.1.1.jar
httpclient-cache-4.1.1.jar
httpcore-4.1.jar
httpmime-4.1.1.jar
posted @ 2011-07-08 14:14 雪山飞鹄 阅读(24653) | 评论 (3)编辑 收藏

package com.ipmotor.sm.db;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 测试jdk中的栈和队列
 * 
@author scott
 *
 
*/
public class TestQueueAndStack {
    
    
/**
     * 测试队列
     * <pre>
     * 队列特点,先进先出,后进后出,火车过山洞例子
     * </pre>
     
*/
    
static void testQueue(){
        Queue
<String> queue=new LinkedList<String>();
        
//添加几个元素
        queue.offer("a");
        queue.offer(
"b");
        queue.offer(
"c");
        queue.offer(
"d");
        queue.offer(
"e");
        queue.add(
"1");
        queue.add(
"2");
        queue.add(
"3");
        queue.add(
"4");
        queue.add(
"5");
        System.out.println(
"队列中的元素是:"+queue);
        
//弹出元素
        queue.poll();
        System.out.println(
"队列中的元素是:"+queue);
        
//查看队列中首个元素,并不移除
        String peek=queue.peek();
        System.out.println(
"查看队列中首个元素,并不移除:"+peek);
        System.out.println(
"队列中的元素是:"+queue);
    }
    
    
    
/**
     * 测试栈
     * <pre>
     * 先进后出,后进先出,水桶倒水
     * </pre>
     
*/
    
static void testStack(){
        Stack
<String> stack=new Stack<String>();
        
//添加几个元素
        stack.push("a");
        stack.push(
"b");
        stack.push(
"c");
        stack.push(
"d");
        stack.push(
"e");
        stack.add(
"1");
        stack.add(
"2");
        stack.add(
"3");
        stack.add(
"4");
        stack.add(
"5");
        System.out.println(
"栈中的元素是:"+stack);
        
//弹出元素
        stack.pop();
        System.out.println(
"栈中的元素是:"+stack);
        
//查看栈中首个元素,并不移除
        String peek=stack.peek();
        System.out.println(
"查看栈中首个元素,并不移除:"+peek);
        System.out.println(
"栈中的元素是:"+stack);
    }
    

    
/**
     * 
@param args
     
*/
    
public static void main(String[] args) {
        testQueue();
        System.out.println(
"-------栈--------");
        testStack();
    }

}

队列中的元素是:[a, b, c, d, e, 1, 2, 3, 4, 5]
队列中的元素是:[b, c, d, e, 1, 2, 3, 4, 5]
查看队列中首个元素,并不移除:b
队列中的元素是:[b, c, d, e, 1, 2, 3, 4, 5]
-------栈--------
栈中的元素是:[a, b, c, d, e, 1, 2, 3, 4, 5]
栈中的元素是:[a, b, c, d, e, 1, 2, 3, 4]
查看栈中首个元素,并不移除:4
栈中的元素是:[a, b, c, d, e, 1, 2, 3, 4]
posted @ 2011-07-08 13:37 雪山飞鹄 阅读(941) | 评论 (0)编辑 收藏

首先在github上申请一个账户
https://github.com/
接下来创建项目名称什么的
然后根据他初始化的信息结合一下博文即可轻松将项目托管到github
http://artori.us/git-github-usage/
posted @ 2011-07-01 11:34 雪山飞鹄 阅读(2368) | 评论 (0)编辑 收藏

仅列出标题
共22页: First 上一页 2 3 4 5 6 7 8 9 10 下一页 Last