1.增加Struts2的jar包
2.修改web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>cn.neilone.OgnlListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
这里需要增加一个监听器,代码如下
package cn.neilone;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import ognl.OgnlRuntime;
public class OgnlListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
OgnlRuntime.setSecurityManager(null);
}
}
3.增加struts.xml文件
该文件与普通的javaee工程无异,仅贴一份我自己的拷贝
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/index.jsp</result>
</action>
<action name="hello" class="cn.neilone.struts2.HelloAction" method="sayHello">
<result>/sayHello.jsp</result>
</action>
</package>
</struts>
4.一个问题的解决
新建包freemarker.core,添加类TextBlock.java,源码如下
package freemarker.core;
import java.io.IOException;
public class TextBlock extends TemplateElement {
private static final char[] EMPTY_CHAR_ARRAY = new char[0];
static final TextBlock EMPTY_BLOCK = new TextBlock(EMPTY_CHAR_ARRAY, false);
// We're using char[] instead of String for storing the text block because
// Writer.write(String) involves copying the String contents to a char[]
// using String.getChars(), and then calling Writer.write(char[]).By
// using Writer.write(char[]) directly, we avoid array copying on each
// write.
private char[] text;
private final boolean unparsed;
public TextBlock(String text) {
this(text, false);
}
public TextBlock(String text, boolean unparsed) {
this(text.toCharArray(), unparsed);
}
private TextBlock(char[] text, boolean unparsed) {
this.text = text;
this.unparsed = unparsed;
}
/**
* Simply outputs the text.
*/
public void accept(Environment env) throws IOException {
env.getOut().write(text);
}
public String getCanonicalForm() {
String text = new String(this.text);
if (unparsed) {
return "<#noparse>" + text + "</#noparse>";
}
return text;
}
public String getDescription() {
String s = new String(text).trim();
if (s.length() == 0) {
return "whitespace";
}
if (s.length() > 20) {
s = s.substring(0, 20) + "...";
s = s.replace('\n', ' ');
s = s.replace('\r', ' ');
}
return "text block (" + s + ")";
}
TemplateElement postParseCleanup(boolean stripWhitespace) {
if (text.length == 0)
return this;
int openingCharsToStrip = 0, trailingCharsToStrip = 0;
boolean deliberateLeftTrim = deliberateLeftTrim();
boolean deliberateRightTrim = deliberateRightTrim();
if (!stripWhitespace || text.length == 0) {
return this;
}
if (parent.parent == null && previousSibling() == null)
return this;
if (!deliberateLeftTrim) {
trailingCharsToStrip = trailingCharsToStrip();
}
if (!deliberateRightTrim) {
openingCharsToStrip = openingCharsToStrip();
}
if (openingCharsToStrip == 0 && trailingCharsToStrip == 0) {
return this;
}
this.text = substring(text, openingCharsToStrip, text.length
- trailingCharsToStrip);
if (openingCharsToStrip > 0) {
this.beginLine++;
this.beginColumn = 1;
}
if (trailingCharsToStrip > 0) {
this.endColumn = 0;
}
return this;
}
/**
* Scans forward the nodes on the same line to see whether there is a
* deliberate left trim in effect. Returns true if the left trim was
* present.
*/
private boolean deliberateLeftTrim() {
boolean result = false;
for (TemplateElement elem = this.nextTerminalNode(); elem != null
&& elem.beginLine == this.endLine; elem = elem
.nextTerminalNode()) {
if (elem instanceof TrimInstruction) {
TrimInstruction ti = (TrimInstruction) elem;
if (!ti.left && !ti.right) {
result = true;
}
if (ti.left) {
result = true;
int lastNewLineIndex = lastNewLineIndex();
if (lastNewLineIndex >= 0 || beginColumn == 1) {
char[] firstPart = substring(text, 0,
lastNewLineIndex + 1);
char[] lastLine = substring(text, 1 + lastNewLineIndex);
if (trim(lastLine).length == 0) {
this.text = firstPart;
this.endColumn = 0;
} else {
int i = 0;
while (Character.isWhitespace(lastLine[i])) {
i++;
}
char[] printablePart = substring(lastLine, i);
this.text = concat(firstPart, printablePart);
}
}
}
}
}
if (result) {
}
return result;
}
/**
* Checks for the presence of a t or rt directive on the same line. Returns
* true if the right trim directive was present.
*/
private boolean deliberateRightTrim() {
boolean result = false;
for (TemplateElement elem = this.prevTerminalNode(); elem != null
&& elem.endLine == this.beginLine; elem = elem
.prevTerminalNode()) {
if (elem instanceof TrimInstruction) {
TrimInstruction ti = (TrimInstruction) elem;
if (!ti.left && !ti.right) {
result = true;
}
if (ti.right) {
result = true;
int firstLineIndex = firstNewLineIndex() + 1;
if (firstLineIndex == 0) {
return false;
}
if (text.length > firstLineIndex
&& text[firstLineIndex - 1] == '\r'
&& text[firstLineIndex] == '\n') {
firstLineIndex++;
}
char[] trailingPart = substring(text, firstLineIndex);
char[] openingPart = substring(text, 0, firstLineIndex);
if (trim(openingPart).length == 0) {
this.text = trailingPart;
this.beginLine++;
this.beginColumn = 1;
} else {
int lastNonWS = openingPart.length - 1;
while (Character.isWhitespace(text[lastNonWS])) {
lastNonWS--;
}
char[] printablePart = substring(text, 0, lastNonWS + 1);
if (trim(trailingPart).length == 0) {
// THIS BLOCK IS HEINOUS! THERE MUST BE A BETTER
// WAY! REVISIT (JR)
boolean trimTrailingPart = true;
for (TemplateElement te = this.nextTerminalNode(); te != null
&& te.beginLine == this.endLine; te = te
.nextTerminalNode()) {
if (te.heedsOpeningWhitespace()) {
trimTrailingPart = false;
}
if (te instanceof TrimInstruction
&& ((TrimInstruction) te).left) {
trimTrailingPart = true;
break;
}
}
if (trimTrailingPart)
trailingPart = EMPTY_CHAR_ARRAY;
}
this.text = concat(printablePart, trailingPart);
}
}
}
}
return result;
}
/*
* private String leftTrim(String s) { int i =0; while (i<s.length()) { if
* (!Character.isWhitespace(s.charAt(i))) break; ++i; } return
* s.substring(i); }
*/
private int firstNewLineIndex() {
String content = new String(text);
int newlineIndex1 = content.indexOf('\n');
int newlineIndex2 = content.indexOf('\r');
int result = newlineIndex1 >= 0 ? newlineIndex1 : newlineIndex2;
if (newlineIndex1 >= 0 && newlineIndex2 >= 0) {
result = Math.min(newlineIndex1, newlineIndex2);
}
return result;
}
private int lastNewLineIndex() {
String content = new String(text);
return Math.max(content.lastIndexOf('\r'), content.lastIndexOf('\n'));
}
/**
* figures out how many opening whitespace characters to strip in the
* post-parse cleanup phase.
*/
private int openingCharsToStrip() {
int newlineIndex = firstNewLineIndex();
if (newlineIndex == -1 && beginColumn != 1) {
return 0;
}
++newlineIndex;
if (text.length > newlineIndex) {
if (newlineIndex > 0 && text[newlineIndex - 1] == '\r'
&& text[newlineIndex] == '\n') {
++newlineIndex;
}
}
if (new String(text).substring(0, newlineIndex).trim().length() > 0) {
return 0;
}
// We look at the preceding elements on the line to see if we should
// strip the opening newline and any whitespace preceding it.
for (TemplateElement elem = this.prevTerminalNode(); elem != null
&& elem.endLine == this.beginLine; elem = elem
.prevTerminalNode()) {
if (elem.heedsOpeningWhitespace()) {
return 0;
}
}
return newlineIndex;
}
/**
* figures out how many trailing whitespace characters to strip in the
* post-parse cleanup phase.
*/
private int trailingCharsToStrip() {
String content = new String(text);
int lastNewlineIndex = lastNewLineIndex();
if (lastNewlineIndex == -1 && beginColumn != 1) {
return 0;
}
String substring = content.substring(lastNewlineIndex + 1);
if (substring.trim().length() > 0) {
return 0;
}
// We look at the elements afterward on the same line to see if we
// should strip any whitespace after the last newline
for (TemplateElement elem = this.nextTerminalNode(); elem != null
&& elem.beginLine == this.endLine; elem = elem
.nextTerminalNode()) {
if (elem.heedsTrailingWhitespace()) {
return 0;
}
}
return substring.length();
}
boolean heedsTrailingWhitespace() {
if (isIgnorable()) {
return false;
}
for (int i = 0; i < text.length; i++) {
char c = text[i];
if (c == '\n' || c == '\r') {
return false;
}
if (!Character.isWhitespace(c)) {
return true;
}
}
return true;
}
boolean heedsOpeningWhitespace() {
if (isIgnorable()) {
return false;
}
for (int i = text.length - 1; i >= 0; i--) {
char c = text[i];
if (c == '\n' || c == '\r') {
return false;
}
if (!Character.isWhitespace(c)) {
return true;
}
}
return true;
}
boolean isIgnorable() {
if (text == null || text.length == 0) {
return true;
}
if (!isWhitespace()) {
return false;
}
// trick here
boolean atTopLevel = true;
TemplateElement prevSibling = previousSibling();
TemplateElement nextSibling = nextSibling();
return ((prevSibling == null && atTopLevel) || nonOutputtingType(prevSibling))
&& ((nextSibling == null && atTopLevel) || nonOutputtingType(nextSibling));
}
private boolean nonOutputtingType(TemplateElement element) {
return (element instanceof Macro || element instanceof Assignment
|| element instanceof AssignmentInstruction
|| element instanceof PropertySetting
|| element instanceof LibraryLoad || element instanceof Comment);
}
private static char[] substring(char[] c, int from, int to) {
char[] c2 = new char[to - from];
System.arraycopy(c, from, c2, 0, c2.length);
return c2;
}
private static char[] substring(char[] c, int from) {
return substring(c, from, c.length);
}
private static char[] trim(char[] c) {
if (c.length == 0) {
return c;
}
return new String(c).trim().toCharArray();
}
private static char[] concat(char[] c1, char[] c2) {
char[] c = new char[c1.length + c2.length];
System.arraycopy(c1, 0, c, 0, c1.length);
System.arraycopy(c2, 0, c, c1.length, c2.length);
return c;
}
boolean isWhitespace() {
return text == null || trim(text).length == 0;
}
}
5.新建一二Action即可测试
包结构如下
发表评论
-
GAE中JDO出现的持久化问题
2010-09-16 08:35 1154The class "The class " ... -
GAE中spring无法识别jdoconfig
2010-09-15 09:31 857准备在GAE中用spring管理JDO,无奈搞了n久仍然没有搞 ... -
org.apache.jasper.JasperException: java.security.AccessControlException
2010-09-14 15:24 1337今天开始将spring整合到GAE上,竟然出现了问题。根据网络 ... -
java.lang.NoClassDefFoundError: javax.swing.tree.TreeNode is a restricted class
2010-09-13 20:32 1846今天在GAE中配置Struts中出现了不少问题,以下是其中一个 ... -
Provider org.apache.xalan.processor.TransformerFactoryImpl not found
2010-09-13 19:20 1982javax.xml.transform.Transformer ... -
GAE原来有Eclipse 3.5的插件
2010-09-13 13:53 1440一直在看Google官方GAE的教程,也就傻傻地认为Googl ...
相关推荐
12. **Weld 1.0.1 rc2发布,支持GAE**:Weld是CDI(Contexts and Dependency Injection)规范的参考实现,1.0.1 rc2版本增加了对Google App Engine的支持,使开发者能够在GAE平台上利用CDI进行更灵活的应用开发。...
2. **数据存储**:GAE提供了NoSQL数据库服务,即Datastore,它支持高可用性和水平扩展。 3. **任务队列**:用于处理异步任务,如发送电子邮件或执行后台计算。 4. **API访问**:开发者可以利用Google的多种服务,如...
SSO单点登录概要设计说明书.doc
奥塔北煤矿6.0 Mta新井设计说明书.docx
内容概要:本文详细介绍了基于S7-200 PLC和组态王软件构建喷泉控制系统的全过程。首先明确了系统的IO分配,包括启动按钮、停止按钮以及喷泉水泵的连接方式。接着展示了梯形图程序的设计,涵盖了基本的启停控制逻辑、定时循环和模式切换机制。随后提供了详细的接线图原理图,解释了输入输出部分的具体接线方法。最后讲述了组态王的画面设计,包括创建工程、定义变量和绘制监控界面等步骤。此外还分享了一些调试过程中遇到的问题及解决方案。 适合人群:对自动化控制感兴趣的初学者和技术人员,尤其是那些希望深入了解PLC编程和人机界面设计的人群。 使用场景及目标:适用于小型喷泉项目的实际控制系统开发,旨在帮助读者掌握PLC编程技巧、熟悉组态软件的应用,并能够独立完成类似的自动化控制系统设计。 其他说明:文中不仅包含了理论知识讲解,还附带了许多实践经验分享,如硬件配置建议、常见错误规避措施等,有助于提高实际操作能力。
计算机二级PPT精选二十套(标红)
保险公司IT变更管理流程设计说明书.doc.doc
毕业设计说明书A江坝后式厂房双曲拱坝设计.pdf
内容概要:文档《计算机二级MS精选300道选择题.docx》涵盖了计算机二级考试中Microsoft Office软件(Word、Excel、PowerPoint)及计算机基础知识的选择题。题目涉及软件操作技巧、功能应用、常见问题解决等方面,旨在帮助考生熟悉并掌握相关知识点,提高应试能力。文档内容详尽,涵盖面广,从基础操作到高级应用均有涉及,适合考生全面复习备考。 适用人群:准备参加计算机二级考试的学生及相关从业人员,特别是需要强化Office软件操作技能和计算机基础知识的人员。 使用场景及目标:①考生可以在复习过程中使用这些选择题进行自我检测,巩固所学知识;②教师可以将其作为教学辅助材料,帮助学生更好地理解和掌握课程内容;③培训机构可以用这些题目作为测试题库,评估学员的学习效果。 其他说明:文档不仅提供了大量的选择题,还详细解析了每道题目的答案,有助于考生深入理解知识点。此外,题目内容紧跟最新考试大纲,确保考生能够获得最有效的备考资料。
内容概要:本文介绍了一种创新的方法,利用多目标黏菌优化算法(MOSMA)来优化支持向量机(SVM)的参数C和gamma,从而提高回归预测的效果。首先详细解释了MOSMA的工作原理,包括黏菌权重更新、快速非支配排序以及自适应参数调整等关键技术点。接着展示了具体的Python代码实现,涵盖数据预处理、适应度函数定义、参数更新规则等方面。实验结果显示,在风电功率预测等多个应用场景中,相较于传统的网格搜索方法,MOSMA能够更快更有效地找到最优参数组合,显著提升了预测性能。 适合人群:从事机器学习研究或应用开发的技术人员,尤其是关注SVM参数优化及回归预测领域的从业者。 使用场景及目标:适用于需要进行高效参数寻优的回归预测任务,如风电功率预测、设备负载预测等。主要目标是通过改进SVM参数配置,获得更高的预测精度和更好的泛化能力。 其他说明:文中提供了完整的代码示例和详细的实施步骤指导,帮助读者快速理解和应用这一先进的优化技术。此外,还讨论了一些常见的注意事项和技术细节,如数据标准化、参数范围设定、并行化改造等。
毕业设计 某油库设计说明书.pdf
Q235钢板焊接工艺设计说明书.docx
75t循环流化床锅炉设计说明书.doc
(最新修订版)直列四缸柴油机配气机构设计毕业论文设计说明书.doc
内容概要:《deepseek大模型生态报告 2025年2月》详细介绍了DeepSeek大模型的背景、应用现状、技术特点及其产业生态。DeepSeek由杭州深度求索公司创立,通过一系列技术创新,如多层注意力架构(MLA)、FP8混合精度训练框架、DualPipe跨节点通信等,显著降低了训练成本和提高了模型性能。DeepSeek在国内和国际市场迅速崛起,登顶苹果应用商店免费APP下载排行榜,并被多家企业和机构接入,包括华为、三大运营商、微软、英伟达等。其开源策略和低成本优势对全球科技供应链和资本市场产生了深远影响,尤其是在AI领域。 适合人群:对人工智能、大模型技术感兴趣的科技爱好者、研究人员、企业家及政策制定者。 使用场景及目标:①了解DeepSeek大模型的技术创新和应用现状;②探讨DeepSeek对全球AI产业生态的影响;③分析DeepSeek在不同行业(如金融、医疗、教育、制造等)的具体应用案例。 其他说明:报告还涵盖了各国政府及相关机构对DeepSeek的态度和政策回应,以及DeepSeek对未来AI技术发展和国际竞争格局的启示。此外,报告深入剖析了DeepSeek在技术架构、数据策略和工程实践方面的突破,揭示了其成功背后的组织文化和创新机制。
内容概要:本文详细介绍了利用粒子群算法解决电动汽车区域综合能源系统中光伏电站、充电桩运营商和电网公司在定价上的三方博弈问题。通过MATLAB代码实现了粒子群算法的具体应用,包括参数设置、适应度函数设计、粒子更新策略以及结果可视化。文中展示了如何将三方定价变量编码成多维粒子,并通过目标函数计算和约束处理确保粒子在合理的解空间内搜索最优解。最终得到的电价曲线反映了不同时间段内的供需变化,验证了算法的有效性和实用性。 适合人群:从事能源系统优化、智能算法应用的研究人员和技术开发者。 使用场景及目标:适用于需要进行能源系统优化调度的场景,特别是涉及多方利益协调的问题。目标是找到光伏电价、充电桩电价和电网电价的最佳组合,使得三方利益达到最优平衡。 其他说明:建议在调试过程中关注特定时段的电价突变,适当调整参数如社会认知系数和社会学习因子,以获得更好的收敛效果。此外,初始粒子的位置选择对收敛速度有很大影响,推荐采用高斯扰动等方法进行初始化。
WY02锥齿轮的加工工艺规程及工时定额计算 课程设计说明书.docx
项目管理制度范文.docx
内容概要:本文深入探讨了双馈风力发电机(DFIG)的仿真建模及其关键技术模块。首先介绍了最大功率跟踪(MPPT)模块的工作原理,利用爬山算法优化风能利用率。接着详细讲解了转子侧变流器的矢量控制,包括坐标变换、PI调节器参数设定以及抗饱和处理。文中还讨论了网侧变流器的直流电压控制方法,强调了双闭环结构的重要性,并分享了低电压穿越仿真的实践经验。此外,文章详细解释了功率解耦控制和变速恒频实现的技术细节,提供了丰富的故障案例和调试技巧。 适合人群:从事风电工程研究和技术开发的专业人士,尤其是对DFIG仿真建模感兴趣的工程师和研究人员。 使用场景及目标:适用于希望深入了解DFIG内部机制的研究人员,帮助他们掌握从基本原理到复杂控制策略的设计与实现。同时,也为实际工程项目提供宝贵的调试经验和故障排除指南。 其他说明:文章不仅涵盖了理论分析,还包括大量实用的代码片段和具体的参数配置建议,确保读者能够顺利构建并运行仿真模型。
内容概要:本文详细介绍了如何利用Matlab2016的Simulink进行统一电能质量变换器(UPQC)的仿真,重点探讨了IP-IQ检测方法及其在电压和电流补偿中的应用。文中首先描述了UPQC的整体结构,包括串联和并联逆变器的设计。接着深入讲解了IP-IQ检测的具体实现步骤,包括三相锁相环同步、坐标变换以及低通滤波器的应用。此外,文章还讨论了电压和电流补偿的控制策略,特别是双闭环控制和SVPWM模块的使用。作者分享了许多调试经验和常见问题的解决方案,如谐波滤波器的选择、PI控制器参数调整、仿真步长设置等。最终展示了仿真结果,证明了该方法的有效性。 适合人群:从事电能质量研究和技术开发的专业人士,尤其是有一定Matlab/Simulink基础的研究人员和工程师。 使用场景及目标:适用于希望深入了解UPQC工作原理和仿真实现的技术人员,帮助他们掌握IP-IQ检测方法和补偿控制策略,提高电能质量问题的解决能力。 其他说明:文中提供了详细的代码片段和调试技巧,有助于读者快速上手并优化自己的仿真模型。