使用Google Weather API查詢天氣預報 收藏Google Weather API 只支持美國地區使用郵政編碼進行查詢,例如:
http://www.google.com/ig/api?hl=zh-cn&weather=94043
(94043 為 山景城, 美國加州 的郵政編碼)
而除了美國以外的地區需要使用經緯度坐標作為參數才能執行 Google Weather API, 例如:
http://www.google.com/ig/api?hl=zh-cn&weather=,,,30670000,104019996
(30670000,104019996 為 成都, 中國大陸 的經緯度坐標)
當然,也可能通行城市名稱的漢語拼音來查詢,例如:以下是北京的天氣
http://www.google.com/ig/api?hl=zh-cn&weather=Beijing
要其它地區的經緯度坐標,可以通過 Google API 提供的國家代碼列表及相應的城市經緯度坐標列表可以查詢到,以下是 Google API 提供的查詢參數:
http://www.google.com/ig/countries?output=xml&hl=zh-cn
(查詢 Google 所支持的所有國家的代碼,并以 zh-cn 簡體中文顯示)
http://www.google.com/ig/cities?output=xml&hl=zh-cn&country=cn
http://www.google.com/ig/cities?country=cn
缺省返回的是英文, 可以增加一個參數來返回中文:
http://www.google.com/ig/api?weather=Nanjing&hl=zh-cn
取得中國的所有城市代碼:
http://www.google.com/ig/cities?country=cn
缺省返回是 JSON 格式.增加一個參數返回XML格式(Firefox 中不行)
http://www.google.com/ig/cities?country=cn&output=xml
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).
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.
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:
org.apache.log4j.ConsoleAppender ConsoleAppender
org.apache.log4j.FileAppender FileAppender
org.apache.log4j.jdbc.JDBCAppender JDBCAppender
org.apache.log4j.AsyncAppender AsyncAppender
org.apache.log4j.net.JMSAppender JMSAppender
org.apache.log4j.lf5.LF5Appender LF5Appender
org.apache.log4j.nt.NTEventLogAppender NTEventLogAppender
org.apache.log4j.varia.NullAppender NullAppender
org.apache.log4j.net.SMTPAppender SMTPAppender
org.apache.log4j.net.SocketAppender SocketAppender
org.apache.log4j.net.SocketHubAppender SocketHubAppender
org.apache.log4j.net.SyslogAppender SyslogAppender
org.apache.log4j.net.TelnetAppender TelnetAppender
org.apache.log4j.WriterAppender WriterAppender
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>
<yet to be described>
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.
I have converted the configuration examples from the log4j manual to xml format. Hopefully people can use this to convert their own configuration files.
# 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>
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>
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>
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>
<yet to be described>
(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>
為什么要使用自定義標簽呢?主要是為了取代丑陋的 JSP 腳本。在 HTML 頁面中插入 JSP 腳本有如下幾個壞處:
出于以上三點的考慮,我們需要一種可在頁面中使用的標簽,這種標簽具有和 HTML 標簽類似的語法,但由可以完成 JSP 腳本的功能——這種標簽就是 JSP 自定義標簽。
在 JSP1.1 規范中開發自定義標簽庫比較復雜,JSP 2 規范簡化了標簽庫的開發,在 JSP 2 中開發標簽庫只需如下幾個步驟:
當我們在 JSP 頁面使用一個簡單的標簽時,底層實際上由標簽處理類提供支持,從而可以使用簡單的標簽來封裝復雜的功能,從而使團隊更好地協作開發(能讓美工人員更好地參與 JSP 頁面的開發)。
早期 JSP 自定義標簽類開發過程略微復雜一些,但 JSP 2 已經簡化了這個過程,它只要自定義標簽類都必須繼承一個父類:javax.servlet.jsp.tagext.SimpleTagSupport,除此之外,JSP 自定義標簽類還有如下要求。
下面開發一個最簡單的自定義標簽,該標簽負責在頁面上輸出 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 是 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 下有三個子元素:
除此之外,taglib 元素下可以包含多個 tag 元素,每個 tag 元素定義一個標簽,tag 元素下至少應包含如下三個子元素:
實際上由于 JSP 2 規范不再推薦使用 JSP 腳本,所以 JSP 2 自定義標簽的標簽體中不能包含 JSP 腳本。所以實際上 body-content 元素的值不可以是 JSP。
定義了上面的標簽庫定義文件后,將標簽庫文件放在 Web 應用的 WEB-INF 路徑,或任意子路徑下,Java Web 規范會自動加載該文件,則該文件定義的標簽庫也將生效。
在 JSP 頁面中確定指定標簽需要 2 點:
使用標簽庫分成以下兩個步驟:
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 所示效果:
前面的簡單標簽既沒有屬性,也沒有標簽體,用法、功能都比較簡單。實際上還有如下兩種常用的標簽:
正如前面介紹的,帶屬性標簽必須為每個屬性提供對應的 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 子元素通常還需要指定如下幾個子元素:
為了配置上面的 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 條記錄,當然這也需要底層 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 顯示了使用 iterator 標簽遍歷集合元素的效果,從 iteratorTag.jsp 頁面的代碼來看,使用 iterator 標簽遍歷集合元素比使用 JSP 腳本遍歷集合元素要優雅得多,這就是自定義標簽的魅力。
實際上 JSTL 標簽庫提供了一套功能非常強大標簽,例如普通的輸出標簽,像我們剛剛介紹的迭代器標簽,還有用于分支判斷的標簽等等,JSTL(JSP 標準標簽庫)都有非常完善的實現。除此之外,Apache 下還有一套 DisplayTags 的標簽庫實現,做得也非常不錯。
本文轉自:http://www.ibm.com/developerworks/cn/java/j-lo-jsp2tag/index.html
經常需要將一些受到版本控制的文件夾挪作他用,在用版本庫的同學都知道,里面的 .svn 文件夾不僅遍布整個文件夾的各個層級,而且里面東西很多,如果遇到要刪除的情況,手動一一刪除可就累了,小D就經常為了刪這些.svn文件夾而刪到手酸,吃過幾次苦之后決定找出批量刪除的方法… 還好,只要有需求就用解決方法,這就分享給大家吧,說不定哪天就能用上,適用于windows客戶端:
確定要刪除的是下面這樣的文件夾,此方面就適用于此,可別弄錯了:
安裝:建立一個文本文件,隨意起個名字,例如aaa.reg(擴展名由txt改為reg,可以在txt編輯的時候點另存為…類型所有、文件名aaa.reg、保存即可),內容如下:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]
@="Delete SVN Folders"
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]
@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""
保存之后,雙擊這個reg文件,會提示是否允許添加到注冊表,確定并提示成功后,在每一個文件夾上點擊右鍵都會有一個“Delete SVN Folders”的選項,點擊就可以刪除這個文件夾及子目錄里面所有的.svn文件了,很方便吧;
注:“Delete SVN Folders”可根據自己的喜好修改,將文件中@="Delete SVN Folders"雙引號內的內容修改成其他即可。
卸載:有同學又要問了:我這次用完了,很好!但我不想要了,點右鍵就出來影響美觀怎么辦?
小D考慮到了這點,現在就告訴你怎么刪,剛才是添加到了注冊表,那我們可以直接去注冊表刪:
運行 regedit 進入注冊表->依次打開:HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\->看到DeleteSVN文件夾->刪除就可以了,也很簡單吧,但小D要提醒你,注冊表不要隨便改動,最好備份一下啊。
OK,分享完畢,感謝收聽。
本人轉自http://www.didiao.net/?p=455
第二步、創建相應的部署目錄
..\Tomcat 6.0\webapps1
..\Tomcat 6.0\webapps2
同時可以將Tomcat 6.0\webapps下的有用的復制到新建的部署目錄
第三步、創建配置文件目錄和配置文件
..\Tomcat 6.0\conf\Catalina1\localhost
..\Tomcat 6.0\conf\Catalina2\localhost
host-manager.xml
manager.xml
配置文件的配置可參照..\Tomcat 6.0\conf\Catalina\localhost下的,只需要修改一下對應目錄即可
大概的配置步驟就是這些,現在可以把不同的war包放在不同的位置來訪問了
以上配置方法同樣適合Tomcat 5.5
事實上,速查表就是來幫助我們把日常中最常用到的信息聚集起來,方便使用,使我們做工作時更有效率。有了它們,免去了你的大腦花額外時間去記憶它們的煩惱——你只需要打開簡表,馬上能查到你想要的信息。
這篇文章里,你可以看到最實用的HTML,CSS,JavaScript速查表,它們可以當作參考資料,備忘錄,能幫助你以最快的速度找到想要的信息。
看看這些簡表是不是你想要的,請在文章下面留下你的建議,謝謝!
Javascript
希望你能喜歡我收集到的這些速查表,并請分享給你的做開發工作的朋友們。
[英文出處]:Most Useful Cheat Sheet For HTML, CSS and Javascript
Celestia 是一款免費開放源代碼軟件。國內有軟件介紹把它稱作「宇宙穿梭機」或是「鳥瞰地球」,這都名副其實。Celestia 會通過檢測操作系統語言自動切換軟件語言,對中文支持良好。
用十字指針指向一個星球,在 Celestia 左上角即顯示星球的信息。也可以像下圖一樣選擇顯示星座,就是在現實看見的同樣的星座,沒有連線,觀賞感受也是不同的。Celestia 的功能多以關鍵字執行,剛上手也許會感覺不知所措,一時了解不到其中的趣味,只要認識了 Celestia 的基本操作,就能發覺把玩 Celestia 是一件多么有趣的事。
同樣作為新手,波斯推薦一定要看 Celestia 的內置演示,就在幫助菜單可以找到。演示有字幕介紹星球的著名點,帶你用 Celestia 遨游太陽系,從地球到月球,再去逛土星……就像一個無影的導游在帶你進行太空旅行。剛打開 Celestia,我覺得它超悶,但是看了演示后,探索 Celestia 的熱情就被激發起來了。
Celestia 還能通過插件增強功能,不過目前插件還只有 1 個。(笑)
下載地址:http://www.shatters.net/celestia/download.html | 自用版本分流 | 35M。
2. Stellarium – 從地球看星際
Stellarium 非常強悍地內置了非常多國語言,光是中文就有 3 種(為什么有 3 種?)。從設置上來說,可控制的比 Celestia 更多,當然在用途上也有所出入。最不同的是,Stellarium 給你一種從自家陽臺抬頭望天的觀賞感受,而這點 Celestia 是做不到的。Stellarium 也是免費開放源代碼軟件。
Stellarium 同樣能點擊星球顯示信息,顯示信息比 Celestia 的全面。在星座顯示上,還能顯示形象配圖。所見區域也能選擇地域而定,不過預設的中國區域太少了,找來找去才只有一個 Acheng, China。
用戶可以通過拖拽天空看到頭頂上的星際。默認是實時顯示,所以波斯的截圖就不是夜間版了,夜間版比較有說服力的說。背景的圖,就是下圖可見的樹木房屋之類都是可換的。
不過 Stellarium 貌似對字體有要求,也許是波斯換了語言后沒有設置好,如圖所見的本來應該顯示星球名稱的地方都變成了小方塊。不過跟 GDI++ 字體渲染沒有沖突。
Stellarium 在官方主頁有新手教學,比 Celestia 重視新人用戶培養呢。
下載地址:http://www.stellarium.org/zh/ | Windows 版本約 41M。
希望你也能從這兩款軟件找到你久違的星空吧!離題地說一句,大家要愛護環境,保護地球噢!