Struts2 学习记录-1--Struts2中的配置文件
主要涉及3个配置文件:web.xml、struts.xml、struts.properties
1. web.xml
任何参与了web应用程序的请求与响应动作,都必须借助web.xml文件来安装这个框架。
struts2的web.xml配置可以参考 官方文档.
首先需要配置过滤器:
<filter>
<filter-name>struts2</filter-name>
<!-- struts 2.5及以上版本 -->
<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>
如果
<url-pattern>*.action</url-pattern>
<url-pattern>*.do</url-pattern>
则只处理以.do
或.action
结尾的请求
通过以上配置就可以使用struts2了。但除此之外,还可以在filter之中配置如下内容:
<init-param>
<!-- 自动加载的系列配置文件 -->
<param-name>config</param-name>
<param-value>struts-default.xml,struts-plugin.xml,/WEB-INF/struts.xml </param-value>
</init-param>
<init-param>
<!-- 配置Struts2框架要扫描的包,多个包用逗号分开。 -->
<param-name>actionPackages</param-name>
<param-value>org.apache.struts2.showcase.person</param-value> </init-param>
<!-- 配置Struts2框架的配置提供者类,多个类用逗号分开 -->
<init-param>
<param-name>configProviders</param-name>
<param-value>com.MyConfigurationProvider</param-value>
</init-param>
或者设置某些属性:
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.devMode</param-name>
<param-value>true</param-value>
</init-param>
</filter>
2. struts.xml
Struts2框架的核心配置文件,主要负责管理struts2框架中的action映射和result以及常量属性(或由struts.properties配置)。参考:
官方 Configuration Elements
Struts2 配置文件struts.xml和web.xml详解
默认情况下,Struts2的配置文件名称为struts.xml,且该文件放在src根目录下(即/WEB-INF/classes目录下、src/main/resources)。如果修改了名称或位置,则需要清晰的进行配置,方法即是上文中的filter
中的config
配置:
<init-param>
<param-name>config</param-name>
<param-value>struts-default.xml,struts-plugin.xml,struts/struts.xml</param-value>
</init-param>
struts-default.xml,struts-plugin.xml也必须加上,或者在struts.xml文件中添加include标签将两个文件包括进去。
或者采用下述配置(?)
<init-param>
<param-name>filterConfig</param-name>
<param-value>classpath:struts2/struts.xml</param-value>
</init-param>
struts.xml 配置示例
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 基础配置:常量属性 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<!-- 开发模式,在web服务器出错时会尽量打印出来 -->
<constant name="struts.devMode" value="true" />
<!-- 配置文件修改后是否自动重新部署到服务器,开发阶段可设置为true,否则需要不时重启服务器。-->
<constant name="struts.configuration.xml.reload" value="true" />
<!-- struts2是处理以.do和.action为后缀的请求url的(默认是.action)-->
<constant name="struts.action.extension" value="do,action"/>
<!-- 包含其他的struts2配置,file属性是相对/WEB-INF/classes的路径 -->
<include file="Home.xml"/>
<!-- 全局异常配置 -->
<package name="main" namespace="/" extends="struts-default">
<!--指定一个默认的Action,如果系统没有找到指定的Action,就会指定来调用这个默认的Action -->
<default-action-ref name="index" />
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="error"/>
</global-exception-mappings>
</package>
<package name="employee" extends="struts-default" namespace="/employee">
<!-- 设置整个包范围内所有Action所要应用的默认拦截器信息。一般不用设置而使用框架默认的即可 -->
<default-interceptor-ref name="crudStack"/>
<action name="delete" method="delete"
class="org.apache.struts2.showcase.action.EmployeeAction" >
<result name="error">/empmanager/editEmployee.jsp</result>
<result type="redirect">edit-${currentEmployee.empId}.action</result>
<!-- 拦截器信息,一般也不设置 -->
<interceptor-ref name="basicStack"/>
</action>
</package>
<!-- 多继承,json配置 -->
<package name="employee" extends="struts-default, json-default" namespace="/employee">
<action name="list" method="list" class="org.apache.struts2.showcase.action.EmployeeAction" >
<result>/empmanager/listEmployees.jsp</result>
<result type="json">
<param name="root">employees</param>
</result>
</action>
</package>
</struts>
特别地,对于返回json的配置(基于 struts2-json-plugin)(参考: stackoverflow例子 及 json-plugin 和 Struts2返回JSON对象的方法总结 ):
public class Struts2Action extends ActionSupport {
private String jsonString;
public String execute() {
Gson gson = new Gson();
jsonString = gson.toJson(audioTaggingService.findTagsByName(q));
return "success";
}
//没有getter的属性将不会出现在json中
public String getJsonString() {
return jsonString;
}
public void setJsonString(String jsonString) {
this.jsonString = jsonString;
}
}
配置xml。注意extends
中必须出现json-default
,可以没有struts-default
(因为json-default
继承自它)。
root
指明了要序列化为json的对象。如果action类中只有一个属性,可以不设置root。
<package name="json" extends="struts-default,json-default" >
<action name="someJsonAction" class="com.something.Struts2Action">
<result type="json">
<param name="noCache">true</param>
<param name="excludeNullProperties">true</param>
<param name="root">jsonString</param>
</result>
</action>
</package>
附:返回json还有一种简便的方法,即将生成好的json字符串写入到response
中去,返回给前端使用。对实体对象转JSON有许多组件可用,如FastJSON,GSON等。
public static void writeJson(String json)
{
//每次调用都进行初始化
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("application/json;charset=utf-8");
try
{
response.getWriter().write(json);
response.getWriter().flush();
response.getWriter().close();
}
catch (IOException e)
{ e.printStackTrace(); }
}
3. struts.properties文件
本文件主要负责配置struts2中大量的属性(struts.xml中的<constant name="" value="">
)。
部分属性:
struts.locale
:默认 en_US,指定 locate 和 encoding schema
struts.il8n.encoding
:设置默认编码集,默认值为 utf-8
struts.objectFactory
:默认值 spring
struts.objectFactory.spring.autoWire
:指定spring框架的自动装配模式,默认值 name(默认根据name属性装配)。可选值为:name/ type/auto/construtor
struts.multipart.parser
处理multipart/form-data
的MIME类型请求框架,默认 jakarta,即 common-fileupload
struts.multipart.saveDir
保存上传文件的临时路径
struts.multipart.maxSize
允许上传的最大字节数
struts.action.extension
默认为 action,为了支持.do,可设置为 "do,action"
4.注解式开发
依赖struts2-convention-plugin
。注解与基于xml配置基本是一致的。
基本无需进行配置,或者只需要极其少量的配置(针对struts.xml)。
进行全局配置:配置一个名为base
,继承自json-default
的package,便于后续使用。
<package name="base" extends="json-default,struts-default">
<!-- 这里可以设置一些全局的返回值映射关系等 -->
</package>
然后,在Action类代码中使用注解:
//若struts.xml中没有配置名为 base 的包,则 “base” 需要写成 "json-default"。如果不是json,则为"struts-default"
@ParentPackage("base")
@Namespace("/watson") //命名空间
@Results({
@Result(name = "json",type="json", params={"root","msg"})
}) //reuslt配置
public class JsonAction {
private Map<String, Object> msg;
//msg必须有getter方法才能出现在JSON中
public Map<String, Object> getMsg() {
return msg;
}
@Action(value="json")
public String json() {
msg = new HashMap<String, Object>();
msg.put("user", user);
return "json";
}
基于方法的@Result注解
@Action( value="login", //表示action的请求名称
results={ //表示结果跳转
@Result(name="success",location="/success.jsp",type="redirect"),
@Result(name="login",location="/login.jsp",type="redirect"),
@Result(name="error",location="/error.jsp",type="redirect")
},
//表示拦截器引用
interceptorRefs={@InterceptorRef("defaultStack"), @InterceptorRef("timer")},
//异常映射声明
exceptionMappings={@ExceptionMapping(exception="java.lang.Exception",result="error")}
)
public String login() throws Exception {
int i = 1/0 ;
if ("admin".equals(user.getUsercode()) && "admin".equals(user.getUserpswd())) {
Map session = ActionContext.getContext().getSession();
session.put("session_user", user);
return "success";
} else {
return "login";
}
}
5.与Spring框架集成的配置
需要struts2-spring-plugin
,参考: Struts2+Spring集成合并
<constant name="struts.objectFactory" value="spring" />
- 方案一,Struts2负责流程,Spring负责对象的创建;Action由Struts2框架负责创建;Service由Spring框架负责创建。
这种情况下,只需要按要求分别配置好Struts2和Spring即可。或者根据需要修改struts.objectFactory.spring.autoWire
等配置。
这个时候使用注解开发,Action类无需使用Spring的@Controller注解,但需加上@Scope("prototype")设为多例 - 方案二,Struts2负责流程,Spring负责对象的创建,Action和Service都由Spring框架负责创建。这是常用的集成合并方案。
主要看一下两个框架核心配置文件的和第一种方案的写法区别:
- struts2.xml的写法:
<struts>
<!-- 注意class的值,这里是Spring中bean的id,是为了在Spring中根据此值进行查找 -->
<!-- 写完整包名代表Action还是由Struts管理,action都是多例! -->
<package name="example" namespace="/user" extends="struts-default">
<action name="login" class="loginAction" method="login">
<result name="success" type="redirect">/success.jsp</result>
<result name="login" type="redirect">/login.jsp</result>
</action>
</package>
</struts>
</span>
- spring配置文件 applicatinContext.xml的写法:
<!--这里的id对应上边的class,这里的class才是真正的路径,采用了Spring的根据name自动装配的功能,当然也可以我们手动指定,
这里需要注意的是,action需要多例创建,而Spring默认为单例创建的,所以需要指定scope="prototype"-->
<bean id="loginAction" class="com.ljh.action.LoginAction" autowire="byName" scope="prototype"></bean>
<bean id="userService" class="com.ljh.service.UserService" ></bean>
</span>
如果都采用注解的方式,Action使用 @Controller注解
注:
struts2的单例多例问题
- Struts2会对每一个请求,产生一个Action的实例来处理. ---多例
- Spring的Ioc容器管理的bean默认是单实例的. ---单例