Struts2环境搭建与测试+FreeMarker
- 格式:doc
- 大小:48.00 KB
- 文档页数:7
Struct2、Hibernate3、Spring3框架搭建实战采⽤⽬前最新的struts-2.3.1.2、hibernate3.6.10.Final、spring-framework-3.1.1.RELEASE开发包,以及eclipse-jee-indigo-SR2-win32、apache-tomcat-7.0.27服务器、JDK6和mysql5做开发环境,参考了前辈的⼀篇相关⽂章,改正了其中的错误和疏漏,克服了公司分配的“新”机器每⼩时⾃动重启三次的困难,终于把环境给搭好了。
整个过程中遵循的⼀个原则是,避免引⼊⽤不到的jar包,以求搭建⼀个最⼩的SSH 运⾏环境。
⾸先创建⼀个Dynamic web project 输⼊任意名字如SSHBase。
第⼀步:加载Spring环境我们需要引⼊的包有:org.springframework.asm-3.1.1.RELEASE.jarorg.springframework.beans-3.1.1.RELEASE.jarorg.springframework.context-3.1.1.RELEASE.jarorg.springframework.core-3.1.1.RELEASE.jarorg.springframework.expression-3.1.1.RELEASE.jarorg.springframework.jdbc-3.1.1.RELEASE.jarorg.springframework.web-3.1.1.RELEASE.jarorg.springframework.orm-3.1.1.RELEASE.jar由于spring默认开启了⽇志,还需要加⼊commons-logging的jar包,否则会报错。
建议不要⼀次性加⼊应该先加最核⼼的运⾏代码看缺少什么加什么,这样就不会加多余的包进来了,spring3已经把包按功能分开,不像以前⼀个包,这样更灵活,只要运⾏我们需要的功能,⽽没⽤到的就不⽤在硬性的添加进来。
一.Struts2基础知识1. struts2的特点及配置1.1struts2与struts1的比较1)在软件设计上struts2没有struts1那样跟ServletApi和StrutsApi有着紧密的耦合,Struts2的应用可以不因爱ServletApi和StrutsApi.struts2的这种设计属于无侵入式设计,而Struts1却属于侵入式设计public class OrderListAction ectends Action//struts依赖于java2)Struts2提供了拦截器,利用拦截器可以进行AOP编程,实现如权限拦截等功能3)Struts2提供了类型转换器,我们可以把特殊的请求参数转换成我们需要的类型,在struts1中,如果我们实现同样的功能,就必须向struts1的底层实现BeanUtil注册类型转换器4)Struts2提供了支持多种表现层技术,如JSp,freeMarker等5)Struts2的输入校验可以对指定方法进行校验,解决了Struts的长久之疼6)提供了全局范围,包范围和Action范围的国际化资源文件管理实现1.2搭建struts2的开发环境1)新建web项目2)导入必要的包3)写配置文件Struts2默认的配置文件为Struts.xml,该文件需要存放在WEB-INF/classes下,该文件的配置模板如下(在m yeclipse中放在src目录下就可以了)模板在D:\Program Files\struts-2.3.4.1-all\struts-2.3.4.1\apps 解压struts2-blank.var再打开web-info/classes中的struts.x m l文件即可<?xml version="1.0"encoding="UTF-8"?><!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration2.3//EN""/dtds/struts-2.3.dtd"><struts></struts>4)在web.xm l中加入Struts2MVC框架启动配置在struts1.x中struts框架是通过Servlet启动的,在struts2中,struts框架式通过Filter 启动的,他在web.xm l中的配置如下:(D:\Program Files\struts-2.3.4.1-all\struts-2.3.4.1\apps 解压struts2-blank.var再打开Web-Info\web.xm l即可)<filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.Str utsPrepareAndExecuteFilter</filter-class><!—自从struts2.1.3以后,下面的FilterDispatcher已经标注为过时<filter-class>org.apache.struts2.dispatcher.ng.filter.FilterDispather</filter-class> --></filter><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping>在StrutsPrepareAndEXecuteFilter()方法中将会读取类路径下的默认文件struts.xml完成初始化操作。
freemarker的用法Freemarker是一种用于生成文本输出(例如HTML网页)的模板引擎。
它通常用于在Web应用程序中生成动态内容,比如将数据填充到HTML模板中。
以下是关于Freemarker的用法的一些方面:1. 模板语法,Freemarker使用类似于HTML的标签和指令来标记要填充数据的位置。
例如,使用`${variable}`语法来插入变量的值,使用`<#if>`和`<#else>`来进行条件判断,使用`<#list>`来遍历列表等等。
2. 数据模型,在使用Freemarker时,需要将数据以某种形式传递给模板引擎。
通常,这些数据以Map的形式传递,也可以是JavaBean或POJO对象。
3. 集成,Freemarker可以与多种Java框架(如Spring、Struts等)集成,以便在Web应用程序中使用。
通常,需要配置模板解析器和视图解析器来使得框架能够识别和处理Freemarker模板。
4. 自定义指令和函数,Freemarker允许用户定义自己的指令和函数,以便扩展模板的功能。
这些自定义指令和函数可以在模板中被调用,从而实现特定的逻辑或功能。
5. 资源加载,Freemarker可以从不同的位置加载模板文件,比如从文件系统、类路径、URL等。
这使得模板可以被灵活地组织和管理。
总的来说,Freemarker是一个功能强大且灵活的模板引擎,它提供了丰富的模板语法和功能,可以帮助开发人员在Web应用程序中实现灵活的动态内容生成。
希望这些信息能够帮助你更好地了解Freemarker的用法。
Struts2相关Struts2是一个按照MVC模式设计的web层框架,其实Struts2就是一个大大的filter,我们可以在web.xml文件中讲符合某种特征的所有请求交给这个filter处理,这个filter再参照一个配置文件(通常为/WEB-INF/classes/struts.xml)将各个请求分别分配给不同的action去处理!Struts2的核心FilterDispatcher, 从2.1.3版本开始, 换成了StrutsPrepareAndExecuteFilter. 官方为什么要做这个升级呢?首先看下官方给的Struts2工作原理图:Struts2工作原理(基于看完上图的理解):当一个HttpServletRequest请求来了,先经过ActionContextCleanUp过滤器,清除Action环境,再经过其他的过滤器,例如说SiteMesh和用户自定义过滤器等等, 最后到达Struts2的核心过滤器StrutsPrepareAndExecuteFilter,此时,StrutsPrepareAndExecuteFilter会去找ActionMapping看此Action路径是否存在,如果存在,则会参照Struts.xml文件产生Action的代理,并且执行Action,Struts2很多功能是靠拦截器完成的,所以这个Action代理真正调用Action的处理请求的方法的时候会经过拦截器1,2,3,才真正调用Action的方法,Action方法结束后会返回一个视图,视图也会去参照ActionMapping,还会参照Template(JSP,FreeMarker),此时,拦截器会再次拦截(说明Struts2的拦截器是进入Action和返回结果的时候都会拦截的,这比Filter好!),最后产生HttpServletResponse,相应结果!我们也看到了, 老版本上面, 我们需要的别的过滤器全部要放在Struts2的过滤器之前. 但是我现在有个需求: 我想在我的过滤器里面做一些事,需要Struts2的环境(ActionContext), 但是又需要在Struts2的Action执行之前. 这个时候, 老版本的那个过滤器就只能两眼望青天了.打个比方, 好比一个病人要做手术, 做手术需要打麻药(自定义过滤器)和动手术(Struts2的过滤器), 请问打麻药要怎么打呢? 不能让病人站着吧.. 所以首先要准备一个床(ActionContext), 之后打麻药, 再手术. 这也就是StrutsPrepareAndExecuteFilter真正的含义. 可以分成StrutsPrepareFilter,StrutsExecuteFilter, 如果没有像之前那样的需求,我们一般都用StrutsPrepareAndExecuteFilter就可以了.。
Struts2校验器类型详解一、Struts2内建校验器位于xwork-2.0.4.jar压缩包中(com.opensymphony.xwork2.validator.validators)有个文件default.xml ,该文件中定义了Struts2框架内建的校验器。
default.xml文件定义了常用的校验器类型。
首先搞清楚:struts2字段校验器与非字段校验器的区别字段校验器配置格式:<field name="被校验的字段"><field-validator type="校验器名"><!--此处需要为不同校验器指定数量不等的校验规则--><param name="参数名">参数值</param>....................<!--校验失败后的提示信息,其中key指定国际化信息的key--><message key="I18Nkey">校验失败后的提示信息</message><!--校验失败后的提示信息:建议用getText("I18Nkey"),否则可能出现Freemarker template Error--></field-vallidator><!-- 如果校验字段满足多个规则,下面可以配置多个校验器--></field>非字段校验器配置格式:<validator type="校验器名"><param name="fieldName">需要被校验的字段</param><!--此处需要为不同校验器指定数量不等的校验规则--><param name="参数名">参数值</param><!--校验失败后的提示信息,其中key指定国际化信息的key--><message key="I18Nkey">校验失败后的提示信息</message><!--校验失败后的提示信息:建议用getText("I18Nkey"),否则可能出现Freemarker template Error--></validator>非字段校验:先指定校验器:由谁来校验,来校验谁!字段校验器:先指定校验的属性:我来校验谁,由谁来校验!下面是对应在包中的类:<validators><validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/><validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/><validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/><validator name="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/><validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/><validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/><validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/><validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/><validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/><validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/><validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/><validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/><validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/><validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/><validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/><validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/></validators>二、各种类型校验器1、类型转换检验器:(1)非字段校验:<validator type="conversion"><param name="fieldName">myField</param><message>类型转换错误</message><param name ="repopulateField">true</param></validator>(2)字段校验:<field name="myField"><field-validator type="conversion"><message>类型转换错误</message><param name ="repopulateField">true</param></field-validator></field>fieldName:该参数指定检查是否存在转换异常的字段名称,如果是字段校验,则不用指定该参数。
一、准备工作1.1 下载文件可以从/站点下载最新的freemarker.jar包(目前最新版本是2.3.18)与eclipse插件(最新版本是0.9.14)。
1.2 安装eclipse插件将下载来的eclipse插件解压缩到本地磁盘,更改hudson.freemarker_ide_0.9.14文件夹中的freemarker-2.3.6.jar文件更改成最新版本的freemarker-2.3.18.jar,并且将META-INF/MANIFEST.MF文件中的Bundle-ClassPath属性值修改为freemarker-2.3.18.jar。
最后将hudson.freemarker_ide_0.9.14放到eclipse的plugins目录中,完成eclipse 插件的安装。
1.3 freemarker文档下载从/官方网站中下载帮助文档(也有中文的手册)二、freemarker的使用2.1 简介2.1.1 FTL tag标签由于freemarker tag标签是属于freemarker的指令,它们仅仅是freemarker 处理过程中的信息,而不会输出到页面上,所以它们与html标签有一些区别。
这些标签都是以#号开头,如<#import "/public/work_public.ftl" as public>。
但用户自定义的标签是以@符号开头,如在freemarker中使用struts标签:<@s.if test="results!=null&&results.size()!=0">注意FTL标签不可以在其他FTL标签和插值中使用(注释可以在FTL标签和插值中使用,因为它在解析时,整个注释都将抛弃,不会影响具体代码),如下面这样就是一个错误的写法:<#if <#include 'foo'>='bar'>...</#if>2.1.2 注释freemarker的文档注释与html相似,但它是以<#--和-->来分割的。
Freemarker简介及标签详解大全◆Freemarker简介FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图)FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件FreeMarker与容器无关,因为它并不知道HTTP或Servlet;FreeMarker同样可以应用于非Web应用程序环境FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库FreeMarker是免费的而且你还可以通过Eclipse的插件来编辑FreeMarker,经过验证,FreeMarker 最好的Eclipse 编辑插件是JBoss Tools。
FreeMarker特性1、通用目标能够生成各种文本:HTML、XML、RTF、Java源代码等等易于嵌入到你的产品中:轻量级;不需要Servlet环境插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等你可以按你所需生成文本:保存到本地文件;作为Email发送;从Web应用程序发送它返回给Web浏览器2、强大的模板语言所有常用的指令:include、if/elseif/else、循环结构在模板中创建和改变变量几乎在任何地方都可以使用复杂表达式来指定值命名的宏,可以具有位置参数和嵌套内容名字空间有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心名字冲突输出转换块:在嵌套模板片段生成输出时,转换HTML 转义、压缩、语法高亮等等;你可以定义自己的转换3、通用数据模型FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰4、为Web准备在模板语言中内建处理典型Web相关任务(如HTML转义)的结构能够集成到Model2 Web应用框架中作为JSP的替代支持JSP标记库为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员5、智能的国际化和本地化字符集智能化(内部使用UNICODE)数字格式本地化敏感日期和时间格式本地化敏感非US字符集可以用作标识(如变量名)多种不同语言的相同模板6、强大的XML处理能力<#recurse> 和<#visit>指令(2.3版本)用于递归遍历XML树在模板中清楚和直觉的访问XML对象模型◆Freemarker 标签完全解析1. assignassign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,assign 指令的用法有多种,包含创建或替换一个顶层变量,或者创建或替换多个变量等。
STRUTS2实验报告1. 系统分析与设计 1.1 系统功能描述本系统是个非常简单的注册、登录系统。
本系统的实现是基于struts2、spring、hibernate三个框架,系统功能单一,业务逻辑简单。
当用户注册信用户时,就是向系统中增加一个新用户,对应的数据库增加一条记录。
当用户输入注册信息时,系统提供了基本的输入验证判断用户输入是否合法,只有当用户输入满足基本输入要求时,才会被提交到实际的登录系统,进行实际的登录处理。
系统还使用了随机产生的图形验证码来防止刷新,防止用户通过单击浏览器的书安心按钮来重复注册多个用户。
系统还提供了一种ajax方式来验证用户输入的注册名是否有效,系统要求所有的用户名不能重复。
故当用户输完用户名后,系统立即在页面上方提示用户该用户名是否可用,如果系统中没有该用户名,则系统提示该用户名可用;否则提示用户该用户名重复,用户必须重新选择用户名注册。
当用户注册一个新用户名之后,就可以使用系统的登录功能来登录系统了,用户输入登录用的用户名、密码后,系统一样提供了基本的输入校验。
除此之外,系统还采用了随机产生图形验证码来防止恶意用户的暴力破解,系统随机生成一个图形验证码,而用户登录必须输入图形验证码中显示的字符串,只有用户输入的字符串和系统随机生成的验证码字符相同时,系统才允许用户登录。
1.2 系统功能流程1.3 数据库设计相关的映射文件:<hibernate-mappingpackage= <classname=user table=user_table> <id name=idcolumn=user_id> <generatorclass=identity</id> nique=true/><propertyname==user_passnot-null=true length=50/> <propertyname=emaillength=100/> </class> <propertyname=usercolumn=</hibernate-mapping> 一旦提供了上面的映射文件,hibernate就可以理解user和user_table之间的对应关系。
freemarker使用流程Freemarker使用流程Freemarker是一款流行的模板引擎,广泛应用于Java Web开发中。
它能够有效地将数据与展示分离,提高开发效率和代码的可维护性。
下面将介绍Freemarker的使用流程,帮助读者更好地理解和运用这一工具。
1. 熟悉Freemarker语法在使用Freemarker之前,首先需要熟悉其语法规则。
Freemarker 使用类似于HTML的标签和表达式来动态生成内容。
了解Freemarker的基本语法结构对于后续的开发至关重要。
2. 配置Freemarker环境在项目中引入Freemarker依赖,并配置Freemarker的相关参数,如模板文件的路径、编码方式等。
确保Freemarker能够正常工作,并与项目的其他组件协调配合。
3. 创建Freemarker模板编写Freemarker模板文件,定义页面的结构和内容。
在模板中可以使用Freemarker的标签和表达式来引用数据、控制流程和展示内容。
合理设计模板结构,提高页面的可读性和可维护性。
4. 准备数据模型准备与模板对应的数据模型,包括需要在页面中展示的数据内容。
数据模型可以是JavaBean、Map等形式,确保数据的准确性和完整性,以便在模板中进行引用和展示。
5. 渲染模板将数据模型与Freemarker模板进行结合,通过Freemarker引擎进行渲染。
在渲染过程中,Freemarker会根据模板中的标签和表达式动态生成最终的页面内容,将数据填充到指定位置。
6. 输出页面内容将渲染后的页面内容输出到浏览器或其他客户端,让用户可以看到最终的页面效果。
确保页面的呈现与预期一致,检查数据的展示是否准确,页面的布局是否符合设计要求。
7. 调试和优化在使用Freemarker的过程中,可能会遇到一些问题和性能瓶颈。
及时调试代码,查找并解决bug,优化页面性能和加载速度。
保持代码的简洁和高效,提升用户体验和开发效率。
1.将org.apache.struts2.views.freemarker.FreemarkerServlet类复制到src下。
FreemarkerServlet.java如下:package org.apache.struts2.views.freemarker;import java.io.FileNotFoundException;import java.io.IOException;import java.util.Locale;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts2.RequestUtils;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.inject.Inject;import com.opensymphony.xwork2.util.V alueStack;import freemarker.template.Configuration;import freemarker.template.ObjectWrapper;import freemarker.template.Template;import freemarker.template.TemplateException;import freemarker.template.TemplateModel;import freemarker.template.TemplateModelException;public class FreemarkerServlet extends HttpServlet {protected Configuration configuration;private static FreemarkerManager freemarkerManager;@Injectpublic static void setFreemarkerManager(FreemarkerManager mgr) {freemarkerManager = mgr;}public FreemarkerServlet() {super();}final public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setAttribute("struts.freemarker.servlet", this);process(request, response);}final public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setAttribute("struts.freemarker.servlet", this);process(request, response);}public void init() throws ServletException {try {configuration = createConfiguration();} catch (TemplateException e) {throw new ServletException("could not configure Freemarker", e);}}/*** This method is called from process() to obtain the* FreeMarker object wrapper object that this result will use* for adapting objects into* template models.. This is a hook that allows you* to custom-configure the wrapper object in a subclass.* <p/>* <b>* The default implementation returns @see Configuration#getOb jectWrapper()* </b>*/protected ObjectWrapper getObjectWrapper() {return configuration.getObjectWrapper();}protected Configuration createConfiguration() throws TemplateException {return freemarkerManager.getConfiguration(getServletContext());}protected TemplateModel createModel(ObjectWrapper wrapper, ServletContext servletContext, HttpServletRequest request, HttpServletResponse response) throws TemplateModelException {V alueStack stack = ServletActionContext.getContext().getV alueStack();Object action = null;if (ServletActionContext.getContext().getActionInvocation() != null) {action = ServletActionContext.getContext().getActionInvocation().getAction();}TemplateModel model = freemarkerManager.buildTemplateModel(stack, action, servletContext, request, response, wrapper);return model;}/*** Returns the locale used for the* {@link Configuration#getTemplate(String, Locale)} call.* The base implementation simply returns the locale setting of the* configuration. Override this method to provide different behaviour, i.e.* to use the locale indicated in the request.*/protected Locale deduceLocale(String templatePath, HttpServletRequest request, HttpServletResponse response) {return configuration.getLocale();}/*** Called after the execution returns from template.process().* This is a generic hook you might use in subclasses to perform a specific* action after the template is processed. It will be invoked even if the* template processing throws an exception. By default does nothing.** @param request the actual HTTP request* @param response the actual HTTP response* @param template the template that was executed* @param data the data that was passed to the template*/protected void postTemplateProcess(HttpServletRequest request, HttpServletResponse response, Template template, TemplateModel data) throws ServletException, IOException { }// /**// * If the parameter "nocache" was set to true, generate a set of headers// * that will advise the HTTP client not to cache the returned page.// */// private void setBrowserCachingPolicy(HttpServletResponse response)// {// if (nocache)// {// // HTTP 1.1 browsers should defeat caching on this header// response.setHeader("Cache-Control", "no-cache");// // HTTP 1.0 browsers should defeat caching on this header// response.setHeader("Pragma", "no-cache");// // Last resort for those that ignore all of the above// response.setHeader("Expires", EXPIRA TION_DA TE);// }// }/*** Called before the execution is passed to template.process().* This is a generic hook you might use in subclasses to perform a specific* action before the template is processed. By default does nothing.* A typical action to perform here is to inject application-specific* objects into the model root** @param request the actual HTTP request* @param response the actual HTTP response* @param template the template that will get executed* @param data the data that will be passed to the template* @return true to process the template, false to suppress template processing.*/protected boolean preTemplateProcess(HttpServletRequest request, HttpServletResponse response, Template template, TemplateModel data) throws ServletException, IOException { return true;}/*** Maps the request URL to a template path that is passed to* {@link Configuration#getTemplate(String, Locale)}. Y ou can override it* (i.e. to provide advanced rewriting capabilities), but you are strongly* encouraged to call the overridden method first, then only modify its* return value.** @param request the currently processed request* @return a String representing the template path*/protected String requestUrlToTemplatePath(HttpServletRequest request) {// First, see if it is an included requestString includeServletPath = (String) request.getAttribute("javax.servlet.include.servlet_path");if (includeServletPath != null) {// Try path info; only if that's null (servlet is mapped to an// URL extension instead of to prefix) use servlet path.String includePathInfo = (String)request.getAttribute("javax.servlet.include.path_info");return (includePathInfo == null) ? includeServletPath : includePathInfo;}// Seems that the servlet was not called as the result of a// RequestDispatcher.include(...). Try pathInfo then servletPath again,// only now directly on the request object:String path = request.getPathInfo();if (path != null) {return path;}path = RequestUtils.getServletPath(request);if (path != null) {return path;}// Seems that it is a servlet mapped with prefix, and there was no extra path info.return "";}private void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String path = requestUrlToTemplatePath(request);Template template = null;try {template = configuration.getTemplate(path, deduceLocale(path, request, response));} catch (FileNotFoundException e) {response.sendError(HttpServletResponse.SC_NOT_FOUND);return;}Object attrContentType = template.getCustomAttribute("content_type");if (attrContentType != null) {response.setContentType(attrContentType.toString());} else {response.setContentType("text/html; charset=" + template.getEncoding());}// // Set cache policy// setBrowserCachingPolicy(response);ServletContext servletContext = getServletContext();try {TemplateModel model = createModel(getObjectWrapper(), servletContext, request, response);// Give subclasses a chance to hook into preprocessingif (preTemplateProcess(request, response, template, model)) {try {// Process the templatetemplate.process(model, response.getWriter());} finally {// Give subclasses a chance to hook into postprocessingpostTemplateProcess(request, response, template, model);}}} catch (TemplateException te) {// only throw a servlet exception if not a debug handler// this is what the original freemarker.ext.servlet.FreemarkerServlet doesif ((configuration.getTemplateExceptionHandler() != freemarker.template.TemplateExceptionHandler.HTML_DEBUG_HANDLER) && (configuration.getTemplateExceptionHandler() != freemarker.template.TemplateExceptionHandler.DEBUG_HANDLER)){throw new ServletException(te);}}}}2.修改web.xml<?xml version="1.0" encoding="UTF-8"?><!-- web-app是Web应用配置文件的根元素,指定Web应用的Schema信息--><web-app id="WebApp_9" version="2.4" xmlns="/xml/ns/j2ee" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="/xml/ns/j2ee /xml/ns/j2ee/web-app_2_4.xsd"><display-name>Struts Blank</display-name><!-- 定义核心Filter的名字--><filter><filter-name>struts2</filter-name><!-- 定义核心Filter的实现类--><filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter><!-- FilterDispatcher用来初始化Struts 2并且处理所有的Web请求--><filter-mapping><filter-name>struts2</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>freemarker</servlet-name><servlet-class>org.apache.struts2.views.freemarker.FreemarkerServlet</servlet-class><load-on-startup>2</load-on-startup></servlet><servlet-mapping><servlet-name>freemarker</servlet-name><url-pattern>*.ftl</url-pattern></servlet-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>。