﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-明天的明天的明天</title><link>http://www.blogjava.net/freiberg/</link><description>用键盘改变生活</description><language>zh-cn</language><lastBuildDate>Fri, 17 Apr 2026 14:10:32 GMT</lastBuildDate><pubDate>Fri, 17 Apr 2026 14:10:32 GMT</pubDate><ttl>60</ttl><item><title>&lt;html:cancel&gt;标签报org.apache.struts.action.InvalidCancelException错误问题</title><link>http://www.blogjava.net/freiberg/archive/2007/10/20/154384.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Fri, 19 Oct 2007 17:20:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/10/20/154384.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/154384.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/10/20/154384.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/154384.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/154384.html</trackback:ping><description><![CDATA[这个问题，本来已经搞好了，但是忘了重新编译，郁闷了半天。。<br />
下面看看解决方案吧：<br />
<p>Any existing applications that use the <strong>Cancel</strong> processing will need to modify their struts-config.xml to set the <strong>cancellable</strong> property for actions which require it. </p>
<p>In Struts 1.2.9 the <strong>&lt;set-property&gt;</strong> is used to set the <strong>cancellable</strong> property for an action.... </p>
<pre>    &lt;action path="/fooAction"
input="/foo.jsp"
validate="true"&gt;
&lt;set-property property="cancellable" value="true"/&gt;
&lt;forward name="success" path="/bar.jsp"/&gt;
&lt;/action&gt;
</pre>
<p>From Struts 1.3.x a new <strong>cancellable</strong> attribute can be used.... </p>
<pre>    &lt;action path="/fooAction"
input="/foo.jsp"
validate="true"
cancellable="true"&gt;
&lt;forward name="success" path="/bar.jsp"/&gt;
&lt;/action&gt;
</pre>
<p>In both Struts 1.2.9 and Struts 1.3.x an exception handler can be configured to handle the <tt>InvalidCancelException</tt> </p>
<pre>    &lt;action path="/fooAction"
input="/foo.jsp"
validate="true"
cancellable="true"&gt;
&lt;forward name="success" path="/bar.jsp"/&gt;
&lt;exception key="errors.cancel"
type="org.apache.struts.action.InvalidCancelException"
path="/foo.jsp"/&gt;
&lt;/action&gt;
</pre>
<img src ="http://www.blogjava.net/freiberg/aggbug/154384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-10-20 01:20 <a href="http://www.blogjava.net/freiberg/archive/2007/10/20/154384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j入门与应用</title><link>http://www.blogjava.net/freiberg/archive/2007/10/18/153765.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Thu, 18 Oct 2007 01:39:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/10/18/153765.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/153765.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/10/18/153765.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/153765.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/153765.html</trackback:ping><description><![CDATA[<p><font color="#333333">第一部分，快速入门<br />
<br />
首先，需要去下载LOG4J这个软件并解压缩出其中的log4j.jar.在你的应用程序的classpath中包含该JAR文件，你也可以简单地将这个文件拷贝到JDK的%java_home%\lib\ext目录下。<br />
在作完以上工作后，你可以将下面的代码保存到名为TestLogging.java中：<br />
##############################<br />
import org.apache.log4j.*;<br />
<br />
// How to use log4j<br />
public class TestLogging {<br />
<br />
// Initialize a logging category. Here, we get THE ROOT CATEGORY<br />
//static Category cat = Category.getRoot();<br />
// Or, get a custom category<br />
static Category cat = Category.getInstance(TestLogging.class.getName());<br />
<br />
// From here on, log away! Methods are: cat.debug(your_message_string),<br />
// cat.info(...), cat.warn(...), cat.error(...), cat.fatal(...)<br />
<br />
public static void main(String args[]) {<br />
// Try a few logging methods<br />
cat.debug("Start of main()");<br />
cat.info("Just testing a log message with priority set to INFO");<br />
cat.warn("Just testing a log message with priority set to WARN");<br />
cat.error("Just testing a log message with priority set to ERROR");<br />
cat.fatal("Just testing a log message with priority set to FATAL");<br />
<br />
// Alternate but INCONVENIENT form<br />
cat.log(Priority.DEBUG, "Calling init()");<br />
<br />
new TestLogging().init();<br />
}<br />
<br />
public void init() {<br />
java.util.Properties prop = System.getProperties();<br />
java.util.Enumeration enum = prop.propertyNames();<br />
<br />
cat.info("***System Environment As Seen By Java***");<br />
cat.debug("***Format: PROPERTY = VALUE***");<br />
<br />
while (enum.hasMoreElements()) {<br />
String key = (String) enum.nextElement();<br />
cat.info(key + " = " + System.getProperty(key));<br />
}<br />
}<br />
<br />
}<br />
<br />
############################################################<br />
Log4J 默认情况下可以记录五个层次（由低到高）的日志消息。<br />
1) debug<br />
2)info<br />
3)warn<br />
4)error<br />
5)fatal<br />
<br />
在TestLoggin.class的目录中保存下列行在一个名字为log4j.properties 文件中.默认情况下，当你在代码中使用getRoot()或getInstance("category_name")时，Log4j会在应用程序的 classpath中查找该文件：<br />
############################################<br />
log4j.rootCategory=DEBUG, dest1<br />
log4j.appender.dest1=org.apache.log4j.ConsoleAppender<br />
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout<br />
############################################<br />
ConsoleAppender指定的是控制台附加器，即日志消息会输出到控制台上，而PatternLayout则指定了消息输出的格式，默认情况下格式为%m%n,%m指定的是消息内容，%n指定的是操作系统平台上的换行符,这里更类似于C语言中的输出控制语句。<br />
现在，你可以编译并且运行TestLogging.java了，你可以获得以下输出结果：<br />
<br />
Start of main()<br />
Just testing a log message with priority set to INFO<br />
Just testing a log message with priority set to WARN<br />
Just testing a log message with priority set to ERROR<br />
Just testing a log message with priority set to FATAL<br />
Calling init()<br />
***System Environment As Seen By Java***<br />
***Format: PROPERTY = VALUE***<br />
java.runtime.name = Java(TM) 2 Runtime Environment, Standard Edition<br />
sun.boot.library.path = c:\jdk1.3\jre\bin<br />
java.vm.version = 1.3.0_02<br />
java.vm.vendor = Sun Microsystems Inc.<br />
... and so on<br />
<br />
如果想打印消息的层次如debug,info,error等，那可以在log4j.properties 文件的最后一行上增加如下一行：<br />
log4j.appender.dest1.layout.ConversionPattern=%-5p: %m%n<br />
这一行覆盖了默认的消息输出格式%m%n,%p指定的是打印消息的层次（info,debug...,其中-5指定的是五个字符的宽度，-指定的是左对齐),%m指定的是消息的内容，%n指定的则是操作系统平台上的换行符.<br />
当作完这些工作后，无须重新编译TestLogging.java，再次运用TestLogg，会得到以下不出的输出结果：<br />
DEBUG: Start of main()<br />
INFO : Just testing a log message with priority set to INFO<br />
WARN : Just testing a log message with priority set to WARN<br />
ERROR: Just testing a log message with priority set to ERROR<br />
FATAL: Just testing a log message with priority set to FATAL<br />
DEBUG: Calling init()<br />
INFO : ***System Environment As Seen By Java***<br />
DEBUG: ***Format: PROPERTY = VALUE***<br />
INFO : java.runtime.name = Java(TM) 2 Runtime Environment, Standard Edition<br />
INFO : sun.boot.library.path = c:\jdk1.3\jre\bin<br />
INFO : java.vm.version = 1.3.0_02<br />
INFO : java.vm.vendor = Sun Microsystems Inc.<br />
... and so on<br />
<br />
如果不想输出日志的DEBUG与INFO消息，那么可以修改"log4j.rotCategory=DEBUG,dest1"为：<br />
log4j.rootCategory=WARN,dest1<br />
该行文件告诉Log4j跳过层次低于WARN的消息输出，也就是说如DEBUG,INFO层次的消息将不会产生输出，再次运行TestLogging.class，得到以下结果：<br />
####################<br />
WARN : Just testing a log message with priority set to WARN<br />
ERROR: Just testing a log message with priority set to ERROR<br />
FATAL: Just testing a log message with priority set to FATAL<br />
####################<br />
<br />
第二部分 Log4j 详解<br />
Log4j有三个主要的组件：category ,附件器和布局。<br />
在程序中，你可以初始化一个category 并且调用它的各种日志方法来将消息字符串记录到日志中。<br />
一个category可以被配置用来输出到多个目标，这些日志目标在Log4j框架中被称为附件器,这些附件器可以包括控制台、文本文件、HTML文件、 XML文件甚至是Windows平的事件日志系统，甚至可以被作为邮件被发送。而这些所有的目标都是通过log4j.properties文件来进行配置，对于使用Log4j框架的程序来讲只是简单地调用类似于info()、debug()等的方法。<br />
附件器类可以是ConsoleAppender, FileAppender, SMTPAppender, SocketAppender, NTEventLogAppender, SyslogAppender, JMSAppender, AsyncAppender 和 NullAppender等。 附件器类可以使用布局（layout）来在发送消息到目标之前进行格式化。例如HTMLLayout将会把消息格式化为HTML 格式。<br />
除了可以记录消息字符串到日志文件之外，同时还可以记录日期、时间、消息层次、类名、源代码的行数、方法名称、线程名称以及其它信息，而具体的输出需要由附件器的布局管理器来配置。<br />
category的名字是大小写区分以"."分隔的一个字符串。一般情况下我们通常使用your_class_name.class.getName()来获得一个JAVA类名来作为category的名字，例如testproj.util.test。<br />
Each word in the category name is said to be an ancestor of the subsequent words and a parent of the immediately following word. This is important because Log4j has this concept of inheriting priorities and appenders from ancestors until overridden in a particular category.<br />
有一个没有名称的category叫root,它就像xml的document元素，是所有category的祖先。<br />
可以使用以下代码来初始一个根category或指定的category。<br />
################<br />
Category cat = Category.getRoot();<br />
Category cat2 = Category.getInstance("your.category.name");<br />
###################<br />
代表层次的常量由高到次是FATAL、ERROR、WARN、INFO和DEBUG，可以在log4j.properties中指定category所属的层次，例如指定log4j.rootCategory=WARN,simple则意味调用root这个category的程序只会记录WARN及 WARN以上的消息。如果没有为一个category指定默认的category，那么category将会从其父category来继承。<br />
常见的Category类的日志方法有：<br />
public void log(Priority p, Object message);<br />
<br />
// Convenient shortcuts to the generic logging method<br />
public void debug(Object message);<br />
public void info(Object message);<br />
public void warn(Object message);<br />
public void error(Object message);<br />
public void fatal(Object message);<br />
<br />
log4j 只记录层次与预设层次相等或更高级别的消息，如以下代码：<br />
Category cat = Category.getRoot();<br />
cat.setPriority(Priority.ERROR);//设置预设层次为ERROR级<br />
// Later...<br />
//cat.info("Started processing..."); //这条消息将不会输出，ERROR<br />
cat.error("User input is erroneous!"); //消息输出，层次相等<br />
cat.fatal("Cannot process user input. Program terminated!"); //消息输出，层次高于预设层次<br />
<br />
第三部分 Log4j 配置<br />
所有的配置工作应该在log4j.properties文件中完成，而该文件一般须放在应用程序的相同的目录中。<br />
在日志系统使用之前，我们必须首先配置log4j.配置log4j意味着增加附件器到Category并且为每一个Category设置一个Layout。<br />
category之间是有继承关系，但他们增加到log4j.properties文件中的顺序是不固定的。<br />
示例一:<br />
#############################################################<br />
# 设置log4j的根category所使用的预设层次是DEBUG,而只使用A1这个附件器.<br />
log4j.rootCategory=DEBUG, A1<br />
#附件器A1被设置为控制台附件器。<br />
log4j.appender.A1=org.apache.log4j.ConsoleAppender<br />
#附件器使用的布局是PatternLayout,即模式布局<br />
log4j.appender.A1.layout=org.apache.log4j.PatternLayout<br />
#附件器A1的模式是%-4r [%t] %-5p %c %x - %m%n,其中%m代表消息字符串，%n代表换行符,其它以%开头的字符代表的含义如下文。<br />
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n<br />
################################################################# <br />
示例二：<br />
#########################################################<br />
#### Use two appenders, one to log to console, another to log to a file<br />
log4j.rootCategory=debug, stdout, R<br />
# Print only messages of priority WARN or higher for your category<br />
log4j.category.your.category.name=WARN<br />
# Specifically inherit the priority level<br />
#log4j.category.your.category.name=INHERITED<br />
#### First appender writes to console<br />
log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />
<br />
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br />
# Pattern to output the caller's file name and line number.<br />
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n<br />
#### Second appender writes to a file<br />
log4j.appender.R=org.apache.log4j.RollingFileAppender<br />
log4j.appender.R.File=example.log<br />
# Control the maximum log file size<br />
log4j.appender.R.MaxFileSize=100KB<br />
# Archive log files (one backup file here)<br />
log4j.appender.R.MaxBackupIndex=1<br />
log4j.appender.R.layout=org.apache.log4j.PatternLayout<br />
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n<br />
########################################################</font></p>
第四部分 Log4j中有用的Layout<br />
一些有用的layout有TTCCLayout, HTMLLayout, PatternLayout, SimpleLayout 和 XMLLayout.<br />
其中SimpleLayout和PatternLayout忽略JAVA throwable 接口派生出来的errors和Exceptions.HTMLLayout和XMLLayout处理这些异常。<br />
SimpleLayout的输出中包含日志消息的层次，紧跟着&#8220;-&#8221;后面的日志消息字符串。例如：<br />
DEBUG - Hello World Message<br />
Patternlayout 可以根据输出的模式字符串来决定消息的输出，模式字符串类似于C语言中的模式字符串。例如PatternLayout中如果使用模式字符串&#8220;%r [%t] %-5p %c -%m%n&#8221;会输出以下消息：<br />
176 [main] INFO org.foo.Bar -Located nearest gas station<br />
以下对各域作一下解释：<br />
1）%r输出程序开始执行之后的微秒数<br />
2）%t输出当前线程的名称<br />
3）%-5p输出消息的层次。<br />
4）%c 输出category的名称<br />
5)-%m及s是日志消息本身,%n是换行符。<br />
当前在模式字符串中你可以嵌入任何想要输出的字符。<br />
模式字符串中的模式如下：<br />
%m:消息本身<br />
%p:消息的层次<br />
%r:从程序开始执行到当前日志产生时的时间间隔（微秒）<br />
%c:输出当前日志动作所在的category名称。例如：如果category名称是"a.b.c","%c{2}"将会输出"b.c". {2}意谓着输出&#8220;以点分隔开的category名称的后两个组件&#8221;,如果 {n}没有，将会输出整个category名称.<br />
%t:输出当前线程的名称<br />
%x:输出和当前线程相关联的NDC(具体解释见下文),尤其用到像java servlets这样的多客户多线程的应用中。<br />
%n:输出平台相关的换行符。<br />
%%:输出一个"%"字符<br />
%d:输出日志产生时候的日期，当然可以对日期的格式进行定制。例如：%d{HH:mm:ss,SSSS}或者是%d{dd MMM yyyy HH:mm:ss,SSSS},如果没有指定后面的格式，将会输出ISO8601的格式。<br />
%l:输出位置信息，相当于%C.%M(%F:%L)的组合。<br />
%C:输出日志消息产生时所在的类名，如果类名是&#8220;test.page.Class1&#8221;%C{1}表示输出类名"Class1",%C{2}输出"page.Class1",而%C则输出"test.page.Class1"。<br />
%M:输出日志消息产生时的方法名称<br />
%F:输出日志消息产生时所在的文件名称<br />
%L:输出代码中的行号<br />
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如：<br />
1)%20c：指定输出category的名称，最小的宽度是20，如果category的名称小于20的话，默认的情况下右对齐。<br />
2) %-20c:指定输出category的名称，最小的宽度是20，如果category的名称小于20的话，"-"号指定左对齐。<br />
3) %.30c:指定输出category的名称，最大的宽度是30，如果category的名称大于30的话，就会将左边多出的字符截掉，但小于30的话也不会有空格。<br />
4)%20.30c:如果category的名称小于20就补空格，并且右对齐，如果其名称长于30字符，就从左边交远销出的字符截掉。<br />
4)%20.30c:<br />
<br />
<br />
<br />
第五部分 Log4j中附件器及相关的键值参数<br />
1.ConsoleAppender选项<br />
Threshold=WARN:指定日志消息的输出最低层次。<br />
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />
Target=System.err：默认情况下是：System.out,指定输出控制台<br />
2.FileAppender 选项<br />
Threshold=WARN:指定日志消息的输出最低层次。<br />
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />
File=mylog.txt:指定消息输出到mylog.txt文件。<br />
Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。<br />
3.RollingFileAppender 选项<br />
Threshold=WARN:指定日志消息的输出最低层次。<br />
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />
File=mylog.txt:指定消息输出到mylog.txt文件。<br />
Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。<br />
MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时，将会自动滚动，即将原来的内容移到mylog.log.1文件。<br />
MaxBackupIndex=2:指定可以产生的滚动文件的最大数。<br />
4.DailyRollingFileAppender 选项<br />
Threshold=WARN:指定日志消息的输出最低层次。<br />
ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。<br />
File=mylog.txt:指定消息输出到mylog.txt文件。<br />
Append=false:默认值是true,即将消息增加到指定文件中，false指将消息覆盖指定的文件内容。<br />
DatePattern='.'yyyy-ww:每周滚动一次文件，即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下：<br />
1)'.'yyyy-MM: 每月<br />
2)'.'yyyy-ww: 每周<br />
3)'.'yyyy-MM-dd: 每天<br />
4)'.'yyyy-MM-dd-a: 每天两次<br />
5)'.'yyyy-MM-dd-HH: 每小时<br />
6)'.'yyyy-MM-dd-HH-mm: 每分钟<br />
5.PatternLayout 选项<br />
ConversionPattern=%m%n :指定怎样格式化指定的消息。<br />
6.HTMLLayout 选项<br />
LocationInfo=true:默认值是false,输出java文件名称和行号<br />
Title=my app file: 默认值是 Log4J Log Messages.<br />
7.XMLLayout 选项<br />
LocationInfo=true:默认值是false,输出java文件和行号<br />
<br />
第六部分 Log4j配置案例解析<br />
#log4j.debug=true<br />
#log4j.disable=fatal<br />
#log4j.additivity.TestLogging=false<br />
<br />
log4j.rootCategory=, dest1<br />
log4j.category.TestLogging=DEBUG, dest1<br />
log4j.appender.dest1=org.apache.log4j.ConsoleAppender<br />
#log4j.appender.dest1.layout=org.apache.log4j.SimpleLayout<br />
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.dest1.layout.ConversionPattern=%-5p %l %x: %m%n<br />
<br />
<br />
!----------------------####### END OF PROPERTIES #######----------------------!<br />
<br />
<br />
##############################################################<br />
# Below I document in more detail how to write a log4j configuration file. #<br />
# SELECTIVELY copy lines beginning with #, paste and uncomment them above. #<br />
##############################################################<br />
<br />
!-----------------------------------------------------------------------------!<br />
! PLACE THIS FILE ANYWHERE IN CLASSPATH !<br />
! Appenders are additive by default. !<br />
! Priorities are inherited until overridden in a category. !<br />
! In ${property_key}, the value of the key can be defined as a system !<br />
! property or in this file itself. System properties are searched first and !<br />
! then this file. !<br />
!-----------------------------------------------------------------------------!<br />
<br />
<br />
<br />
!-----------------------------------------------------------------------------!<br />
! Configure log4j's operation at the meta level !<br />
!-----------------------------------------------------------------------------!<br />
! Observe log4j parsing this file<br />
#log4j.debug=true<br />
! Set this to false for log4j to actually obey the log4j.disable property(next)<br />
#log4j.disableOverride=false<br />
! Disable all logging in all categories for messages with priority equal to<br />
! or lower than the one given here<br />
#log4j.disable=INFO<br />
<br />
<br />
<br />
!-----------------------------------------------------------------------------!<br />
! Configure categories (loggers) !<br />
!-----------------------------------------------------------------------------!<br />
<br />
! ROOT CATEGORY (Usually sufficient to set this one only)<br />
! Here, logs messages with priority DEBUG (default) or higher<br />
#log4j.rootCategory=, dest1<br />
! Or,<br />
#log4j.rootCategory=debug, dest1, dest2<br />
<br />
! YOUR CATEGORIES (to customize logging per class/pkg/project/etc)<br />
! Here, overrides ancestor's priority and makes it WARN or higher for this cat.<br />
#log4j.category.TestLogging=WARN, dest3<br />
! Or,<br />
#log4j.category.TestLogging=DEBUG, dest3<br />
<br />
!--------DON'T DO THIS!!! APPENDERS ARE ADDITIVE BY DEFAULT!!!----!<br />
! It will write the same log message TWICE to dest1. Once for root, then for !<br />
! this category. !<br />
!#log4j.category.TestLogging=DEBUG, dest1, dest3 !<br />
! If you DO NOT want additivity for this category, say so !<br />
!#log4j.additivity.TestLogging=false !<br />
!-----------------------------------------------------------------------------!<br />
<br />
<br />
<br />
!-----------------------------------------------------------------------------!<br />
! Configure appenders (log destinations/targets) and their options !<br />
!-----------------------------------------------------------------------------!<br />
<br />
! WRITE TO CONSOLE (stdout or stderr)<br />
#log4j.appender.dest1=org.apache.log4j.ConsoleAppender<br />
#log4j.appender.dest1.ImmediateFlush=true<br />
<br />
! WRITE LOG TO A FILE, ROLL THE FILE AFTER SOME SIZE<br />
#log4j.appender.dest2=org.apache.log4j.RollingFileAppender<br />
! This appender will only log messages with priority equal to or higher than<br />
! the one specified here<br />
#log4j.appender.dest2.Threshold=ERROR<br />
! Specify the file name (${property_key} gets substituted with its value)<br />
#log4j.appender.dest2.File=${java.home}/log4j.log<br />
! Don't append, overwrite<br />
#log4j.appender.dest2.Append=false<br />
! Control the maximum log file size<br />
#log4j.appender.dest2.MaxFileSize=100KB<br />
! Keep backup file(s) (backups will be in filename.1, .2 etc.)<br />
#log4j.appender.dest2.MaxBackupIndex=2<br />
<br />
! WRITE LOG TO A FILE, ROLL THE FILE EVERY WEEK<br />
#log4j.appender.dest3=org.apache.log4j.DailyRollingFileAppender<br />
! Specify the file name<br />
#log4j.appender.dest3.File=log4TestLogging2.html<br />
! Control the maximum log file size<br />
#log4j.appender.dest3.MaxFileSize=300KB<br />
! Rollover log file at the start of each week<br />
#log4j.appender.dest3.DatePattern='.'yyyy-ww<br />
<br />
<br />
<br />
!-----------------------------------------------------------------------------!<br />
! Configure appender layouts (log formats) and their options !<br />
!-----------------------------------------------------------------------------!<br />
<br />
! USE SIMPLE LOG FORMAT (e.g. INFO - your log message)<br />
#log4j.appender.dest1.layout=org.apache.log4j.SimpleLayout<br />
<br />
! USE A C PRINTF STYLE PATTERN TO FORMAT LOG MESSAGE<br />
#log4j.appender.dest1.layout=org.apache.log4j.PatternLayout<br />
! For a pattern layout, specify the pattern (Default is %m%n which is fastest)<br />
#log4j.appender.dest1.layout.ConversionPattern=%-5p: %m%n<br />
! Or,<br />
#log4j.appender.dest1.layout.ConversionPattern=%-5p %6.10r[%t]%x(%F:%L) - %m%n<br />
<br />
#log4j.appender.dest2.layout=org.apache.log4j.PatternLayout<br />
#log4j.appender.dest2.layout.ConversionPattern=[%d{ISO8601}]%5p%6.6r[%t]%x(%F:%L) - %m%n<br />
! Or, (the pattern below will slow down your app)<br />
#log4j.appender.dest2.layout.ConversionPattern=[%d{yyyy-mm-dd hh:mm},%6.6r]%-5p[%t]%x(%F:%L) - %m%n<br />
<br />
<br />
! FORMAT LOG MESSAGES IN THE FORM OF AN HTML TABLE<br />
#log4j.appender.dest3.layout=org.apache.log4j.HTMLLayout<br />
! Include Java file name and line number (Default is false)<br />
#log4j.appender.dest3.layout.LocationInfo=true<br />
! Set <br />
<img src ="http://www.blogjava.net/freiberg/aggbug/153765.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-10-18 09:39 <a href="http://www.blogjava.net/freiberg/archive/2007/10/18/153765.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简要介绍一下学习web开发的过程和几本书</title><link>http://www.blogjava.net/freiberg/archive/2007/09/19/146545.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Wed, 19 Sep 2007 09:23:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/19/146545.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/146545.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/19/146545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/146545.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/146545.html</trackback:ping><description><![CDATA[我结合自己的学习过程，介绍一下个人认为的学习web的大体思路，只是一家之言，错误之处请各位高手指出，强烈欢迎批评。<br />
1.首先要先学习java，这是使用jsp的基础，我当时是结合c++去学习的java，对比着学的。推荐大家看一下《Think in java》,不过最好是稍微入门后看。然后编一下java的程序，熟悉java语言。<br />
2.学习servlet和jsp，这两者不要分开学，因为两者是相同的东西，只不过用到的地方不同，然后摸清javabean，这样就可以做一些小项目了,了解mvc机制。推荐看《servlet/jsp核心编程》。<br />
3.然后要对协议有了解，《tcp/ip详解》一，二，三卷，号称圣经的书。<br />
4.学习一些现在主流的框架，struts我看的是《精通struts》，spring是《spring in action》由于我也在学习的过程中，所以不好提什么建议，然后我觉得就该看一下持久层框架，现在比较流行的是hibernate吧，我看的是《深入浅出hibernate》<br />
5.最后应该是ejb了，还没有学，只是有个概念。<br />
在学的过程中，我认为主要是要培养自己面向对象的概念，和对系统架构的了解，这样在可以对项目进行把握。<br />
还有要学习的是xml，sql等等这都是基础我就不多说了。<br />
<img src ="http://www.blogjava.net/freiberg/aggbug/146545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-19 17:23 <a href="http://www.blogjava.net/freiberg/archive/2007/09/19/146545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java用于精确计算的类</title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145815.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 05:01:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145815.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145815.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145815.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145815.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145815.html</trackback:ping><description><![CDATA[/*<br />
&nbsp;* 创建日期 2004-10-14<br />
&nbsp;*<br />
&nbsp;* 如果需要精确计算,非要用String来够造BigDecimal不可<br />
&nbsp;*/<br />
package com.lims.actions.testqc.comm;
<p><font color="#008000">/**<br />
&nbsp;* @author Jstar<br />
&nbsp;*<br />
&nbsp;* <br />
&nbsp;* 窗口 &gt; 首选项 &gt; Java &gt; 代码生成 &gt; 代码和注释<br />
&nbsp;*/</font><br />
import java.math.BigDecimal;</p>
<p><font color="#008000">/**<br />
* 由于Java的简单类型不能够精确的对浮点数进行运算，这个工具类提供精<br />
* 确的浮点数运算，包括加减乘除和四舍五入。<br />
*/</font></p>
<p><font color="#008000">public class</font> Arith {</p>
<p>&nbsp;//默认除法运算精度</p>
<p>&nbsp;private static final int DEF_DIV_SCALE = 10;</p>
<p>&nbsp;//这个类不能实例化</p>
<p>&nbsp;private Arith() {</p>
<p>&nbsp;}</p>
<p><font color="#008000">&nbsp;/**<br />
&nbsp;<br />
&nbsp; * 提供精确的加法运算。<br />
&nbsp;<br />
&nbsp; * @param v1 被加数<br />
&nbsp;<br />
&nbsp; * @param v2 加数<br />
&nbsp;<br />
&nbsp; * @return 两个参数的和<br />
&nbsp;<br />
&nbsp; */</font></p>
<p>&nbsp;public static double add(double v1, double v2) {</p>
<p>&nbsp;&nbsp;bigdecimal b1 = new BigDecimal(Double.toString(v1));</p>
<p>&nbsp;&nbsp;bigdecimal b2 = new BigDecimal(Double.toString(v2));</p>
<p>&nbsp;&nbsp;return b1.add(b2).doubleValue();</p>
<p>&nbsp;}</p>
<p><font color="#008000">&nbsp;/**<br />
&nbsp; * 提供精确的减法运算。<br />
&nbsp; * @param v1 被减数<br />
&nbsp; * @param v2 减数<br />
&nbsp; * @return 两个参数的差<br />
&nbsp; */</font></p>
<p>&nbsp;public static double sub(double v1, double v2) {</p>
<p>&nbsp;&nbsp;bigdecimal b1 = new BigDecimal(Double.toString(v1));</p>
<p>&nbsp;&nbsp;bigdecimal b2 = new BigDecimal(Double.toString(v2));</p>
<p>&nbsp;&nbsp;return b1.subtract(b2).doubleValue();</p>
<p>&nbsp;}</p>
<p><font color="#008000">&nbsp;/**<br />
&nbsp;<br />
&nbsp; * 提供精确的乘法运算。<br />
&nbsp;<br />
&nbsp; * @param v1 被乘数<br />
&nbsp;<br />
&nbsp; * @param v2 乘数<br />
&nbsp;<br />
&nbsp; * @return 两个参数的积<br />
&nbsp;<br />
&nbsp; */</font></p>
<p>&nbsp;public static double mul(double v1, double v2) {</p>
<p>&nbsp;&nbsp;bigdecimal b1 = new BigDecimal(Double.toString(v1));</p>
<p>&nbsp;&nbsp;bigdecimal b2 = new BigDecimal(Double.toString(v2));</p>
<p>&nbsp;&nbsp;return b1.multiply(b2).doubleValue();</p>
<p>&nbsp;}</p>
<p><font color="#008000">&nbsp;/**<br />
&nbsp;<br />
&nbsp; * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到<br />
&nbsp;<br />
&nbsp; * 小数点以后10位，以后的数字四舍五入。<br />
&nbsp;<br />
&nbsp; * @param v1 被除数<br />
&nbsp;<br />
&nbsp; * @param v2 除数<br />
&nbsp;<br />
&nbsp; * @return 两个参数的商<br />
&nbsp;<br />
&nbsp; */</font></p>
<p>&nbsp;public static double div(double v1, double v2) {</p>
<p>&nbsp;&nbsp;return div(v1, v2, DEF_DIV_SCALE);</p>
<p>&nbsp;}</p>
<p><font color="#008000">&nbsp;/**<br />
&nbsp;<br />
&nbsp; * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指<br />
&nbsp;<br />
&nbsp; * 定精度，以后的数字四舍五入。<br />
&nbsp;<br />
&nbsp; * @param v1 被除数<br />
&nbsp;<br />
&nbsp; * @param v2 除数<br />
&nbsp;<br />
&nbsp; * @param scale 表示表示需要精确到小数点以后几位。<br />
&nbsp;<br />
&nbsp; * @return 两个参数的商<br />
&nbsp;<br />
&nbsp; */</font></p>
<p>&nbsp;public static double div(double v1, double v2, int scale) {</p>
<p>&nbsp;&nbsp;if (scale &lt; 0) {</p>
<p>&nbsp;&nbsp;&nbsp;throw new IllegalArgumentException("The scale must be a positive integer or zero");</p>
<p>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;bigdecimal b1 = new BigDecimal(Double.toString(v1));</p>
<p>&nbsp;&nbsp;bigdecimal b2 = new BigDecimal(Double.toString(v2));</p>
<p>&nbsp;&nbsp;return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();</p>
<p>&nbsp;}</p>
<p><font color="#008000">&nbsp;/**<br />
&nbsp;<br />
&nbsp; * 提供精确的小数位四舍五入处理。<br />
&nbsp;<br />
&nbsp; * @param v 需要四舍五入的数字<br />
&nbsp;<br />
&nbsp; * @param scale 小数点后保留几位<br />
&nbsp;<br />
&nbsp; * @return 四舍五入后的结果<br />
&nbsp;<br />
&nbsp; */</font></p>
<p>&nbsp;public static double round(double v, int scale) {</p>
<p>&nbsp;&nbsp;if (scale &lt; 0) {</p>
<p>&nbsp;&nbsp;&nbsp;throw new IllegalArgumentException("The scale must be a positive integer or zero");</p>
<p>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;bigdecimal b = new BigDecimal(Double.toString(v));</p>
<p>&nbsp;&nbsp;bigdecimal one = new BigDecimal("1");</p>
<p>&nbsp;&nbsp;return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();</p>
<p>&nbsp;}</p>
<p>};<br />
</p>
<img src ="http://www.blogjava.net/freiberg/aggbug/145815.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 13:01 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145815.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】一篇关于web.xml配置的详细说明 </title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145814.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 05:01:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145814.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145814.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145814.html</trackback:ping><description><![CDATA[1 定义头和根元素<br />
<br />
部署描述符文件就像所有XML文件一样，必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。<br />
DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本（如2.2或2.3）并指定管理此文件其余部分内容的语法的DTD(Document Type Definition，文档类型定义)。<br />
所有部署描述符文件的顶层（根）元素为web-app。请注意，XML元素不像HTML，他们是大小写敏感的。因此，web-App和WEB-APP都是不合法的，web-app必须用小写。<br />
<br />
2 部署描述符文件内的元素次序<br />
<br />
XML 元素不仅是大小写敏感的，而且它们还对出现在其他元素中的次序敏感。例如，XML头必须是文件中的第一项，DOCTYPE声明必须是第二项，而web- app元素必须是第三项。在web-app元素内，元素的次序也很重要。服务器不一定强制要求这种次序，但它们允许（实际上有些服务器就是这样做的）完全拒绝执行含有次序不正确的元素的Web应用。这表示使用非标准元素次序的web.xml文件是不可移植的。<br />
下面的列表给出了所有可直接出现在web-app元素内的合法元素所必需的次序。例如，此列表说明servlet元素必须出现在所有servlet-mapping元素之前。请注意，所有这些元素都是可选的。因此，可以省略掉某一元素，但不能把它放于不正确的位置。<br />
l icon icon元素指出IDE和GUI工具用来表示Web应用的一个和两个图像文件的位置。<br />
l display-name display-name元素提供GUI工具可能会用来标记这个特定的Web应用的一个名称。<br />
l description description元素给出与此有关的说明性文本。<br />
l context-param context-param元素声明应用范围内的初始化参数。<br />
l filter 过滤器元素将一个名字与一个实现javax.servlet.Filter接口的类相关联。<br />
l filter-mapping 一旦命名了一个过滤器，就要利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。<br />
l listener servlet API的版本2.3增加了对事件监听程序的支持，事件监听程序在建立、修改和删除会话或servlet环境时得到通知。Listener元素指出事件监听程序类。<br />
l servlet 在向servlet或JSP页面制定初始化参数或定制URL时，必须首先命名servlet或JSP页面。Servlet元素就是用来完成此项任务的。<br />
l servlet-mapping 服务器一般为servlet提供一个缺省的URL：<a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/ServletName</font></a><font size="2">。但是，常常会更改这个URL，以便servlet可以访问初始化参数或更容易地处理相对URL。在更改缺省URL时，使用servlet-mapping元素。<br />
l session-config 如果某个会话在一定时间内未被访问，服务器可以抛弃它以节省内存。可通过使用HttpSession的setMaxInactiveInterval方法明确设置单个会话对象的超时值，或者可利用session-config元素制定缺省超时值。<br />
l mime-mapping 如果Web应用具有想到特殊的文件，希望能保证给他们分配特定的MIME类型，则mime-mapping元素提供这种保证。<br />
l welcom-file-list welcome-file-list元素指示服务器在收到引用一个目录名而不是文件名的URL时，使用哪个文件。<br />
l error-page error-page元素使得在返回特定HTTP状态代码时，或者特定类型的异常被抛出时，能够制定将要显示的页面。<br />
l taglib taglib元素对标记库描述符文件（Tag Libraryu Descriptor file）指定别名。此功能使你能够更改TLD文件的位置，而不用编辑使用这些文件的JSP页面。<br />
l resource-env-ref resource-env-ref元素声明与资源相关的一个管理对象。<br />
l resource-ref resource-ref元素声明一个资源工厂使用的外部资源。<br />
l security-constraint security-constraint元素制定应该保护的URL。它与login-config元素联合使用<br />
l login-config 用login-config元素来指定服务器应该怎样给试图访问受保护页面的用户授权。它与sercurity-constraint元素联合使用。<br />
l security-role security-role元素给出安全角色的一个列表，这些角色将出现在servlet元素内的security-role-ref元素的role-name子元素中。分别地声明角色可使高级IDE处理安全信息更为容易。<br />
l env-entry env-entry元素声明Web应用的环境项。<br />
l ejb-ref ejb-ref元素声明一个EJB的主目录的引用。<br />
l ejb-local-ref ejb-local-ref元素声明一个EJB的本地主目录的应用。<br />
<br />
3 分配名称和定制的UL<br />
<br />
在web.xml中完成的一个最常见的任务是对servlet或JSP页面给出名称和定制的URL。用servlet元素分配名称，使用servlet-mapping元素将定制的URL与刚分配的名称相关联。<br />
3.1 分配名称<br />
为了提供初始化参数，对servlet或JSP页面定义一个定制URL或分配一个安全角色，必须首先给servlet或JSP页面一个名称。可通过 servlet元素分配一个名称。最常见的格式包括servlet-name和servlet-class子元素（在web-app元素内），如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt; <br />
这表示位于WEB-INF/classes/moreservlets/TestServlet的servlet已经得到了注册名Test。给 servlet一个名称具有两个主要的含义。首先，初始化参数、定制的URL模式以及其他定制通过此注册名而不是类名引用此servlet。其次,可在 URL而不是类名中使用此名称。因此，利用刚才给出的定义，URL </font><a href="http://host/webAppPrefix/servlet/Test" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/Test</font></a><font size="2"> 可用于 </font><a href="http://host/webAppPrefix/servlet/moreservlets.TestServlet" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/moreservlets.TestServlet</font></a><font size="2"> 的场所。<br />
请记住：XML元素不仅是大小写敏感的，而且定义它们的次序也很重要。例如，web-app元素内所有servlet元素必须位于所有servlet- mapping元素（下一小节介绍）之前，而且还要位于5.6节和5.11节讨论的与过滤器或文档相关的元素（如果有的话）之前。类似地，servlet 的servlet-name子元素也必须出现在servlet-class之前。5.2节"部署描述符文件内的元素次序"将详细介绍这种必需的次序。<br />
例如，程序清单5-1给出了一个名为TestServlet的简单servlet，它驻留在moreservlets程序包中。因为此servlet是扎根在一个名为deployDemo的目录中的Web应用的组成部分，所以TestServlet.class放在deployDemo/WEB- INF/classes/moreservlets中。程序清单5-2给出将放置在deployDemo/WEB-INF/内的web.xml文件的一部分。此web.xml文件使用servlet-name和servlet-class元素将名称Test与TestServlet.class相关联。图 5-1和图5-2分别显示利用缺省URL和注册名调用TestServlet时的结果。<br />
<br />
程序清单5-1 TestServlet.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
<br />
/** Simple servlet used to illustrate servlet naming<br />
* and custom URLs.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/" target="_blank"><font color="#1d58d1" size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class TestServlet extends HttpServlet {<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType("text/html");<br />
PrintWriter out = response.getWriter();<br />
String uri = request.getRequestURI();<br />
out.println(ServletUtilities.headWithTitle("Test Servlet") +<br />
"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />
"&lt;H2&gt;URI: " + uri + "&lt;/H2&gt;\n" +<br />
"&lt;/BODY&gt;&lt;/HTML&gt;");<br />
}<br />
}<br />
<br />
<br />
程序清单5-2 web.xml（说明servlet名称的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- &#8230; --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- &#8230; --&gt;<br />
&lt;/web-app&gt;<br />
<br />
3.2 定义定制的URL<br />
大多数服务器具有一个缺省的serlvet URL：<br />
</font><a href="http://host/webAppPrefix/servlet/packageName.ServletName" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/packageName.ServletName</font></a><font size="2">。虽然在开发中使用这个URL很方便，但是我们常常会希望另一个URL用于部署。例如，可能会需要一个出现在Web应用顶层的URL（如，http: //host/webAppPrefix/Anyname），并且在此URL中没有servlet项。位于顶层的URL简化了相对URL的使用。此外，对许多开发人员来说，顶层URL看上去比更长更麻烦的缺省URL更简短。<br />
事实上，有时需要使用定制的URL。比如，你可能想关闭缺省URL映射，以便更好地强制实施安全限制或防止用户意外地访问无初始化参数的servlet。如果你禁止了缺省的URL，那么你怎样访问servlet呢？这时只有使用定制的URL了。<br />
为了分配一个定制的URL，可使用servlet-mapping元素及其servlet-name和url-pattern子元素。Servlet- name元素提供了一个任意名称，可利用此名称引用相应的servlet；url-pattern描述了相对于Web应用的根目录的URL。url- pattern元素的值必须以斜杠（/）起始。<br />
下面给出一个简单的web.xml摘录，它允许使用URL </font><a href="http://host/webAppPrefix/UrlTest" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/UrlTest</font></a><font size="2">而不是</font><a href="http://host/webAppPrefix/servlet/Test" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/Test</font></a><font size="2">或<br />
http: //host/webAppPrefix/servlet/moreservlets.TestServlet。请注意，仍然需要XML头、 DOCTYPE声明以及web-app封闭元素。此外，可回忆一下，XML元素出现地次序不是随意的。特别是，需要把所有servlet元素放在所有 servlet-mapping元素之前。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.TestServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
URL模式还可以包含通配符。例如，下面的小程序指示服务器发送所有以Web应用的URL前缀开始，以..asp结束的请求到名为BashMS的servlet。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;msUtils.ASPTranslator&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;BashMS&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/*.asp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
3.3 命名JSP页面<br />
因为JSP页面要转换成sevlet，自然希望就像命名servlet一样命名JSP页面。毕竟，JSP页面可能会从初始化参数、安全设置或定制的URL中受益，正如普通的serlvet那样。虽然JSP页面的后台实际上是servlet这句话是正确的，但存在一个关键的猜疑：即，你不知道JSP页面的实际类名（因为系统自己挑选这个名字）。因此，为了命名JSP页面，可将jsp-file元素替换为servlet-calss元素，如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Test&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
命名JSP页面的原因与命名servlet的原因完全相同：即为了提供一个与定制设置（如，初始化参数和安全设置）一起使用的名称，并且，以便能更改激活 JSP页面的URL（比方说，以便多个URL通过相同页面得以处理，或者从URL中去掉.jsp扩展名）。但是，在设置初始化参数时，应该注意，JSP页面是利用jspInit方法，而不是init方法读取初始化参数的。<br />
例如，程序清单5-3给出一个名为TestPage.jsp的简单JSP页面，它的工作只是打印出用来激活它的URL的本地部分。TestPage.jsp放置在deployDemo应用的顶层。程序清单5-4给出了用来分配一个注册名PageName，然后将此注册名与</font><a href="http://host/webAppPrefix/UrlTest2/anything" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/UrlTest2/anything</font></a><font size="2"> 形式的URL相关联的web.xml文件（即，deployDemo/WEB-INF/web.xml）的一部分。<br />
<br />
程序清单5-3 TestPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;<br />
JSP Test Page<br />
&lt;/TITLE&gt;<br />
&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR="#FDF5E6"&gt;<br />
&lt;H2&gt;URI: &lt;%= request.getRequestURI() %&gt;&lt;/H2&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;<br />
<br />
<br />
程序清单5-4 web.xml（说明JSP页命名的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/TestPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
4 禁止激活器servlet<br />
<br />
对servlet或JSP页面建立定制URL的一个原因是，这样做可以注册从 init（servlet）或jspInit（JSP页面）方法中读取得初始化参数。但是，初始化参数只在是利用定制URL模式或注册名访问 servlet或JSP页面时可以使用，用缺省URL </font><a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/ServletName</font></a><font size="2"> 访问时不能使用。因此，你可能会希望关闭缺省URL，这样就不会有人意外地调用初始化servlet了。这个过程有时称为禁止激活器servlet，因为多数服务器具有一个用缺省的servlet URL注册的标准servlet，并激活缺省的URL应用的实际servlet。<br />
有两种禁止此缺省URL的主要方法：<br />
l 在每个Web应用中重新映射/servlet/模式。<br />
l 全局关闭激活器servlet。<br />
重要的是应该注意到，虽然重新映射每个Web应用中的/servlet/模式比彻底禁止激活servlet所做的工作更多，但重新映射可以用一种完全可移植的方式来完成。相反，全局禁止激活器servlet完全是针对具体机器的，事实上有的服务器（如ServletExec）没有这样的选择。下面的讨论对每个Web应用重新映射/servlet/ URL模式的策略。后面提供在Tomcat中全局禁止激活器servlet的详细内容。<br />
4.1 重新映射/servlet/URL模式<br />
在一个特定的Web应用中禁止以</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/</font></a><font size="2"> 开始的URL的处理非常简单。所需做的事情就是建立一个错误消息servlet，并使用前一节讨论的url-pattern元素将所有匹配请求转向该 servlet。只要简单地使用：<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
作为servlet-mapping元素中的模式即可。<br />
例如，程序清单5-5给出了将SorryServlet servlet（程序清单5-6）与所有以</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/</font></a><font size="2"> 开头的URL相关联的部署描述符文件的一部分。<br />
<br />
程序清单5-5 web.xml（说明JSP页命名的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Sorry&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.SorryServlet&lt;/servlet-class&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; Sorry &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
程序清单5-6 SorryServlet.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
<br />
/** Simple servlet used to give error messages to<br />
* users who try to access default servlet URLs<br />
* (i.e., </font><a href="http://host/webAppPrefix/servlet/ServletName" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/ServletName</font></a><font size="2">)<br />
* in Web applications that have disabled this<br />
* behavior.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/" target="_blank"><font color="#1d58d1" size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class SorryServlet extends HttpServlet {<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType("text/html");<br />
PrintWriter out = response.getWriter();<br />
String title = "Invoker Servlet Disabled.";<br />
out.println(ServletUtilities.headWithTitle(title) +<br />
"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />
"&lt;H2&gt;" + title + "&lt;/H2&gt;\n" +<br />
"Sorry, access to servlets by means of\n" +<br />
"URLs that begin with\n" +<br />
"</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/</font></a><font size="2">\n" +<br />
"has been disabled.\n" + <br />
"&lt;/BODY&gt;&lt;/HTML&gt;");<br />
}<br />
<br />
public void doPost(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
doGet(request, response);<br />
}<br />
}<br />
<br />
<br />
4.2 全局禁止激活器：Tomcat<br />
Tomcat 4中用来关闭缺省URL的方法与Tomcat 3中所用的很不相同。下面介绍这两种方法：<br />
1．禁止激活器： Tomcat 4<br />
Tomcat 4用与前面相同的方法关闭激活器servlet，即利用web.xml中的url-mapping元素进行关闭。不同之处在于Tomcat使用了放在 install_dir/conf中的一个服务器专用的全局web.xml文件，而前面使用的是存放在每个Web应用的WEB-INF目录中的标准 web.xml文件。<br />
因此，为了在Tomcat 4中关闭激活器servlet，只需在install_dir/conf/web.xml中简单地注释出/servlet/* URL映射项即可，如下所示：<br />
&lt;!-- <br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;invoker&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/servlet/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
--&gt;<br />
再次提醒，应该注意这个项是位于存放在install_dir/conf的Tomcat专用的web.xml文件中的，此文件不是存放在每个Web应用的WEB-INF目录中的标准web.xml。<br />
2．禁止激活器：Tomcat3<br />
在Apache Tomcat的版本3中，通过在install_dir/conf/server.xml中注释出InvokerInterceptor项全局禁止缺省 servlet URL。例如，下面是禁止使用缺省servlet URL的server.xml文件的一部分。<br />
&lt;!-- <br />
&lt;RequsetInterceptor <br />
className="org.apache.tomcat.request.InvokerInterceptor"<br />
debug="0" prefix="/servlet/" /&gt;<br />
--&gt;<br />
<br />
5 初始化和预装载servlet与JSP页面<br />
<br />
这里讨论控制servlet和JSP页面的启动行为的方法。特别是，说明了怎样分配初始化参数以及怎样更改服务器生存期中装载servlet和JSP页面的时刻。<br />
5.1 分配servlet初始化参数<br />
利用init-param元素向servlet提供初始化参数，init-param元素具有param-name和param-value子元素。例如，在下面的例子中，如果initServlet servlet是利用它的注册名（InitTest）访问的，它将能够从其方法中调用getServletConfig(). getInitParameter("param1")获得"Value 1"，调用getServletConfig().getInitParameter("param2")获得"2"。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;param1&lt;/param-name&gt;<br />
&lt;param-value&gt;value1&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;param2&lt;/param-name&gt;<br />
&lt;param-value&gt;2&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
在涉及初始化参数时，有几点需要注意：<br />
l 返回值。GetInitParameter的返回值总是一个String。因此，在前一个例子中，可对param2使用Integer.parseInt获得一个int。<br />
l JSP中的初始化。JSP页面使用jspInit而不是init。JSP页面还需要使用jsp-file元素代替servlet-class。<br />
l 缺省URL。初始化参数只在通过它们的注册名或与它们注册名相关的定制URL模式访问Servlet时可以使用。因此，在这个例子中，param1和 param2初始化参数将能够在使用URL </font><a href="http://host/webAppPrefix/servlet/InitTest" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/InitTest</font></a><font size="2"> 时可用，但在使用URL </font><a href="http://host/webAppPrefix/servlet/myPackage.InitServlet" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/myPackage.InitServlet</font></a><font size="2"> 时不能使用。<br />
例如，程序清单5-7给出一个名为InitServlet的简单servlet，它使用init方法设置firstName和emailAddress字段。程序清单5-8给出分配名称InitTest给servlet的web.xml文件。<br />
程序清单5-7 InitServlet.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
<br />
/** Simple servlet used to illustrate servlet<br />
* initialization parameters.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/" target="_blank"><font color="#1d58d1" size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class InitServlet extends HttpServlet {<br />
private String firstName, emailAddress;<br />
<br />
public void init() {<br />
ServletConfig config = getServletConfig();<br />
firstName = config.getInitParameter("firstName");<br />
emailAddress = config.getInitParameter("emailAddress");<br />
}<br />
<br />
public void doGet(HttpServletRequest request,<br />
HttpServletResponse response)<br />
throws ServletException, IOException {<br />
response.setContentType("text/html");<br />
PrintWriter out = response.getWriter();<br />
String uri = request.getRequestURI();<br />
out.println(ServletUtilities.headWithTitle("Init Servlet") +<br />
"&lt;BODY BGCOLOR=\"#FDF5E6\"&gt;\n" +<br />
"&lt;H2&gt;Init Parameters:&lt;/H2&gt;\n" +<br />
"&lt;UL&gt;\n" +<br />
"&lt;LI&gt;First name: " + firstName + "\n" +<br />
"&lt;LI&gt;Email address: " + emailAddress + "\n" +<br />
"&lt;/UL&gt;\n" + <br />
"&lt;/BODY&gt;&lt;/HTML&gt;");<br />
}<br />
}<br />
<br />
<br />
程序清单5-8 web.xml（说明初始化参数的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitTest&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;moreservlets.InitServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;firstName&lt;/param-name&gt;<br />
&lt;param-value&gt;Larry&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />
&lt;param-value&gt;</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#69;&#108;&#108;&#105;&#115;&#111;&#110;&#64;&#77;&#105;&#99;&#114;&#111;&#115;&#111;&#102;&#116;&#46;&#99;&#111;&#109;"><font color="#1d58d1" size="2">Ellison@Microsoft.com</font></a><font size="2">&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
5.2 分配JSP初始化参数<br />
给JSP页面提供初始化参数在三个方面不同于给servlet提供初始化参数。<br />
1）使用jsp-file而不是servlet-class。因此，WEB-INF/web.xml文件的servlet元素如下所示：<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;...&lt;/param-name&gt;<br />
&lt;param-value&gt;...&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
...<br />
&lt;/servlet&gt;<br />
2) 几乎总是分配一个明确的URL模式。对servlet，一般相应地使用以</font><a href="http://host/webAppPrefix/servlet/" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/</font></a><font size="2"> 开始的缺省URL。只需记住，使用注册名而不是原名称即可。这对于JSP页面在技术上也是合法的。例如，在上面给出的例子中，可用URL </font><a href="http://host/webAppPrefix/servlet/PageName" target="_blank"><font color="#1d58d1" size="2">http://host/webAppPrefix/servlet/PageName</font></a><font size="2"> 访问RealPage.jsp的对初始化参数具有访问权的版本。但在用于JSP页面时，许多用户似乎不喜欢应用常规的servlet的URL。此外，如果 JSP页面位于服务器为其提供了目录清单的目录中（如，一个既没有index.html也没有index.jsp文件的目录），则用户可能会连接到此 JSP页面，单击它，从而意外地激活未初始化的页面。因此，好的办法是使用url-pattern（5.3节）将JSP页面的原URL与注册的 servlet名相关联。这样，客户机可使用JSP页面的普通名称，但仍然激活定制的版本。例如，给定来自项目1的servlet定义，可使用下面的 servlet-mapping定义：<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/RealPage.jsp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
3）JSP页使用jspInit而不是init。自动从JSP页面建立的servlet或许已经使用了inti方法。因此，使用JSP声明提供一个init方法是不合法的，必须制定jspInit方法。<br />
为了说明初始化JSP页面的过程，程序清单5-9给出了一个名为InitPage.jsp的JSP页面，它包含一个jspInit方法且放置于 deployDemo Web应用层次结构的顶层。一般，</font><a href="http://host/deployDemo/InitPage.jsp" target="_blank"><font color="#1d58d1" size="2">http://host/deployDemo/InitPage.jsp</font></a><font size="2"> 形式的URL将激活此页面的不具有初始化参数访问权的版本，从而将对firstName和emailAddress变量显示null。但是， web.xml文件（程序清单5-10）分配了一个注册名，然后将该注册名与URL模式/InitPage.jsp相关联。<br />
<br />
程序清单5-9 InitPage.jsp<br />
&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;&lt;TITLE&gt;JSP Init Test&lt;/TITLE&gt;&lt;/HEAD&gt;<br />
&lt;BODY BGCOLOR="#FDF5E6"&gt;<br />
&lt;H2&gt;Init Parameters:&lt;/H2&gt;<br />
&lt;UL&gt;<br />
&lt;LI&gt;First name: &lt;%= firstName %&gt;<br />
&lt;LI&gt;Email address: &lt;%= emailAddress %&gt;<br />
&lt;/UL&gt;<br />
&lt;/BODY&gt;&lt;/HTML&gt;<br />
&lt;%!<br />
private String firstName, emailAddress;<br />
<br />
public void jspInit() {<br />
ServletConfig config = getServletConfig();<br />
firstName = config.getInitParameter("firstName");<br />
emailAddress = config.getInitParameter("emailAddress");<br />
}<br />
%&gt;<br />
<br />
<br />
程序清单5-10 web.xml（说明JSP页面的init参数的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;InitPage&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/InitPage.jsp&lt;/jsp-file&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;firstName&lt;/param-name&gt;<br />
&lt;param-value&gt;Bill&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
&lt;param-name&gt;emailAddress&lt;/param-name&gt;<br />
&lt;param-value&gt;</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#103;&#97;&#116;&#101;&#115;&#64;&#111;&#114;&#97;&#99;&#108;&#101;&#46;&#99;&#111;&#109;"><font color="#1d58d1" size="2">gates@oracle.com</font></a><font size="2">&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt; <br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; InitPage&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/InitPage.jsp&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
5.3 提供应用范围内的初始化参数<br />
一般，对单个地servlet或JSP页面分配初始化参数。指定的servlet或JSP页面利用ServletConfig的getInitParameter方法读取这些参数。但是，在某些情形下，希望提供可由任意servlet或JSP页面借助ServletContext的getInitParameter方法读取的系统范围内的初始化参数。<br />
可利用context-param元素声明这些系统范围内的初始化值。context-param元素应该包含param-name、param-value以及可选的description子元素，如下所示：<br />
&lt;context-param&gt;<br />
&lt;param-name&gt;support-email&lt;/param-name&gt;<br />
&lt;param-value&gt;</font><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#98;&#108;&#97;&#99;&#107;&#104;&#111;&#108;&#101;&#64;&#109;&#121;&#99;&#111;&#109;&#112;&#97;&#110;&#121;&#46;&#99;&#111;&#109;"><font color="#1d58d1" size="2">blackhole@mycompany.com</font></a><font size="2">&lt;/param-value&gt;<br />
&lt;/context-param&gt;<br />
可回忆一下，为了保证可移植性，web.xml内的元素必须以正确的次序声明。但这里应该注意，context-param元素必须出现任意与文档有关的元素（icon、display-name或description）之后及filter、filter-mapping、listener或 servlet元素之前。<br />
5.4 在服务器启动时装载servlet<br />
假如servlet或JSP页面有一个要花很长时间执行的init （servlet）或jspInit（JSP）方法。例如，假如init或jspInit方法从某个数据库或ResourceBundle查找产量。这种情况下，在第一个客户机请求时装载servlet的缺省行为将对第一个客户机产生较长时间的延迟。因此，可利用servlet的load-on- startup元素规定服务器在第一次启动时装载servlet。下面是一个例子。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt; &#8230; &lt;/servlet-name&gt;<br />
&lt;servlet-class&gt; &#8230; &lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />
&lt;load-on-startup/&gt;<br />
&lt;/servlet&gt;<br />
可以为此元素体提供一个整数而不是使用一个空的load-on-startup。想法是服务器应该在装载较大数目的servlet或JSP页面之前装载较少数目的servlet或JSP页面。例如，下面的servlet项（放置在Web应用的WEB-INF目录下的web.xml文件中的web-app元素内）将指示服务器首先装载和初始化SearchServlet，然后装载和初始化由位于Web应用的result目录中的index.jsp文件产生的 servlet。<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Search&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;myPackage.SearchServlet&lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;Results&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;/results/index.jsp&lt;/servlet-class&gt; &lt;!-- Or jsp-file --&gt;<br />
&lt;load-on-startup&gt;2&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;<br />
<br />
6 声明过滤器<br />
<br />
servlet版本2.3引入了过滤器的概念。虽然所有支持servlet API版本2.3的服务器都支持过滤器，但为了使用与过滤器有关的元素，必须在web.xml中使用版本2.3的DTD。<br />
过滤器可截取和修改进入一个servlet或JSP页面的请求或从一个servlet或JSP页面发出的相应。在执行一个servlet或JSP页面之前，必须执行第一个相关的过滤器的doFilter方法。在该过滤器对其FilterChain对象调用doFilter时，执行链中的下一个过滤器。如果没有其他过滤器，servlet或JSP页面被执行。过滤器具有对到来的ServletRequest对象的全部访问权，因此，它们可以查看客户机名、查找到来的cookie等。为了访问servlet或JSP页面的输出，过滤器可将响应对象包裹在一个替身对象（stand-in object）中，比方说把输出累加到一个缓冲区。在调用FilterChain对象的doFilter方法之后，过滤器可检查缓冲区，如有必要，就对它进行修改，然后传送到客户机。<br />
例如，程序清单5-11帝国难以了一个简单的过滤器，只要访问相关的servlet或JSP页面，它就截取请求并在标准输出上打印一个报告（开发过程中在桌面系统上运行时，大多数服务器都可以使用这个过滤器）。<br />
<br />
程序清单5-11 ReportFilter.java<br />
package moreservlets;<br />
<br />
import java.io.*;<br />
import javax.servlet.*;<br />
import javax.servlet.http.*;<br />
import java.util.*;<br />
<br />
/** Simple filter that prints a report on the standard output <br />
* whenever the associated servlet or JSP page is accessed.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/" target="_blank"><font color="#1d58d1" size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class ReportFilter implements Filter {<br />
public void doFilter(ServletRequest request,<br />
ServletResponse response,<br />
FilterChain chain)<br />
throws ServletException, IOException {<br />
HttpServletRequest req = (HttpServletRequest)request;<br />
System.out.println(req.getRemoteHost() +<br />
" tried to access " +<br />
req.getRequestURL() +<br />
" on " + new Date() + ".");<br />
chain.doFilter(request,response);<br />
}<br />
<br />
public void init(FilterConfig config)<br />
throws ServletException {<br />
}<br />
<br />
public void destroy() {}<br />
}<br />
<br />
一旦建立了一个过滤器，可以在web.xml中利用filter元素以及filter-name（任意名称）、file-class（完全限定的类名）和（可选的）init-params子元素声明它。请注意，元素在web.xml的web-app元素中出现的次序不是任意的；允许服务器（但不是必需的）强制所需的次序，并且实际中有些服务器也是这样做的。但这里要注意，所有filter元素必须出现在任意filter-mapping元素之前， filter-mapping元素又必须出现在所有servlet或servlet-mapping元素之前。<br />
例如，给定上述的ReportFilter类，可在web.xml中作出下面的filter声明。它把名称Reporter与实际的类ReportFilter（位于moreservlets程序包中）相关联。<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
一旦命名了一个过滤器，可利用filter-mapping元素把它与一个或多个servlet或JSP页面相关联。关于此项工作有两种选择。<br />
首先，可使用filter-name和servlet-name子元素把此过滤器与一个特定的servlet名（此servlet名必须稍后在相同的 web.xml文件中使用servlet元素声明）关联。例如，下面的程序片断指示系统只要利用一个定制的URL访问名为SomeServletName 的servlet或JSP页面，就运行名为Reporter的过滤器。<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;servlet-name&gt;SomeServletName&lt;/servlet-name&gt;<br />
&lt;/filter-mapping&gt;<br />
其次，可利用filter-name和url-pattern子元素将过滤器与一组servlet、JSP页面或静态内容相关联。例如，相面的程序片段指示系统只要访问Web应用中的任意URL，就运行名为Reporter的过滤器。<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;<br />
例如，程序清单5-12给出了将ReportFilter过滤器与名为PageName的servlet相关联的web.xml文件的一部分。名字 PageName依次又与一个名为TestPage.jsp的JSP页面以及以模式http: //host/webAppPrefix/UrlTest2/ 开头的URL相关联。TestPage.jsp的源代码已经JSP页面命名的谈论在前面的3节"分配名称和定制的URL"中给出。事实上，程序清单5- 12中的servlet和servlet-name项从该节原封不动地拿过来的。给定这些web.xml项，可看到下面的标准输出形式的调试报告（换行是为了容易阅读）。<br />
audit.irs.gov tried to access <br />
</font><a href="http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html" target="_blank"><font color="#1d58d1" size="2">http://mycompany.com/deployDemo/UrlTest2/business/tax-plan.html</font></a><br />
<font size="2">on Tue Dec 25 13:12:29 EDT 2001.<br />
<br />
程序清单5-12 Web.xml（说明filter用法的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;filter&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;filter-class&gt;moresevlets.ReportFilter&lt;/filter-class&gt;<br />
&lt;/filter&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;filter-mapping&gt;<br />
&lt;filter-name&gt;Reporter&lt;/filter-name&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;/filter-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet&gt;<br />
&lt;servlet-name&gt;PageName&lt;/servlet-name&gt;<br />
&lt;jsp-file&gt;/RealPage.jsp&lt;/jsp-file&gt;<br />
&lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt; PageName &lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/UrlTest2/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
7 指定欢迎页<br />
<br />
假如用户提供了一个像http: //host/webAppPrefix/directoryName/ 这样的包含一个目录名但没有包含文件名的URL，会发生什么事情呢？用户能得到一个目录表？一个错误？还是标准文件的内容？如果得到标准文件内容，是 index.html、index.jsp、default.html、default.htm或别的什么东西呢？<br />
Welcome-file-list 元素及其辅助的welcome-file元素解决了这个模糊的问题。例如，下面的web.xml项指出，如果一个URL给出一个目录名但未给出文件名，服务器应该首先试用index.jsp，然后再试用index.html。如果两者都没有找到，则结果有赖于所用的服务器（如一个目录列表）。<br />
&lt;welcome-file-list&gt;<br />
&lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;<br />
&lt;welcome-file&gt;index.html&lt;/welcome-file&gt;<br />
&lt;/welcome-file-list&gt;<br />
虽然许多服务器缺省遵循这种行为，但不一定必须这样。因此，明确地使用welcom-file-list保证可移植性是一种良好的习惯。<br />
<br />
8 指定处理错误的页面<br />
<br />
现在我了解到，你在开发servlet和JSP页面时从不会犯错误，而且你的所有页面是那样的清晰，一般的程序员都不会被它们的搞糊涂。但是，是人总会犯错误的，用户可能会提供不合规定的参数，使用不正确的URL或者不能提供必需的表单字段值。除此之外，其它开发人员可能不那么细心，他们应该有些工具来克服自己的不足。<br />
error-page元素就是用来克服这些问题的。它有两个可能的子元素，分别是：error-code和exception- type。第一个子元素error-code指出在给定的HTTP错误代码出现时使用的URL。第二个子元素excpetion-type指出在出现某个给定的Java异常但未捕捉到时使用的URL。error-code和exception-type都利用location元素指出相应的URL。此 URL必须以/开始。location所指出的位置处的页面可通过查找HttpServletRequest对象的两个专门的属性来访问关于错误的信息，这两个属性分别是：javax.servlet.error.status_code和javax.servlet.error.message。<br />
可回忆一下，在web.xml内以正确的次序声明web-app的子元素很重要。这里只要记住，error-page出现在web.xml文件的末尾附近，servlet、servlet-name和welcome-file-list之后即可。<br />
<br />
8.1 error-code元素<br />
为了更好地了解error-code元素的值，可考虑一下如果不正确地输入文件名，大多数站点会作出什么反映。这样做一般会出现一个404错误信息，它表示不能找到该文件，但几乎没提供更多有用的信息。另一方面，可以试一下在</font><a href="http://www.microsoft.com/" target="_blank"><font color="#1d58d1" size="2">www.microsoft.com</font></a><font size="2">、</font><a href="http://www.ibm.com/" target="_blank"><font color="#1d58d1" size="2">www.ibm.com</font></a><font size="2"> 处或者特别是在</font><a href="http://www.bea.com/" target="_blank"><font color="#1d58d1" size="2">www.bea.com</font></a><font size="2"> 处输出未知的文件名。这是会得出有用的消息，这些消息提供可选择的位置，以便查找感兴趣的页面。提供这样有用的错误页面对于Web应用来说是很有价值得。事实上rm-error-page子元素）。由form-login-page给出的HTML表单必须具有一个j_security_check的 ACTION属性、一个名为j_username的用户名文本字段以及一个名为j_password的口令字段。<br />
例如，程序清单5-19指示服务器使用基于表单的验证。Web应用的顶层目录中的一个名为login.jsp的页面将收集用户名和口令，并且失败的登陆将由相同目录中名为login-error.jsp的页面报告。<br />
<br />
程序清单5-19 web.xml（说明login-config的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;security-constraint&gt; ... &lt;/security-constraint&gt;<br />
&lt;login-config&gt;<br />
&lt;auth-method&gt; FORM &lt;/auth-method&gt;<br />
&lt;form-login-config&gt;<br />
&lt;form-login-page&gt;/login.jsp&lt;/form-login-page&gt;<br />
&lt;form-error-page&gt;/login-error.jsp&lt;/form-error-page&gt;<br />
&lt;/form-login-config&gt;<br />
&lt;/login-config&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
9.2 限制对Web资源的访问<br />
现在，可以指示服务器使用何种验证方法了。"了不起，"你说道，"除非我能指定一个来收到保护的 URL，否则没有多大用处。"没错。指出这些URL并说明他们应该得到何种保护正是security-constriaint元素的用途。此元素在 web.xml中应该出现在login-config的紧前面。它包含是个可能的子元素，分别是：web-resource-collection、 auth-constraint、user-data-constraint和display-name。下面各小节对它们进行介绍。<br />
l web-resource-collection<br />
此元素确定应该保护的资源。所有security-constraint元素都必须包含至少一个web-resource-collection项。此元素由一个给出任意标识名称的web-resource-name元素、一个确定应该保护的URL的url-pattern元素、一个指出此保护所适用的 HTTP命令（GET、POST等，缺省为所有方法）的http-method元素和一个提供资料的可选description元素组成。例如，下面的 Web-resource-collection项（在security-constratint元素内）指出Web应用的proprietary目录中所有文档应该受到保护。<br />
&lt;security-constraint&gt;<br />
&lt;web-resource-coolection&gt;<br />
&lt;web-resource-name&gt;Proprietary&lt;/web-resource-name&gt;<br />
&lt;url-pattern&gt;/propritary/*&lt;/url-pattern&gt;<br />
&lt;/web-resource-coolection&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/security-constraint&gt;<br />
重要的是应该注意到，url-pattern仅适用于直接访问这些资源的客户机。特别是，它不适合于通过MVC体系结构利用 RequestDispatcher来访问的页面，或者不适合于利用类似jsp:forward的手段来访问的页面。这种不匀称如果利用得当的话很有好处。例如，servlet可利用MVC体系结构查找数据，把它放到bean中，发送请求到从bean中提取数据的JSP页面并显示它。我们希望保证决不直接访问受保护的JSP页面，而只是通过建立该页面将使用的bean的servlet来访问它。url-pattern和auth-contraint元素可通过声明不允许任何用户直接访问JSP页面来提供这种保证。但是，这种不匀称的行为可能让开发人员放松警惕，使他们偶然对应受保护的资源提供不受限制的访问。 <br />
l auth-constraint<br />
尽管web-resource-collention元素质出了哪些URL应该受到保护，但是auth-constraint元素却指出哪些用户应该具有受保护资源的访问权。此元素应该包含一个或多个标识具有访问权限的用户类别role- name元素，以及包含（可选）一个描述角色的description元素。例如，下面web.xml中的security-constraint元素部门规定只有指定为Administrator或Big Kahuna（或两者）的用户具有指定资源的访问权。<br />
&lt;security-constraint&gt;<br />
&lt;web-resource-coolection&gt; ... &lt;/web-resource-coolection&gt;<br />
&lt;auth-constraint&gt;<br />
&lt;role-name&gt;administrator&lt;/role-name&gt;<br />
&lt;role-name&gt;kahuna&lt;/role-name&gt;<br />
&lt;/auth-constraint&gt;<br />
&lt;/security-constraint&gt;<br />
重要的是认识到，到此为止，这个过程的可移植部分结束了。服务器怎样确定哪些用户处于任何角色以及它怎样存放用户的口令，完全有赖于具体的系统。<br />
例如，Tomcat使用install_dir/conf/tomcat-users.xml将用户名与角色名和口令相关联，正如下面例子中所示，它指出用户joe（口令bigshot）和jane（口令enaj）属于administrator和kahuna角色。<br />
&lt;tomcat-users&gt;<br />
&lt;user name="joe" password="bigshot" roles="administrator,kahuna" /&gt;<br />
&lt;user name="jane" password="enaj" roles="kahuna" /&gt;<br />
&lt;/tomcat-users&gt;<br />
l user-data-constraint<br />
这个可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素（合法值为NONE、 INTEGRAL或CONFIDENTIAL），并且可选地包含一个description元素。transport-guarantee为NONE值将对所用的通讯协议不加限制。INTEGRAL值表示数据必须以一种防止截取它的人阅读它的方式传送。虽然原理上（并且在未来的HTTP版本中），在 INTEGRAL和CONFIDENTIAL之间可能会有差别，但在当前实践中，他们都只是简单地要求用SSL。例如，下面指示服务器只允许对相关资源做 HTTPS连接：<br />
&lt;security-constraint&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;user-data-constraint&gt;<br />
&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<br />
&lt;/user-data-constraint&gt;<br />
&lt;/security-constraint&gt;<br />
l display-name<br />
security-constraint的这个很少使用的子元素给予可能由GUI工具使用的安全约束项一个名称。<br />
9.3 分配角色名<br />
迄今为止，讨论已经集中到完全由容器（服务器）处理的安全问题之上了。但servlet以及JSP页面也能够处理它们自己的安全问题。<br />
例如，容器可能允许用户从bigwig或bigcheese角色访问一个显示主管人员额外紧贴的页面，但只允许bigwig用户修改此页面的参数。完成这种更细致的控制的一种常见方法是调用HttpServletRequset的isUserInRole方法，并据此修改访问。<br />
Servlet的 security-role-ref子元素提供出现在服务器专用口令文件中的安全角色名的一个别名。例如，假如编写了一个调用 request.isUserInRole（"boss"）的servlet，但后来该servlet被用在了一个其口令文件调用角色manager而不是boss的服务器中。下面的程序段使该servlet能够使用这两个名称中的任何一个。<br />
&lt;servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;security-role-ref&gt;<br />
&lt;role-name&gt;boss&lt;/role-name&gt; &lt;!-- New alias --&gt;<br />
&lt;role-link&gt;manager&lt;/role-link&gt; &lt;!-- Real name --&gt;<br />
&lt;/security-role-ref&gt;<br />
&lt;/servlet&gt;<br />
也可以在web-app内利用security-role元素提供将出现在role-name元素中的所有安全角色的一个全局列表。分别地生命角色使高级IDE容易处理安全信息。<br />
<br />
10 控制会话超时<br />
<br />
如果某个会话在一定的时间内未被访问，服务器可把它扔掉以节约内存。可利用HttpSession的setMaxInactiveInterval方法直接设置个别会话对象的超时值。如果不采用这种方法，则缺省的超时值由具体的服务器决定。但可利用session-config和session- timeout元素来给出一个适用于所有服务器的明确的超时值。超时值的单位为分钟，因此，下面的例子设置缺省会话超时值为三个小时（180分钟）。<br />
&lt;session-config&gt;<br />
&lt;session-timeout&gt;180&lt;/session-timeout&gt;<br />
&lt;/session-config&gt;<br />
<br />
11 Web应用的文档化<br />
<br />
越来越多的开发环境开始提供servlet和JSP的直接支持。例子有Borland Jbuilder Enterprise Edition、Macromedia UltraDev、Allaire JRun Studio（写此文时，已被Macromedia收购）以及IBM VisuaAge for Java等。<br />
大量的web.xml元素不仅是为服务器设计的，而且还是为可视开发环境设计的。它们包括icon、display-name和discription等。<br />
可回忆一下，在web.xml内以适当地次序声明web-app子元素很重要。不过，这里只要记住icon、display-name和description是web.xml的web-app元素内的前三个合法元素即可。<br />
l icon<br />
icon元素指出GUI工具可用来代表Web应用的一个和两个图像文件。可利用small-icon元素指定一幅16 x 16的GIF或JPEG图像，用large-icon元素指定一幅32 x 32的图像。下面举一个例子： <br />
&lt;icon&gt;<br />
&lt;small-icon&gt;/images/small-book.gif&lt;/small-icon&gt;<br />
&lt;large-icon&gt;/images/tome.jpg&lt;/large-icon&gt;<br />
&lt;/icon&gt;<br />
l display-name<br />
display-name元素提供GUI工具可能会用来标记此Web应用的一个名称。下面是个例子。<br />
&lt;display-name&gt;Rare Books&lt;/display-name&gt;<br />
l description<br />
description元素提供解释性文本，如下所示：<br />
&lt;description&gt;<br />
This Web application represents the store developed for<br />
rare-books.com, an online bookstore specializing in rare<br />
and limited-edition books.<br />
&lt;/description&gt;<br />
<br />
12 关联文件与MIME类型<br />
<br />
服务器一般都具有一种让Web站点管理员将文件扩展名与媒体相关联的方法。例如，将会自动给予名为mom.jpg的文件一个image/jpeg的MIME 类型。但是，假如你的Web应用具有几个不寻常的文件，你希望保证它们在发送到客户机时分配为某种MIME类型。mime-mapping元素（具有 extension和mime-type子元素）可提供这种保证。例如，下面的代码指示服务器将application/x-fubar的MIME类型分配给所有以.foo结尾的文件。<br />
&lt;mime-mapping&gt;<br />
&lt;extension&gt;foo&lt;/extension&gt;<br />
&lt;mime-type&gt;application/x-fubar&lt;/mime-type&gt;<br />
&lt;/mime-mapping&gt;<br />
或许，你的Web应用希望重载（override）标准的映射。例如，下面的代码将告诉服务器在发送到客户机时指定.ps文件作为纯文本（text/plain）而不是作为PostScript（application/postscript）。<br />
&lt;mime-mapping&gt;<br />
&lt;extension&gt;ps&lt;/extension&gt;<br />
&lt;mime-type&gt;application/postscript&lt;/mime-type&gt;<br />
&lt;/mime-mapping&gt;<br />
<br />
<br />
13 定位TLD<br />
<br />
JSP taglib元素具有一个必要的uri属性，它给出一个TLD（Tag Library Descriptor）文件相对于Web应用的根的位置。TLD文件的实际名称在发布新的标签库版本时可能会改变，但我们希望避免更改所有现有JSP页面。此外，可能还希望使用保持taglib元素的简练性的一个简短的uri。这就是部署描述符文件的taglib元素派用场的所在了。Taglib包含两个子元素：taglib-uri和taglib-location。taglib-uri元素应该与用于JSP taglib元素的uri属性的东西相匹配。Taglib-location元素给出TLD文件的实际位置。例如，假如你将文件chart-tags- 1.3beta.tld放在WebApp/WEB-INF/tlds中。现在，假如web.xml在web-app元素内包含下列内容。<br />
&lt;taglib&gt;<br />
&lt;taglib-uri&gt;/charts.tld&lt;/taglib-uri&gt;<br />
&lt;taglib-location&gt;<br />
/WEB-INF/tlds/chart-tags-1.3beta.tld<br />
&lt;/taglib-location&gt;<br />
&lt;/taglib&gt;<br />
给出这个说明后，JSP页面可通过下面的简化形式使用标签库。<br />
&lt;%@ taglib uri="/charts.tld" prefix="somePrefix" %&gt;<br />
<br />
14 指定应用事件监听程序<br />
<br />
应用事件监听器程序是建立或修改servlet环境或会话对象时通知的类。它们是servlet规范的版本2.3中的新内容。这里只简单地说明用来向Web应用注册一个监听程序的web.xml的用法。<br />
注册一个监听程序涉及在web.xml的web-app元素内放置一个listener元素。在listener元素内，listener-class元素列出监听程序的完整的限定类名，如下所示：<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
虽然listener元素的结构很简单，但请不要忘记，必须正确地给出web-app元素内的子元素的次序。listener元素位于所有的servlet 元素之前以及所有filter-mapping元素之后。此外，因为应用生存期监听程序是serlvet规范的2.3版本中的新内容，所以必须使用 web.xml DTD的2.3版本，而不是2.2版本。<br />
例如，程序清单5-20给出一个名为ContextReporter的简单的监听程序，只要Web应用的Servlet-Context建立（如装载Web应用）或消除（如服务器关闭）时，它就在标准输出上显示一条消息。程序清单5-21给出此监听程序注册所需要的web.xml文件的一部分。<br />
<br />
程序清单5-20 ContextReporterjava<br />
package moreservlets;<br />
<br />
import javax.servlet.*;<br />
import java.util.*;<br />
<br />
/** Simple listener that prints a report on the standard output <br />
* when the ServletContext is created or destroyed.<br />
* &lt;P&gt;<br />
* Taken from More Servlets and JavaServer Pages<br />
* from Prentice Hall and Sun Microsystems Press,<br />
* </font><a href="http://www.moreservlets.com/" target="_blank"><font color="#1d58d1" size="2">http://www.moreservlets.com/.</font></a><br />
<font size="2">* &#169; 2002 Marty Hall; may be freely used or adapted.<br />
*/<br />
<br />
public class ContextReporter implements ServletContextListener {<br />
public void contextInitialized(ServletContextEvent event) {<br />
System.out.println("Context created on " +<br />
new Date() + ".");<br />
}<br />
<br />
public void contextDestroyed(ServletContextEvent event) {<br />
System.out.println("Context destroyed on " +<br />
new Date() + ".");<br />
}<br />
}<br />
<br />
<br />
程序清单5-21 web.xml（声明一个监听程序的摘录）<br />
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />
&lt;!DOCTYPE web-app<br />
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />
"</font><a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/dtd/web-app_2_3.dtd</font></a><font size="2">"&gt;<br />
<br />
&lt;web-app&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;filter-mapping&gt; &#8230; &lt;/filter-mapping&gt;<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;package.ListenerClass&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
&lt;servlet&gt; ... &lt;/servlet&gt;<br />
&lt;!-- ... --&gt;<br />
&lt;/web-app&gt;<br />
<br />
<br />
15 J2EE元素<br />
<br />
本节描述用作J2EE环境组成部分的Web应用的web.xml元素。这里将提供一个简明的介绍，详细内容可以参阅</font><a href="http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf" target="_blank"><font color="#1d58d1" size="2">http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf</font></a><font size="2">的Java 2 Plantform Enterprise Edition版本1.3规范的第5章。<br />
l distributable<br />
distributable 元素指出，Web应用是以这样的方式编程的：即，支持集群的服务器可安全地在多个服务器上分布Web应用。例如，一个可分布的应用必须只使用 Serializable对象作为其HttpSession对象的属性，而且必须避免用实例变量（字段）来实现持续性。distributable元素直接出现在discription元素之后，并且不包含子元素或数据，它只是一个如下的标志。<br />
&lt;distributable /&gt;<br />
l resource-env-ref<br />
resource -env-ref元素声明一个与某个资源有关的管理对象。此元素由一个可选的description元素、一个resource-env-ref- name元素（一个相对于java:comp/env环境的JNDI名）以及一个resource-env-type元素（指定资源类型的完全限定的类），如下所示：<br />
&lt;resource-env-ref&gt;<br />
&lt;resource-env-ref-name&gt;<br />
jms/StockQueue<br />
&lt;/resource-env-ref-name&gt;<br />
&lt;resource-env-ref-type&gt;<br />
javax.jms.Queue<br />
&lt;/resource-env-ref-type&gt;<br />
&lt;/resource-env-ref&gt;<br />
l env-entry<br />
env -entry元素声明Web应用的环境项。它由一个可选的description元素、一个env-entry-name元素（一个相对于java: comp/env环境JNDI名）、一个env-entry-value元素（项值）以及一个env-entry-type元素（java.lang程序包中一个类型的完全限定类名，java.lang.Boolean、java.lang.String等）组成。下面是一个例子：<br />
&lt;env-entry&gt;<br />
&lt;env-entry-name&gt;minAmout&lt;/env-entry-name&gt;<br />
&lt;env-entry-value&gt;100.00&lt;/env-entry-value&gt;<br />
&lt;env-entry-type&gt;minAmout&lt;/env-entry-type&gt;<br />
&lt;/env-entry&gt;<br />
l ejb-ref<br />
ejb -ref元素声明对一个EJB的主目录的应用。它由一个可选的description元素、一个ejb-ref-name元素（相对于java: comp/env的EJB应用）、一个ejb-ref-type元素（bean的类型，Entity或Session）、一个home元素（bean的主目录接口的完全限定名）、一个remote元素（bean的远程接口的完全限定名）以及一个可选的ejb-link元素（当前bean链接的另一个 bean的名称）组成。<br />
l ejb-local-ref<br />
ejb-local-ref元素声明一个EJB的本地主目录的引用。除了用local-home代替home外，此元素具有与ejb-ref元素相同的属性并以相同的方式使用。</font> 
<img src ="http://www.blogjava.net/freiberg/aggbug/145814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 13:01 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】JSP三种页面跳转方式 </title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145812.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145812.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145812.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145812.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145812.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145812.html</trackback:ping><description><![CDATA[<p>使用JSP大约有下列三种跳转方式：<br />
1. response.sendRedirect();<br />
2. response.setHeader("Location","");<br />
3. &lt;jsp:forward page="" /&gt; </p>
<p>经过试验得到下面的一些规则：</p>
<p><strong>一. response.sendRedirect()</strong></p>
<ol>
    <li>此语句前不允许有out.flush()，如果有，会有异常：<br />
    java.lang.IllegalStateException: Can't sendRedirect() after data has committed to the client.<br />
    &nbsp;at com.caucho.server.connection.AbstractHttpResponse.sendRedirect(AbstractHttpResponse.java:558)<br />
    ...
    <li>跳转后浏览器地址栏变化
    <li>如果要跳到不同主机下，跳转后，此语句后面的语句会继续执行，如同新开了线程，但是对response的操作已经无意义了；
    <li>如果要跳到相同主机下，此语句后面的语句执行完成后才会跳转； </li>
</ol>
<p><strong>二. response.setHeader("Location","")</strong></p>
<ol>
    <li>此语句前不允许有out.flush()，如果有，页面不会跳转。
    <li>跳转后浏览器地址栏变化
    <li>此语句后面的语句执行完成后才会跳转 </li>
</ol>
<p><strong>三. &lt;jsp:forward page="" /&gt; </strong></p>
<ol>
    <li>此语句前不允许有out.flush()，如果有，会有异常：<br />
    java.lang.IllegalStateException: forward() not allowed after buffer has committed.<br />
    &nbsp;at com.caucho.server.webapp.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:134)<br />
    &nbsp;at com.caucho.server.webapp.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:101)<br />
    &nbsp;at com.caucho.jsp.PageContextImpl.forward(PageContextImpl.java:836)<br />
    &nbsp;...
    <li>跳转后浏览器地址栏不变，但是只能跳到当前主机下
    <li>此语句后面的语句执行完成后才会跳转&nbsp;
    <li>跳转后得路径变为当前路径，图片不是绝对路径将无法显示 </li>
</ol>
<h4>JSP跳转页面详解<br />
在JSP中使用jsp forward Action来实现页面的跳转功能。</h4>
<div>　　 语法：</div>
<div>&lt;jsp:forward page="{relativeURL|&lt;%= expression %&gt;}"/&gt; 或<br />
&lt;jsp:forward page="{relativeURL|&lt;%= expression %&gt;}"&gt;<br />
&lt;jsp:param name="parameterName"<br />
value="{parameterValue|&lt;%= expression %&gt;}"/&gt;+&lt;/jsp:forward&gt;</div>
<div>　　这个action使您可以将request向前到另外一个页面。它只有一个属性，page。Page应有一个相对的URL组成。这可以是一个静态的值或者是能够在被请求的时候计算得到的值，就如下面两个例子一般：</div>
<div>&lt;jsp:forward page="/utils/errorReporter.jsp"/&gt;<br />
&lt;jsp:forward page="&lt;%= someJavaExpression %&gt;"/&gt;<br />
!supportEmptyParas]&gt;</div>
<div>　　现在以一个具体例子来说明：在test1.jsp中使用forward使其跳转到test2.jsp页面中。</div>
<div>Test1.jsp<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;forward test&lt;/TITLE&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;/HEAD&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;BODY BGCOLOR="#FFFFFF"&gt;<br />
&lt;!--跳转到test2.jsp--!&gt;<br />
&lt;jsp:forward page="/test2.jsp"/&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;<br />
!supportEmptyParas]&gt;<br />
test2.jsp<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt; forward test &lt;/TITLE&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;/HEAD&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;BODY BGCOLOR="#FFFFFF"&gt;<br />
&lt;%out.println("这是jsp2.jsp页面产生出的输出");%&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;<br />
!supportEmptyParas]&gt;<br />
　　运行test1.jsp，可在浏览器中看见："这是jsp2.jsp页面产生出的输出"的输出信息。但是如果你在test1.jsp和test2.jsp这两个页面中有参数传递怎么办呢？用get方式吧，不但总的长度有限制，使用现在十分不方便，而且有时候还不安全。其实我们完全可以使用jsp1.1中给forward里提供的para属性就可以解决。现以test3.jsp和test4.jsp来说明。</div>
<div>!supportEmptyParas]&gt;<br />
Test1.jsp<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt; forward test &lt;/TITLE&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;/HEAD&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;BODY BGCOLOR="#FFFFFF"&gt;<br />
&lt;jsp:forward page="/test4.jsp"&gt;<br />
&lt;jsp:param name="name" value="powerman"/&gt;<br />
&lt;jsp:param name="address" value=" 北京西大街188号"/&gt;<br />
&lt;/jsp:forward&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;<br />
!supportEmptyParas]&gt;<br />
test2.jsp<br />
&lt;HTML&gt;<br />
&lt;HEAD&gt;<br />
&lt;TITLE&gt;forward test&lt;/TITLE&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;/HEAD&gt;<br />
!supportEmptyParas]&gt;<br />
&lt;BODY BGCOLOR="#FFFFFF"&gt;<br />
&lt;%<br />
out.println("这是jsp4.jsp页面产生出的输出"+"&lt;br&gt;");<br />
out.println("姓名："+request.getParameter("name")+"&lt;br&gt;");<br />
out.println("地址："+request.getParameter("address")+"&lt;br&gt;");<br />
!supportEmptyParas]&gt;<br />
%&gt;<br />
&lt;/BODY&gt;<br />
&lt;/HTML&gt;</div>
<div>　　 运行test3.jsp，可在浏览器中看见：</div>
<div>　　 "这是jsp4.jsp页面产生出的输出<br />
　　 姓名：powerman<br />
　　 地址：北京西大街188号"</div>
<div>的输出信息<br />
</div>
<img src ="http://www.blogjava.net/freiberg/aggbug/145812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 12:54 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】java中文件操作大全</title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145811.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 04:53:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145811.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145811.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145811.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一.获得控制台用户输入的信息/**&nbsp;*//**获得控制台用户输入的信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;IOException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp...&nbsp;&nbsp;<a href='http://www.blogjava.net/freiberg/archive/2007/09/17/145811.html'>阅读全文</a><img src ="http://www.blogjava.net/freiberg/aggbug/145811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 12:53 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不用imagemagic，生成高质量缩略图的算法</title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145810.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 04:53:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145810.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145810.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145810.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145810.html</trackback:ping><description><![CDATA[生成高品质缩略图算法。 &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; import &nbsp; java.awt.image.BufferedImage; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; public &nbsp; class &nbsp; ImageScale &nbsp; { &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; width; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; height; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; scaleWidth; &nbsp; <br />
&nbsp; double &nbsp; support &nbsp; = &nbsp; (double) &nbsp; 3.0; &nbsp; <br />
&nbsp; double &nbsp; PI &nbsp; = &nbsp; (double) &nbsp; 3.14159265358978; &nbsp; <br />
&nbsp; double[] &nbsp; contrib; &nbsp; <br />
&nbsp; double[] &nbsp; normContrib; &nbsp; <br />
&nbsp; double[] &nbsp; tmpContrib; &nbsp; <br />
&nbsp; int &nbsp; startContrib, &nbsp; stopContrib; &nbsp; <br />
&nbsp; int &nbsp; nDots; &nbsp; <br />
&nbsp; int &nbsp; nHalfDots; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; /** &nbsp; <br />
&nbsp; &nbsp; * &nbsp; Start: &nbsp; <br />
&nbsp; &nbsp; * &nbsp; Use &nbsp; Lanczos &nbsp; filter &nbsp; to &nbsp; replace &nbsp; the &nbsp; original &nbsp; algorithm &nbsp; for &nbsp; image &nbsp; scaling. &nbsp; Lanczos &nbsp; improves &nbsp; quality &nbsp; of &nbsp; the &nbsp; scaled &nbsp; image &nbsp; <br />
&nbsp; &nbsp; * &nbsp; modify &nbsp; by &nbsp; :blade &nbsp; <br />
&nbsp; &nbsp; * &nbsp; */ &nbsp; <br />
&nbsp; public &nbsp; BufferedImage &nbsp; imageZoomOut(BufferedImage &nbsp; srcBufferImage,int &nbsp; w, &nbsp; int &nbsp; h) &nbsp; { &nbsp; <br />
&nbsp; width &nbsp; = &nbsp; srcBufferImage.getWidth(); &nbsp; <br />
&nbsp; height &nbsp; = &nbsp; srcBufferImage.getHeight(); &nbsp; <br />
&nbsp; scaleWidth &nbsp; = &nbsp; w; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; if &nbsp; (DetermineResultSize(w, &nbsp; h) &nbsp; == &nbsp; 1) &nbsp; { &nbsp; <br />
&nbsp; return &nbsp; srcBufferImage; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; CalContrib(); &nbsp; <br />
&nbsp; BufferedImage &nbsp; pbOut &nbsp; = &nbsp; HorizontalFiltering(srcBufferImage, &nbsp; w); &nbsp; <br />
&nbsp; BufferedImage &nbsp; pbFinalOut &nbsp; = &nbsp; VerticalFiltering(pbOut, &nbsp; h); &nbsp; <br />
&nbsp; return &nbsp; pbFinalOut; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; /** &nbsp; <br />
&nbsp; &nbsp; * &nbsp; 决定图像尺寸 &nbsp; <br />
&nbsp; &nbsp; * &nbsp; */ &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; DetermineResultSize(int &nbsp; w, &nbsp; int &nbsp; h) &nbsp; { &nbsp; <br />
&nbsp; double &nbsp; scaleH, &nbsp; scaleV; &nbsp; <br />
&nbsp; scaleH &nbsp; = &nbsp; (double) &nbsp; w &nbsp; / &nbsp; (double) &nbsp; width; &nbsp; <br />
&nbsp; scaleV &nbsp; = &nbsp; (double) &nbsp; h &nbsp; / &nbsp; (double) &nbsp; height; &nbsp; <br />
&nbsp; //需要判断一下scaleH，scaleV，不做放大操作 &nbsp; <br />
&nbsp; if &nbsp; (scaleH &nbsp; &gt;= &nbsp; 1.0 &nbsp; &amp;&amp; &nbsp; scaleV &nbsp; &gt;= &nbsp; 1.0) &nbsp; { &nbsp; <br />
&nbsp; return &nbsp; 1; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; DetermineResultSize() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; double &nbsp; Lanczos(int &nbsp; i, &nbsp; int &nbsp; inWidth, &nbsp; int &nbsp; outWidth, &nbsp; double &nbsp; Support) &nbsp; { &nbsp; <br />
&nbsp; double &nbsp; x; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; x &nbsp; = &nbsp; (double) &nbsp; i &nbsp; * &nbsp; (double) &nbsp; outWidth &nbsp; / &nbsp; (double) &nbsp; inWidth; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; return &nbsp; Math.sin(x &nbsp; * &nbsp; PI) &nbsp; / &nbsp; (x &nbsp; * &nbsp; PI) &nbsp; * &nbsp; Math.sin(x &nbsp; * &nbsp; PI &nbsp; / &nbsp; Support) &nbsp; <br />
&nbsp; / &nbsp; (x &nbsp; * &nbsp; PI &nbsp; / &nbsp; Support); &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; Lanczos() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; // &nbsp; <br />
&nbsp; // &nbsp; &nbsp; &nbsp; Assumption: &nbsp; same &nbsp; horizontal &nbsp; and &nbsp; vertical &nbsp; scaling &nbsp; factor &nbsp; <br />
&nbsp; // &nbsp; <br />
&nbsp; private &nbsp; void &nbsp; CalContrib() &nbsp; { &nbsp; <br />
&nbsp; nHalfDots &nbsp; = &nbsp; (int) &nbsp; ((double) &nbsp; width &nbsp; * &nbsp; support &nbsp; / &nbsp; (double) &nbsp; scaleWidth); &nbsp; <br />
&nbsp; nDots &nbsp; = &nbsp; nHalfDots &nbsp; * &nbsp; 2 &nbsp; + &nbsp; 1; &nbsp; <br />
&nbsp; try &nbsp; { &nbsp; <br />
&nbsp; contrib &nbsp; = &nbsp; new &nbsp; double[nDots]; &nbsp; <br />
&nbsp; normContrib &nbsp; = &nbsp; new &nbsp; double[nDots]; &nbsp; <br />
&nbsp; tmpContrib &nbsp; = &nbsp; new &nbsp; double[nDots]; &nbsp; <br />
&nbsp; } &nbsp; catch &nbsp; (Exception &nbsp; e) &nbsp; { &nbsp; <br />
&nbsp; System.out.println("init &nbsp; contrib,normContrib,tmpContrib" &nbsp; + &nbsp; e); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; center &nbsp; = &nbsp; nHalfDots; &nbsp; <br />
&nbsp; contrib[center] &nbsp; = &nbsp; 1.0; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; double &nbsp; weight &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; int &nbsp; i &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; 1; &nbsp; i &nbsp; &lt;= &nbsp; center; &nbsp; i++) &nbsp; { &nbsp; <br />
&nbsp; contrib[center &nbsp; + &nbsp; i] &nbsp; = &nbsp; Lanczos(i, &nbsp; width, &nbsp; scaleWidth, &nbsp; support); &nbsp; <br />
&nbsp; weight &nbsp; += &nbsp; contrib[center &nbsp; + &nbsp; i]; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; center &nbsp; - &nbsp; 1; &nbsp; i &nbsp; &gt;= &nbsp; 0; &nbsp; i--) &nbsp; { &nbsp; <br />
&nbsp; contrib[i] &nbsp; = &nbsp; contrib[center &nbsp; * &nbsp; 2 &nbsp; - &nbsp; i]; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; weight &nbsp; = &nbsp; weight &nbsp; * &nbsp; 2 &nbsp; + &nbsp; 1.0; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; 0; &nbsp; i &nbsp; &lt;= &nbsp; center; &nbsp; i++) &nbsp; { &nbsp; <br />
&nbsp; normContrib[i] &nbsp; = &nbsp; contrib[i] &nbsp; / &nbsp; weight; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; center &nbsp; + &nbsp; 1; &nbsp; i &nbsp; &lt; &nbsp; nDots; &nbsp; i++) &nbsp; { &nbsp; <br />
&nbsp; normContrib[i] &nbsp; = &nbsp; normContrib[center &nbsp; * &nbsp; 2 &nbsp; - &nbsp; i]; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; CalContrib() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; //处理边缘 &nbsp; <br />
&nbsp; private &nbsp; void &nbsp; CalTempContrib(int &nbsp; start, &nbsp; int &nbsp; stop) &nbsp; { &nbsp; <br />
&nbsp; double &nbsp; weight &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; i &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; start; &nbsp; i &nbsp; &lt;= &nbsp; stop; &nbsp; i++) &nbsp; { &nbsp; <br />
&nbsp; weight &nbsp; += &nbsp; contrib[i]; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; start; &nbsp; i &nbsp; &lt;= &nbsp; stop; &nbsp; i++) &nbsp; { &nbsp; <br />
&nbsp; tmpContrib[i] &nbsp; = &nbsp; contrib[i] &nbsp; / &nbsp; weight; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; CalTempContrib() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; GetRedValue(int &nbsp; rgbValue) &nbsp; { &nbsp; <br />
&nbsp; int &nbsp; temp &nbsp; = &nbsp; rgbValue &nbsp; &amp; &nbsp; 0x00ff0000; &nbsp; <br />
&nbsp; return &nbsp; temp &nbsp; &gt;&gt; &nbsp; 16; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; GetGreenValue(int &nbsp; rgbValue) &nbsp; { &nbsp; <br />
&nbsp; int &nbsp; temp &nbsp; = &nbsp; rgbValue &nbsp; &amp; &nbsp; 0x0000ff00; &nbsp; <br />
&nbsp; return &nbsp; temp &nbsp; &gt;&gt; &nbsp; 8; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; GetBlueValue(int &nbsp; rgbValue) &nbsp; { &nbsp; <br />
&nbsp; return &nbsp; rgbValue &nbsp; &amp; &nbsp; 0x000000ff; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; ComRGB(int &nbsp; redValue, &nbsp; int &nbsp; greenValue, &nbsp; int &nbsp; blueValue) &nbsp; { &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; return &nbsp; (redValue &nbsp; &lt;&lt; &nbsp; 16) &nbsp; + &nbsp; (greenValue &nbsp; &lt;&lt; &nbsp; 8) &nbsp; + &nbsp; blueValue; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; //行水平滤波 &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; HorizontalFilter(BufferedImage &nbsp; bufImg, &nbsp; int &nbsp; startX, &nbsp; int &nbsp; stopX, &nbsp; <br />
&nbsp; int &nbsp; start, &nbsp; int &nbsp; stop, &nbsp; int &nbsp; y, &nbsp; double[] &nbsp; pContrib) &nbsp; { &nbsp; <br />
&nbsp; double &nbsp; valueRed &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; double &nbsp; valueGreen &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; double &nbsp; valueBlue &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; int &nbsp; valueRGB &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; int &nbsp; i, &nbsp; j; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; startX, &nbsp; j &nbsp; = &nbsp; start; &nbsp; i &nbsp; &lt;= &nbsp; stopX; &nbsp; i++, &nbsp; j++) &nbsp; { &nbsp; <br />
&nbsp; valueRGB &nbsp; = &nbsp; bufImg.getRGB(i, &nbsp; y); &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; valueRed &nbsp; += &nbsp; GetRedValue(valueRGB) &nbsp; * &nbsp; pContrib[j]; &nbsp; <br />
&nbsp; valueGreen &nbsp; += &nbsp; GetGreenValue(valueRGB) &nbsp; * &nbsp; pContrib[j]; &nbsp; <br />
&nbsp; valueBlue &nbsp; += &nbsp; GetBlueValue(valueRGB) &nbsp; * &nbsp; pContrib[j]; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; valueRGB &nbsp; = &nbsp; ComRGB(Clip((int) &nbsp; valueRed), &nbsp; Clip((int) &nbsp; valueGreen), &nbsp; <br />
&nbsp; Clip((int) &nbsp; valueBlue)); &nbsp; <br />
&nbsp; return &nbsp; valueRGB; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; HorizontalFilter() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; //图片水平滤波 &nbsp; <br />
&nbsp; private &nbsp; BufferedImage &nbsp; HorizontalFiltering(BufferedImage &nbsp; bufImage, &nbsp; int &nbsp; iOutW) &nbsp; { &nbsp; <br />
&nbsp; int &nbsp; dwInW &nbsp; = &nbsp; bufImage.getWidth(); &nbsp; <br />
&nbsp; int &nbsp; dwInH &nbsp; = &nbsp; bufImage.getHeight(); &nbsp; <br />
&nbsp; int &nbsp; value &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; BufferedImage &nbsp; pbOut &nbsp; = &nbsp; new &nbsp; BufferedImage(iOutW, &nbsp; dwInH, &nbsp; <br />
&nbsp; BufferedImage.TYPE_INT_RGB); &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (int &nbsp; x &nbsp; = &nbsp; 0; &nbsp; x &nbsp; &lt; &nbsp; iOutW; &nbsp; x++) &nbsp; { &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; startX; &nbsp; <br />
&nbsp; int &nbsp; start; &nbsp; <br />
&nbsp; int &nbsp; X &nbsp; = &nbsp; (int) &nbsp; (((double) &nbsp; x) &nbsp; * &nbsp; ((double) &nbsp; dwInW) &nbsp; / &nbsp; ((double) &nbsp; iOutW) &nbsp; + &nbsp; 0.5); &nbsp; <br />
&nbsp; int &nbsp; y &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; startX &nbsp; = &nbsp; X &nbsp; - &nbsp; nHalfDots; &nbsp; <br />
&nbsp; if &nbsp; (startX &nbsp; &lt; &nbsp; 0) &nbsp; { &nbsp; <br />
&nbsp; startX &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; start &nbsp; = &nbsp; nHalfDots &nbsp; - &nbsp; X; &nbsp; <br />
&nbsp; } &nbsp; else &nbsp; { &nbsp; <br />
&nbsp; start &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; stop; &nbsp; <br />
&nbsp; int &nbsp; stopX &nbsp; = &nbsp; X &nbsp; + &nbsp; nHalfDots; &nbsp; <br />
&nbsp; if &nbsp; (stopX &nbsp; &gt; &nbsp; (dwInW &nbsp; - &nbsp; 1)) &nbsp; { &nbsp; <br />
&nbsp; stopX &nbsp; = &nbsp; dwInW &nbsp; - &nbsp; 1; &nbsp; <br />
&nbsp; stop &nbsp; = &nbsp; nHalfDots &nbsp; + &nbsp; (dwInW &nbsp; - &nbsp; 1 &nbsp; - &nbsp; X); &nbsp; <br />
&nbsp; } &nbsp; else &nbsp; { &nbsp; <br />
&nbsp; stop &nbsp; = &nbsp; nHalfDots &nbsp; * &nbsp; 2; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; if &nbsp; (start &nbsp; &gt; &nbsp; 0 &nbsp; || &nbsp; stop &nbsp; &lt; &nbsp; nDots &nbsp; - &nbsp; 1) &nbsp; { &nbsp; <br />
&nbsp; CalTempContrib(start, &nbsp; stop); &nbsp; <br />
&nbsp; for &nbsp; (y &nbsp; = &nbsp; 0; &nbsp; y &nbsp; &lt; &nbsp; dwInH; &nbsp; y++) &nbsp; { &nbsp; <br />
&nbsp; value &nbsp; = &nbsp; HorizontalFilter(bufImage, &nbsp; startX, &nbsp; stopX, &nbsp; start, &nbsp; <br />
&nbsp; stop, &nbsp; y, &nbsp; tmpContrib); &nbsp; <br />
&nbsp; pbOut.setRGB(x, &nbsp; y, &nbsp; value); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; } &nbsp; else &nbsp; { &nbsp; <br />
&nbsp; for &nbsp; (y &nbsp; = &nbsp; 0; &nbsp; y &nbsp; &lt; &nbsp; dwInH; &nbsp; y++) &nbsp; { &nbsp; <br />
&nbsp; value &nbsp; = &nbsp; HorizontalFilter(bufImage, &nbsp; startX, &nbsp; stopX, &nbsp; start, &nbsp; <br />
&nbsp; stop, &nbsp; y, &nbsp; normContrib); &nbsp; <br />
&nbsp; pbOut.setRGB(x, &nbsp; y, &nbsp; value); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; return &nbsp; pbOut; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; HorizontalFiltering() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; int &nbsp; VerticalFilter(BufferedImage &nbsp; pbInImage, &nbsp; int &nbsp; startY, &nbsp; int &nbsp; stopY, &nbsp; <br />
&nbsp; int &nbsp; start, &nbsp; int &nbsp; stop, &nbsp; int &nbsp; x, &nbsp; double[] &nbsp; pContrib) &nbsp; { &nbsp; <br />
&nbsp; double &nbsp; valueRed &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; double &nbsp; valueGreen &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; double &nbsp; valueBlue &nbsp; = &nbsp; 0.0; &nbsp; <br />
&nbsp; int &nbsp; valueRGB &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; int &nbsp; i, &nbsp; j; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (i &nbsp; = &nbsp; startY, &nbsp; j &nbsp; = &nbsp; start; &nbsp; i &nbsp; &lt;= &nbsp; stopY; &nbsp; i++, &nbsp; j++) &nbsp; { &nbsp; <br />
&nbsp; valueRGB &nbsp; = &nbsp; pbInImage.getRGB(x, &nbsp; i); &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; valueRed &nbsp; += &nbsp; GetRedValue(valueRGB) &nbsp; * &nbsp; pContrib[j]; &nbsp; <br />
&nbsp; valueGreen &nbsp; += &nbsp; GetGreenValue(valueRGB) &nbsp; * &nbsp; pContrib[j]; &nbsp; <br />
&nbsp; valueBlue &nbsp; += &nbsp; GetBlueValue(valueRGB) &nbsp; * &nbsp; pContrib[j]; &nbsp; <br />
&nbsp; // &nbsp; &nbsp; System.out.println(valueRed+"-&gt;"+Clip((int)valueRed)+"&lt;-"); &nbsp; <br />
&nbsp; // &nbsp; <br />
&nbsp; // &nbsp; &nbsp; System.out.println(valueGreen+"-&gt;"+Clip((int)valueGreen)+"&lt;-"); &nbsp; <br />
&nbsp; // &nbsp; &nbsp; System.out.println(valueBlue+"-&gt;"+Clip((int)valueBlue)+"&lt;-"+"--&gt;"); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; valueRGB &nbsp; = &nbsp; ComRGB(Clip((int) &nbsp; valueRed), &nbsp; Clip((int) &nbsp; valueGreen), &nbsp; <br />
&nbsp; Clip((int) &nbsp; valueBlue)); &nbsp; <br />
&nbsp; // &nbsp; &nbsp; &nbsp; System.out.println(valueRGB); &nbsp; <br />
&nbsp; return &nbsp; valueRGB; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; VerticalFilter() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; private &nbsp; BufferedImage &nbsp; VerticalFiltering(BufferedImage &nbsp; pbImage, &nbsp; int &nbsp; iOutH) &nbsp; { &nbsp; <br />
&nbsp; int &nbsp; iW &nbsp; = &nbsp; pbImage.getWidth(); &nbsp; <br />
&nbsp; int &nbsp; iH &nbsp; = &nbsp; pbImage.getHeight(); &nbsp; <br />
&nbsp; int &nbsp; value &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; BufferedImage &nbsp; pbOut &nbsp; = &nbsp; new &nbsp; BufferedImage(iW, &nbsp; iOutH, &nbsp; <br />
&nbsp; BufferedImage.TYPE_INT_RGB); &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; for &nbsp; (int &nbsp; y &nbsp; = &nbsp; 0; &nbsp; y &nbsp; &lt; &nbsp; iOutH; &nbsp; y++) &nbsp; { &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; startY; &nbsp; <br />
&nbsp; int &nbsp; start; &nbsp; <br />
&nbsp; int &nbsp; Y &nbsp; = &nbsp; (int) &nbsp; (((double) &nbsp; y) &nbsp; * &nbsp; ((double) &nbsp; iH) &nbsp; / &nbsp; ((double) &nbsp; iOutH) &nbsp; + &nbsp; 0.5); &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; startY &nbsp; = &nbsp; Y &nbsp; - &nbsp; nHalfDots; &nbsp; <br />
&nbsp; if &nbsp; (startY &nbsp; &lt; &nbsp; 0) &nbsp; { &nbsp; <br />
&nbsp; startY &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; start &nbsp; = &nbsp; nHalfDots &nbsp; - &nbsp; Y; &nbsp; <br />
&nbsp; } &nbsp; else &nbsp; { &nbsp; <br />
&nbsp; start &nbsp; = &nbsp; 0; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; stop; &nbsp; <br />
&nbsp; int &nbsp; stopY &nbsp; = &nbsp; Y &nbsp; + &nbsp; nHalfDots; &nbsp; <br />
&nbsp; if &nbsp; (stopY &nbsp; &gt; &nbsp; (int) &nbsp; (iH &nbsp; - &nbsp; 1)) &nbsp; { &nbsp; <br />
&nbsp; stopY &nbsp; = &nbsp; iH &nbsp; - &nbsp; 1; &nbsp; <br />
&nbsp; stop &nbsp; = &nbsp; nHalfDots &nbsp; + &nbsp; (iH &nbsp; - &nbsp; 1 &nbsp; - &nbsp; Y); &nbsp; <br />
&nbsp; } &nbsp; else &nbsp; { &nbsp; <br />
&nbsp; stop &nbsp; = &nbsp; nHalfDots &nbsp; * &nbsp; 2; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; if &nbsp; (start &nbsp; &gt; &nbsp; 0 &nbsp; || &nbsp; stop &nbsp; &lt; &nbsp; nDots &nbsp; - &nbsp; 1) &nbsp; { &nbsp; <br />
&nbsp; CalTempContrib(start, &nbsp; stop); &nbsp; <br />
&nbsp; for &nbsp; (int &nbsp; x &nbsp; = &nbsp; 0; &nbsp; x &nbsp; &lt; &nbsp; iW; &nbsp; x++) &nbsp; { &nbsp; <br />
&nbsp; value &nbsp; = &nbsp; VerticalFilter(pbImage, &nbsp; startY, &nbsp; stopY, &nbsp; start, &nbsp; stop, &nbsp; <br />
&nbsp; x, &nbsp; tmpContrib); &nbsp; <br />
&nbsp; pbOut.setRGB(x, &nbsp; y, &nbsp; value); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; } &nbsp; else &nbsp; { &nbsp; <br />
&nbsp; for &nbsp; (int &nbsp; x &nbsp; = &nbsp; 0; &nbsp; x &nbsp; &lt; &nbsp; iW; &nbsp; x++) &nbsp; { &nbsp; <br />
&nbsp; value &nbsp; = &nbsp; VerticalFilter(pbImage, &nbsp; startY, &nbsp; stopY, &nbsp; start, &nbsp; stop, &nbsp; <br />
&nbsp; x, &nbsp; normContrib); &nbsp; <br />
&nbsp; pbOut.setRGB(x, &nbsp; y, &nbsp; value); &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; return &nbsp; pbOut; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; } &nbsp; // &nbsp; end &nbsp; of &nbsp; VerticalFiltering() &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; int &nbsp; Clip(int &nbsp; x) &nbsp; { &nbsp; <br />
&nbsp; if &nbsp; (x &nbsp; &lt; &nbsp; 0) &nbsp; <br />
&nbsp; return &nbsp; 0; &nbsp; <br />
&nbsp; if &nbsp; (x &nbsp; &gt; &nbsp; 255) &nbsp; <br />
&nbsp; return &nbsp; 255; &nbsp; <br />
&nbsp; return &nbsp; x; &nbsp; <br />
&nbsp; } &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; /** &nbsp; <br />
&nbsp; &nbsp; * &nbsp; End: &nbsp; <br />
&nbsp; &nbsp; * &nbsp; Use &nbsp; Lanczos &nbsp; filter &nbsp; to &nbsp; replace &nbsp; the &nbsp; original &nbsp; algorithm &nbsp; for &nbsp; image &nbsp; scaling. &nbsp; Lanczos &nbsp; improves &nbsp; quality &nbsp; of &nbsp; the &nbsp; scaled &nbsp; image &nbsp; <br />
&nbsp; &nbsp; * &nbsp; modify &nbsp; by &nbsp; :blade &nbsp; <br />
&nbsp; &nbsp; * &nbsp; */ &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
<img src ="http://www.blogjava.net/freiberg/aggbug/145810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 12:53 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Url Rewrite Filter 重写url，不依赖与WEB服务器组件 </title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145809.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 04:52:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145809.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145809.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145809.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145809.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145809.html</trackback:ping><description><![CDATA[首先要在web.xml中声明一个Filter<br />
&nbsp;&lt;filter&gt;<br />
&nbsp;&nbsp;&lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;filter-class&gt;org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&lt;/filter-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;logLevel&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;WARN&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />
&nbsp;&lt;/filter&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&lt;filter-name&gt;UrlRewriteFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/filter-mapping&gt;
<p>然后在WEB-INF目录下新建urlrewrite.xml<br />
在其中进行重写规则的定义，它使用正则表达式来进行规则的定义</p>
<p>&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "<a href="http://tuckey.org/res/dtds/urlrewrite2.6.dtd">http://tuckey.org/res/dtds/urlrewrite2.6.dtd</a>"&gt;</p>
<p>&lt;!--</p>
<p>&nbsp;&nbsp;&nbsp; Configuration file for UrlRewriteFilter<br />
&nbsp;&nbsp;&nbsp; <a href="http://tuckey.org/urlrewrite/">http://tuckey.org/urlrewrite/</a></p>
<p>--&gt;<br />
&lt;urlrewrite&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;rule&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;from&gt;/test.html&lt;/from&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;to type="redirect"&gt;%{context-path}/page.html&lt;/to&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/rule&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;rule&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;from&gt;/param/(.*)&lt;/from&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;to&gt;/param.jsp?param=$1&lt;/to&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/rule&gt;<br />
<br />
&lt;/urlrewrite&gt;</p>
<p>上面是我的一个简单的测试<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;rule&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;from&gt;/test.html&lt;/from&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;to type="redirect"&gt;%{context-path}/page.html&lt;/to&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/rule&gt;<br />
是将test.html的访问请求转发给page.html</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;rule&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;from&gt;/param/(.*)&lt;/from&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;to&gt;/param.jsp?param=$1&lt;/to&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/rule&gt;<br />
将param.jsp?param=111这种请求重写为/param/111</p>
里面有详细的例子，大家可以自己看下 
<img src ="http://www.blogjava.net/freiberg/aggbug/145809.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 12:52 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145809.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】ImageMagick, JMagick安装、配置及使用</title><link>http://www.blogjava.net/freiberg/archive/2007/09/17/145808.html</link><dc:creator>Endless</dc:creator><author>Endless</author><pubDate>Mon, 17 Sep 2007 04:51:00 GMT</pubDate><guid>http://www.blogjava.net/freiberg/archive/2007/09/17/145808.html</guid><wfw:comment>http://www.blogjava.net/freiberg/comments/145808.html</wfw:comment><comments>http://www.blogjava.net/freiberg/archive/2007/09/17/145808.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/freiberg/comments/commentRss/145808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freiberg/services/trackbacks/145808.html</trackback:ping><description><![CDATA[<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体">
<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体">ImageMagick, JMagick安装、配置及使用：<br />
平台：winXP <br />
1. 安装ImageMagick（ImageMagick website:http://www.imagemagick.org/script/index.php）<br />
&nbsp;&nbsp;&nbsp; 下载并安装ImageMagick。file name: ImageMagick-6.2.6-8-Q16-windows-dll.exe<br />
&nbsp;&nbsp;&nbsp;&nbsp; download address: <a href="http://prdownloads.sourceforge.net/imagemagick/ImageMagick-6.2.6-8-Q16-windows-dll.exe?download">http://prdownloads.sourceforge.net/imagemagick/ImageMagick-6.2.6-8-Q16-windows-dll.exe?download</a><br />
&nbsp;&nbsp;&nbsp; 安装成功后，把install path加入系统path，以便能调用dll.如C:\Program Files\ImageMagick-6.2.6-Q16</span></font></div>
<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体">2. 安装JMagick（JMagick website: <a href="http://www.yeo.id.au/jmagick/">http://www.yeo.id.au/jmagick/</a>）<br />
&nbsp;&nbsp;&nbsp; 下载JMatick。file name: jmagick-6.2.6-win.zip <br />
&nbsp;&nbsp;&nbsp; download address: <a href="http://www.yeo.id.au/jmagick/quickload/win-6.2.6/jmagick-6.2.6-win.zip">http://www.yeo.id.au/jmagick/quickload/win-6.2.6/jmagick-6.2.6-win.zip</a><br />
&nbsp;&nbsp;&nbsp; 解压后把jmagick-6.2.6-win\jar\jmagick.jar copy到项目的WEB-INF\lib目录下，把jmagick-6.2.6-win\q16\jmagick.dll copy 到c:\windows\system32目录下。</span></font></div>
<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体">3. 程序参考： <br />
&nbsp;&nbsp; JMagickScale.java 实现图片缩略图 <br />
------------------------------------------------------------------<br />
package images;<br />
import magick.ImageInfo;<br />
import magick.MagickException;<br />
import magick.MagickImage;<br />
public class JMagickScale {<br />
&nbsp;/**<br />
&nbsp; * Description:<br />
&nbsp; * @param args<br />
&nbsp; * @throws MagickException <br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) throws MagickException {<br />
&nbsp; System.setProperty("jmagick.systemclassloader","no");<br />
&nbsp; <br />
&nbsp; //reading image<br />
&nbsp; ImageInfo info = new ImageInfo("c:/image4.bmp");<br />
&nbsp; MagickImage image = new MagickImage(info);<br />
&nbsp; <br />
&nbsp; //resize image<br />
&nbsp; MagickImage scaleImg = image.scaleImage(95, 80);<br />
&nbsp; <br />
&nbsp; //write image to file<br />
&nbsp; scaleImg.setFileName("c:/MyFile4.bmp");<br />
&nbsp; scaleImg.writeImage(info);<br />
&nbsp;}<br />
}</span></font></div>
<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体">&nbsp;JMagickTest.java 实现图片的各种操作示例,如旋转,加边框，设置背景，提升质量，加盖文字说明等等... <br />
-----------------------------------------------------------------------------------------------------------------------------<br />
package images;<br />
import java.awt.Dimension;<br />
import java.awt.Rectangle;<br />
import magick.ImageInfo;<br />
import magick.MagickImage;<br />
import magick.MagickException;<br />
import magick.QuantizeInfo;<br />
import magick.ColorspaceType;<br />
import magick.MagickApiException;<br />
import magick.PixelPacket;<br />
import magick.DrawInfo;<br />
import magick.ResolutionType;<br />
import magick.ProfileInfo;<br />
import magick.MontageInfo;<br />
import magick.Magick;<br />
import magick.MagickInfo;<br />
import java.io.IOException;<br />
import java.io.FileOutputStream;<br />
/**<br />
&nbsp;* For testing JMagick functions.<br />
&nbsp;* <br />
&nbsp;* @author Eric Yeo<br />
&nbsp;*/<br />
public class JMagickTest {<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Display the information about the profile supplied.<br />
&nbsp;&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param profile<br />
&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the profile for which to display<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; private static void displayProfile(ProfileInfo profile) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (profile.getName() == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Profile name is null");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Profile name is " + profile.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (profile.getInfo() == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("No profile info");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Profile length is " + profile.getInfo().length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rectangle rect = new Rectangle(0, 0, 80, 40);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int flags = Magick.parseImageGeometry("60x50", rect);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Scaled to " + rect.width + "x" + rect.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Copy an image.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ImageInfo info = new ImageInfo("pics.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info.setPage("50x50+0+0");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info.setUnits(ResolutionType.PixelsPerInchResolution);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info.setColorspace(ColorspaceType.RGBColorspace);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info.setBorderColor(PixelPacket.queryColorDatabase("red"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info.setDepth(8);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Depth "+info.getDepth());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info.setDepth(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage image = new MagickImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setImageAttribute("Comment", "Processed by JMagick");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Quality is "+image.getQuality());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Colorspace is " + image.getColorspace());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Resolution units is " + image.getUnits());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("X resolution is " + image.getXResolution());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Y resolution is " + image.getYResolution());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Size blob is " + image.sizeBlob());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Colors " + image.getColors());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Total colors " + image.getTotalColors());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Depth is "+image.getDepth());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.signatureImage();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setFileName("copy.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Background Color<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Old colour " + image.getBackgroundColor());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setBackgroundColor(PixelPacket.queryColorDatabase("red"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("New colour " + image.getBackgroundColor());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Border image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setBorderColor(PixelPacket.queryColorDatabase("green"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage borderedImage = image.borderImage(new Rectangle(0, 0,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10, 20));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; borderedImage.setFileName("border.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; borderedImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Raise image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage raisedImage = new MagickImage(new ImageInfo("pics.jpg"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raisedImage.raiseImage(new Rectangle(0, 0, 10, 20), true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raisedImage.setFileName("raised.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raisedImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Profile test<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Number of generic profiles "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + image.getGenericProfileCount());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; displayProfile(image.getColorProfile());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setColorProfile(new ProfileInfo());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; displayProfile(image.getColorProfile());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setColorProfile(new ProfileInfo("Test", new byte[20]));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; displayProfile(image.getColorProfile());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Montage test<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage images[] = new MagickImage[2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; images[0] = image;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; images[1] = image;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage seqImage = new MagickImage(images);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MontageInfo montageInfo = new MontageInfo(new ImageInfo());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; montageInfo.setFileName("montage.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; montageInfo.setTitle("Melbourne");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; montageInfo.setBorderWidth(5);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage montage = seqImage.montageImages(montageInfo);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; montage.writeImage(new ImageInfo());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Converting the montage into a blob<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; montage.setMagick("JPG");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] mblob = montage.imageToBlob(new ImageInfo());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Length "+mblob.length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Test average<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage average = seqImage.averageImages();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; average.setFileName("average.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; average.writeImage(new ImageInfo());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Image to blob<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info = new ImageInfo();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] blob = image.imageToBlob(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Blob to image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; info = new ImageInfo();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage blobImage = new MagickImage(info, blob);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dimension imageDim = blobImage.getDimension();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Blob width is " + imageDim.width);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Blob heght is " + imageDim.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(imageDim);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blobImage.setFileName("blob.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blobImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // JPEG Image to GIF blob<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image.setMagick("GIF");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blob = image.imageToBlob(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream out = new FileOutputStream("blob.gif");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.write(blob);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (IOException ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Unable to write blob to file: " + ex);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Rotation and shear<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; image = new MagickImage(new ImageInfo("pics.jpg"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage rotated = image.rotateImage(45.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rotated.setFileName("rotated.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rotated.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage sheared = image.shearImage(50.0, 10.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheared.setFileName("sheared.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sheared.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage scaled = image.scaleImage(100, 80);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scaled.setFileName("scaled.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scaled.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Cloning<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageDim = image.getDimension();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Width is " + imageDim.width);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Height is " + imageDim.height);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Depth is " + image.getDepth());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Storage class is " + image.getStorageClass());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Comment is \""<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + image.getImageAttribute("Comment") + "\"");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage clonedImage = image.cloneImage(0, 0, false);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clonedImage.setFileName("clone.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clonedImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Quantization<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage quantizedImage = new MagickImage(new ImageInfo(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "pics.jpg"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QuantizeInfo quantizeInfo = new QuantizeInfo();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quantizeInfo.setColorspace(ColorspaceType.GRAYColorspace);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quantizeInfo.setNumberColors(256);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quantizeInfo.setTreeDepth(4);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("QuantizeImage "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + quantizedImage.quantizeImage(quantizeInfo));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Colors " + quantizedImage.getColors());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Total colors "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + quantizedImage.getTotalColors());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quantizedImage.setFileName("quantized.png");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; quantizedImage.writeImage(info);<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; quantizedImage.getColors(); i++) {<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelPacket pp = quantizedImage.getColormap(i);<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Colormap[" + i + "] = (" + pp.getRed()<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ", " + pp.getGreen() + ", " + pp.getBlue() + ")");<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelPacket[] ppArray = quantizedImage.getColormap();<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; quantizedImage.getColors(); i++) {<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Colormap2[" + i + "] = ("<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ppArray[i].getRed() + ", " + ppArray[i].getGreen()<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ", " + ppArray[i].getBlue() + ")");<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create an image from scratch<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage blankImage = new MagickImage();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] pixels = new byte[200 * 100 * 4];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 200 * 100; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pixels[4 * i] = (byte) 255;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pixels[4 * i + 1] = (byte) 255;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pixels[4 * i + 2] = (byte) 255;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pixels[4 * i + 3] = (byte) 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.constituteImage(200, 100, "RGBA", pixels);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Put a red rectangle around the border<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawInfo drawInfo = new DrawInfo(new ImageInfo());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drawInfo.setPrimitive("Rectangle 10 10 190 90");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drawInfo.setStroke(PixelPacket.queryColorDatabase("red"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drawInfo.setFill(PixelPacket.queryColorDatabase("white"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.drawImage(drawInfo);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Annotate the image with a green Hello<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ImageInfo blankImageInfo = new ImageInfo();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawInfo annotateInfo = new DrawInfo(blankImageInfo);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; annotateInfo.setOpacity(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; annotateInfo.setFont("fixed");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; annotateInfo.setFill(PixelPacket.queryColorDatabase("green"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; annotateInfo.setText("Hello");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; annotateInfo.setGeometry("+30+30");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.annotateImage(annotateInfo);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.setFileName("blank.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Make the white page of the image transparent<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.transparentImage(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PixelPacket.queryColorDatabase("white"), 65535);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.setFileName("transparent.png");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blankImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Crop image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rect = new Rectangle(20, 20, 150, 120);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage cropped = image.cropImage(rect);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cropped.setFileName("cropped.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cropped.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Chop image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rect = new Rectangle(0, 0, 150, 120);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage chopped = image.chopImage(rect);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chopped.setFileName("chopped.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chopped.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Sharpen image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage sharpened = image.sharpenImage(1.0, 5.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sharpened.setFileName("sharpened.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sharpened.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Despeckle image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage despeckled = image.despeckleImage();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; despeckled.setFileName("despeckled.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; despeckled.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Convolve image<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double[] kernel = new double[9];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 9; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kernel[i] = 1.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; kernel[4] = 2.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickImage convolvedImage = image.convolveImage(3, kernel);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convolvedImage.setFileName("convolved.jpg");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convolvedImage.writeImage(info);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Finally display the image.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickWindow window = new MagickWindow(image);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.setVisible(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // MagickInfo test<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MagickInfo minfo = new MagickInfo("JPEG");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("JPG description: " + minfo.getDescription());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (MagickApiException ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println("MagickException: " + ex + ": " + ex.getReason()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ", " + ex.getDescription());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (MagickException ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println("MagickException: " + ex);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}</span></font></div>
<div><font color="#000000"></font>&nbsp;</div>
<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体">MagickWindow.java&nbsp; 在java.awt组件中显示<br />
-----------------------------------------------------------------------------------------------------------------------<br />
package images;<br />
import java.awt.Dimension;<br />
import java.awt.Frame;<br />
import java.awt.event.WindowAdapter;<br />
import java.awt.event.WindowEvent;<br />
import magick.MagickImage;<br />
import magick.util.MagickViewer;<br />
/**<br />
&nbsp;* This class implements a window that displays a MagickImage.<br />
&nbsp;*<br />
&nbsp;* @author Eric Yeo<br />
&nbsp;*/<br />
public class MagickWindow extends Frame {<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * A listener that exits the application when we receive<br />
&nbsp;&nbsp;&nbsp;&nbsp; * the window closing event.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; private final class MyListener extends WindowAdapter {<br />
&nbsp;/**<br />
&nbsp; * This method is called when the window closes.<br />
&nbsp; */<br />
&nbsp;public void windowClosing(WindowEvent event)<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.exit(0);<br />
&nbsp;}<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * We want the window size to be this big.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public Dimension getPreferredSize() {<br />
&nbsp;return new Dimension(250, 200);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * We want the window size to be at this minimum.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public Dimension getMinimumSize() {<br />
&nbsp;return new Dimension(300, 200);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Constructor.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public MagickWindow(MagickImage image)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;setResizable(true);<br />
&nbsp;addWindowListener(new MyListener());<br />
&nbsp;MagickViewer imageViewer = new MagickViewer();<br />
&nbsp;add(imageViewer, "Center");<br />
&nbsp;<br />
&nbsp;setTitle("Magick Window");<br />
&nbsp;pack();<br />
&nbsp;imageViewer.setImage(image);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</span></font></div>
<div><font color="#000000"><span style="font-size: 9pt; font-family: 宋体"><br />
&nbsp;</span></font></div>
</span></font></div>
<img src ="http://www.blogjava.net/freiberg/aggbug/145808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freiberg/" target="_blank">Endless</a> 2007-09-17 12:51 <a href="http://www.blogjava.net/freiberg/archive/2007/09/17/145808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>