- 浏览: 333919 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (59)
- wicket (1)
- java (24)
- js (27)
- xml (3)
- Android (1)
- 服务器 (7)
- 数据库 (7)
- spring (1)
- hibernate (1)
- ssh (6)
- web (25)
- oracle (1)
- 函数 (2)
- mysql (1)
- 手机 (6)
- javascript (21)
- session (3)
- cookie (4)
- struts (1)
- ngnix (1)
- 软件使用 (2)
- linux (1)
- vi (1)
- 前端 (6)
- javascrip (2)
- html (3)
- js css (2)
- 正则 (1)
- ajax (1)
- toast (1)
- 消息提示 (1)
- 确认弹窗 (1)
- springmvc (1)
- 倒计时 (1)
最新评论
-
wenm168:
美观的图片上传前预览效果:http://www.anyrt.c ...
JavaScript 图片的上传前预览(兼容所有浏览器) -
口弦1992:
我的ie9并没有图片预览出来啊。
JavaScript 图片的上传前预览(兼容所有浏览器) -
axie1234567:
分享的东西很有用。
java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能) -
wyl4728:
32个赞
mysql函数大全 -
yu_long:
seeker.getCountry(ip);
解析出来的 ...
根据IP地址获取所在地
struts1 7大组件
ActionServlet 控制器
Action 包含事务逻辑
ActionForm 显示模块数据 数据模型
ActionMapping 帮助ActionServlet控制器将请求映射到操作
ActionForward 用来指示操作转移的对象
ActionError 用来存储和回收错误
Struts标记库 可以减轻开发显示层次的工作
mvc
model------actionform
v---------jsp
contrl----actionservlet 核心控制器
业务控制器 action
1 helloworld(不带form)
strutt1.2与1.3在lib上的差别 由于1.2中没有标签库包 ,所以需要相关的tld文件
(struts-bean.tld,struts-html.tld,struts-logic.tld,struts-nested.tld,struts-tiles.tld)
(1)导包 拷贝需要相关的tld文件(1.2)
(2)写action类 继承action 重写execute方法
public class HelloWorldAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//HelloWorldForm hwForm = (HelloWorldForm) form;
//hwForm.setMessage("Hello World");
return mapping.findForward("success");
}
}
(3)在web-inf新建struts-config.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<action-mappings>
<action input="/jsp页(如xx.jsp)" path="/取个名字" scope="session" type="包名.类名">
<forward name="取个名字" path="/jsp页(如xx.jsp)" />
</action>
<action path="/取个名字" forward="/jsp页(如xx.jsp)"/>
</action-mappings>
</struts-config>
(4)在web.xml进行struts配置
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
(5)运行 http://localhost:端口号/应用名/配置的path
演示不同路径访问 以及传值回jsp页面
2 helloworld(在1的基础上 带form)
(1) 编写ActionForm 继承ActionForm 里面提供相关属性的set与get方法
(2) 在struts-config.xml配置 form-bean
<form-beans>
<form-bean name="取个名字" type="包名.类名"/>
</form-beans>
在action配置处加入 name=上面配置的form名 指定formbean的scope (request或者session) 可再次演示request属性值丢失问题
如下
<action path="/login" type="com.Login" name="loginForm" scope="request">
一个action只绑定一个form
演示 request或者session的formbean使用
action类中的代码 给HelloForm设置一个属性
HelloForm f=(HelloForm)form;
f.setName("pppppppppp");
采用BeanUtils拷贝属性值到相关的javabean中
Person p=new Person();
BeanUtils.copyProperties(p, loginForm);
在jsp页面上取出来
<%
HelloForm f=(HelloForm)session.getAttribute("helloform"); //此处的属性helloform就是在struts-config.xml的formbean名称
out.print(f.getName());
%>
(3) actionform如何自动获取页面值 只需要form表单中名字与formbean名字相同即可
(4)ActionForm的类型自动转换
* 基本的数据类型都可以自动进行转换;
* java.sql.Date 默认的转换格式是 yyyy-MM-dd;
* java.util.Date 默认不可以转换;可自定义类型转换器
自定义转换器的实现步骤:
1. 定义一个实现了Converter接口的类,并且实现convert方法;
2. 定义一个servlet来注册转换器,注册转换器引用ConvertUtils类的静态方法register(转换器,转换类型);
* ConvertUtils.register(new UtilDateConverter(), java.util.Date.class);
3. 配置servlet时注意配上这个<load-on-startup>5</load-on-startup>值要大于0,因为这个servlet要求在tomcat启动时初始化;
4. 第二种方法注册转换器通过实现PlugIn接口,在struts-config.xml中配置上<plug-in
1.先申明一个转换类
package com;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.beanutils.Converter;
public class UtilDateConverter implements Converter {
@Override
public Object convert(Class type, Object value) {
// TODO Auto-generated method stub
System.out.println("UtilDateConverter.value=" + value);
if (value == null) {
return value;
}
if (value instanceof Date) {
return value;
}
Date d = null;
if (value instanceof String) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
d = sdf.parse((String) value);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return d;
}
}
2 方法1.使用servlet注册
package com;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.apache.commons.beanutils.ConvertUtils;
/**
* 注册java.util.date转换器
*
* @author Administrator
*
*/
public class UtilDateConverterInitWithServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("UtilDateConverterInitWithServlet.init()");
ConvertUtils.register(new UtilDateConverter(), Date.class);
}
}
其中web.xml文件加上
<servlet>
<servlet-name>UtilDateConverterInitWithServlet</servlet-name>
<servlet-class>com.UtilDateConverterInitWithServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
方法2.使用struts中的plug-in进行注册
package com;
import java.util.Date;
import javax.servlet.ServletException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
public class UtilDateConverterInitWithPlugin implements PlugIn {
public void destroy() {
}
public void init(ActionServlet servlet, ModuleConfig config)
throws ServletException {
System.out.println("UtilDateConverterInitWithPlugin.init()");
ConvertUtils.register(new UtilDateConverter(), Date.class);
}
}
其中struts-config.xml文件加上
<plug-in className="com.UtilDateConverterInitWithPlugin"/>
* ActionForm中的其他属性
//以下属性都需要new 否则空指针
private List<String> friends = new ArrayList<String>();
private static String[] skillLevels = new String[] { "Beginner",
"Intermediate", "Advanced" };
private Map<String, Object> skills = new HashMap<String, Object>();
private List tbList = new AutoArrayList(TestBean.class);
public List<TestBean> getTbList() {
return tbList;
}
public void setTbList(List<TestBean> tbList) {
this.tbList = tbList;
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
// TODO Auto-generated method stub
return null;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
this.friends.clear();
}
public Object getSkill(String key) {
return skills.get(key);
}
public void setSkill(String key, Object value) {
skills.put(key, value);
}
public Map getSkills() {
return skills;
}
public String[] getSkillLevels() {
return skillLevels;
}
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
//一下方法比上面少一个s 自己实现
public void setFriend(int index, String friend) {
if (this.friends.size() > index) {
/* 用指定的元素替代此列表中指定位置上的元素 */
this.friends.set(index, friend);
} else {
while (this.friends.size() < index) {
this.friends.add(null);
}
this.friends.add(index, friend);
}
}
//一下方法比上面少一个s 自己实现
public String getFriend(int index) {
if (this.friends.size() > index) {
return (String) this.friends.get(index);
} else {
return null;
}
}
AutoArrayList代码实现
public class AutoArrayList extends ArrayList {
private Class itemClass;
public AutoArrayList(Class itemClass) {
this.itemClass = itemClass;
}
public Object get(int index) {
try {
while (index >= size()) {
add(itemClass.newInstance());
}
} catch (Exception e) {
e.printStackTrace();
}
return super.get(index);
}
}
输入页面示例
<html:form action="collection_test.do" method="post">
Friend 1 :<html:text property="friend[0]"></html:text><br> <!-- 调用setFriend(int index,String friend)-->
Friend 2 :<html:text property="friend[1]"></html:text><br>
Friend 3 :<html:text property="friend[2]"></html:text><br>
java skill: <html:select property="skill(java)"> <!-- 调用setSkill(String key,Object value) -->
<html:options property="skillLevels"/>
</html:select><br>
jsp skill:<html:select property="skill(jsp)">
<html:options property="skillLevels"/>
</html:select><br>
struts skill:<html:select property="skill(struts)">
<html:options property="skillLevels"/>
</html:select><br>
tbList 1 :<html:text property="tbList[0].name"></html:text><br>
tbList 2 :<html:text property="tbList[1].name"></html:text><br>
tbList 3 :<html:text property="tbList[2].name"></html:text><br>
<input type=submit></input>
</html:form>
输出页面示例
Friend 1:<bean:write name="collectionForm" property="friend[0]"/><br><!-- 调用getFriend(int index)-->
Friend 2:<bean:write name="collectionForm" property="friend[1]"/><br>
Friend 3:<bean:write name="collectionForm" property="friend[2]"/><br>
java skill :<bean:write name="collectionForm" property="skill(java)"/><br><!-- 调用getSkill(String key) -->
jsp skill :<bean:write name="collectionForm" property="skill(jsp)"/><br>
struts skill :<bean:write name="collectionForm" property="skill(struts)"/>
跳转演示
登录练习
地址栏斜杠的演示 / 如何精确定位action
多个方法的演示(增加,删除,修改)
3 Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的
并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
4 全局转发与局部转发 全局异常与局部异常
<global-forwards>
<forward name="xxx" path="/global.jsp"></forward>
<forward name="success" path="/uuu.jsp"></forward>
</global-forwards>
全局转发 所有的action共用 局部转发 自己的action用 当两者重名时,优先选择局部转发
全局异常与局部异常(附件 struts1.x中的异常处理.txt)
<global-exceptions>
<exception key="资源文件中的key" type="包名.类名(如java.lang.ArithmeticException") path="/error.jsp"></exception>
</global-exceptions>
在error.jsp页面 <html:errors/>获取异常信息
全局异常 所有的action共用 局部异常 自己的action用 当两者重名时,优先选择局部异常
5 资源文件的使用 默认情况下,Struts默认的资源文件为ApplicationResources.properties文件。
在src目录下建立一个properties文件 一般为ApplicationResource.properties 里面写着键值对信息
如
aaa=111
bbb=222
ccc=333
在 struts-config.xml中配置使用资源文件 与<action-mappings>同级别,一般在<action-mappings>后,
<message-resources parameter="文件名(不需要后缀名)"/> 如上的配置为<message-resources parameter="ApplicationResource"/>
如果该资源文件不在src目录下,而在其他包名下,则应加上包名,假设ApplicationResource.properties在com包下,则配置修改为
<message-resources parameter="com/ApplicationResource"/>
资源文件中文乱码解决 native2ascii -encoding gbk ApplicationResources_zh_CN.properties temp.properties
或者用jinto插件进行编辑
在jsp页面上通过bean标记 可输出资源文件的内容
<bean:message key="aaa"/>
在页面上将显示111
ActionError与ActionMessage
actionError 1.1版本 1.2版本推出actionMessage actionMessage是actionError的父类
actionError从语义上一般是指错误信息 actionMessage指的是一般信息
ActionError类与ActionErrors类
ActionError类从不独立进行错误处理,它们总是被存储在ActionErrors对象中。ActionErrors对象保存ActionError类的集合以及它们特定的属性值,我们可以使用自己定义的属性值,或是使用ActionErrors.GLOBAL_ERROR.
如下使用
ActionErrors errors = new ActionErrors();
ActionError error = new ActionError("资源文件中的key值",“要传递进去的参数值(一个或多个(字符串数组))");
errors.add(ActionErrors.GLOBAL_ERROR,error);//或者使用
errors.add("属性名",error )
saveErrors(req,errors);
在页面上通过
<html:errors /> 显示所有错误
<html:errors property="属性名"/> 显示对应的属性错误
ActionError类有两个构造方法 分别有一个参数和两个参数的
一个参数的 参数就是资源文件中的键值
两个参数的 第一个参数是资源文件中的键值,第2个参数是我们可以传进资源文件中的参数值
ActionMeaaage类与ActionMeaaages类
<html:messages id="aaa" property="属性名" message="true">
<bean:write name="aaa"/>
</html:messages>
6 dispatchaction action类继承DispatchAction 不需要重写execute方法 否则失效 因为默认进入execute方法
(1)编写如下类似方法
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
System.out.println("进入add方法");
return mapping.findForward(SUCCESS);
}
public ActionForward update(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
System.out.println("进入update方法");
return mapping.findForward(SUCCESS);
}
(2)在action配置处加入parameter="method"
(3)调用该action时传参数methoda=add或者其他方法名即可
小技巧 不需要强转
String name = (String) PropertyUtils.getSimpleProperty(form, "userName");
String password = (String) PropertyUtils.getSimpleProperty(form, "password");
7 actionforward
ActionForward aw=new ActionForward();
aw.setPath("/taglibdemo.jsp");
return aw;
8 标记库 三大核心 name property value(value可放到嵌套外 <html:multibox property="hobby" value="drink" /> 等价于<html:multibox property="hobby" >drink</html:multibox>)
<logic:iterate>
<bean:write> filter="false" 显示含html标签的 输出int类型的时候加上format属性 format="#"
<bean:define> 使用map中bean演示
<logic:empty>
<logic:present> 作用域是否存在当前name
复选框与下拉框使用
婚否:<html:checkbox property="marry"></html:checkbox> 单个复选框
<br> 多个复选框
爱好 :<html:multibox property="hobby" value="drink" />喝水
<html:multibox property="hobby" value="sleep"></html:multibox>睡觉
<html:multibox property="hobby" value="doxxx"></html:multibox>瞎搞
用<bean:write>演示actionform
// action中片段代码
//list中放简单基本数据
List listBasic=new ArrayList();
listBasic.add("test1");
listBasic.add("test2");
listBasic.add("test3");
listBasic.add("test4");
request.setAttribute("listBasic", listBasic);
// list中 bean
List listBean=new ArrayList();
TaglibBean tb=new TaglibBean();
tb.setName("TaglibBean1");
tb.setAge(11);
tb.setMoney(12.4567);
listBean.add(tb);
tb=new TaglibBean();
tb.setName("TaglibBean2");
tb.setAge(12);
tb.setMoney(12.111);
listBean.add(tb);
tb=new TaglibBean();
tb.setName("TaglibBean3");
tb.setAge(13);
tb.setMoney(12.2222222222);
listBean.add(tb);
request.setAttribute("listBean", listBean);
//hashmap 简单数据
Map map=new HashMap();
map.put("mapkey1", "mapvalue1");
map.put("mapkey2", "mapvalue2");
map.put("mapkey3", "mapvalue3");
request.setAttribute("map", map);
//hashmap 放bean
Map beanMap=new HashMap();
tb=new TaglibBean();
tb.setName("TaglibBean1map");
tb.setAge(11);
tb.setMoney(12.4567);
beanMap.put("mapkey1map", tb);
tb=new TaglibBean();
tb.setName("TaglibBean2map");
tb.setAge(12);
tb.setMoney(12.111);
beanMap.put("mapkey2map", tb);
tb=new TaglibBean();
tb.setName("TaglibBean3map");
tb.setAge(13);
tb.setMoney(12.2222222222);
beanMap.put("mapkey3map", tb);
request.setAttribute("beanMap", beanMap);
//html标签输出 使用filter=false
String strTable="<table border=1><tr><td>aaaa</td></tr></table>";
request.setAttribute("strTable", strTable);
//类似 if else
String ifStr="xxx";
request.setAttribute("ifStr", ifStr);
//单独bean 属性比较 if else
tb=new TaglibBean();
tb.setName("onlyyou");
request.setAttribute("onlybean", tb);
//jsp中片段代码 (附件taglibdemo.jsp)
1 logic:present与logic:iterate 简单集合数据<br>
<logic:present name="listBasic">
xxxx
<logic:iterate name="listBasic" id="element" >
<bean:write name="element"/><br>
</logic:iterate>
</logic:present>
<logic:notPresent name="listBasic">
作用域不存在listBasic
</logic:notPresent>
2 logicempty与logic:iterate 简单集合数据<br>
<logic:notEmpty name="listBasic">
<logic:iterate name="listBasic" id="element" >
<bean:write name="element"/><br>
</logic:iterate>
</logic:notEmpty>
<logic:empty name="listBasic">
集合元素为空
</logic:empty>
3 logicempty与logic:iterate list中 bean (含bean 中list)<br>
<logic:notEmpty name="listBean">
<logic:iterate name="listBean" id="element" >
<bean:write name="element" property="name"/><br>
<bean:write name="element" property="age" format="#.00"/><br>
<bean:write name="element" property="money" format="#.000"/><br>
<logic:notEmpty name="element" property="list">
<logic:iterate name="element" id="bean_list" property="list">
<bean:write name="bean_list"/><br>
</logic:iterate>
</logic:notEmpty>
</logic:iterate>
</logic:notEmpty>
4 logicempty与logic:iterate map<br>
<logic:notEmpty name="map">
<logic:iterate name="map" id="element">
<bean:write name="element" property="value"/><br>
</logic:iterate>
</logic:notEmpty>
5 hashmap 放bean<br>
<logic:notEmpty name="beanMap">
<logic:iterate name="beanMap" id="element">
<bean:define id="map_bean" name="element" property="value"/>
<bean:write name="map_bean" property="name"/><br>
</logic:iterate>
</logic:notEmpty>
6 作用域中的简单字符串 html标签输出 使用filter=false<br>
<logic:present name="strTable">
<bean:write name="strTable" filter="false"/>
</logic:present>
7 类似if else<br>
<logic:equal name="ifStr" value="xxx">
等于 xxx
</logic:equal >
<logic:notEqual name="ifStr" value="xxx">
不等于 xxx
</logic:notEqual >
7 类似if else 单独bean<br>
<logic:equal name="onlybean" property="name" value="xxx">
等于 xxx
</logic:equal >
<logic:notEqual name="onlybean" property="name" value="xxx">
<bean:write name="onlybean" property="name"/>
</logic:notEqual >
9 动态form 不能通过new创建实例 减少actionform的个数
动态ActionForm是struts从1.1版本开始引入一项新的技术,即在创建ActionForm时
可以不用通过编程的方式而只要通过struts-config.xml文件中进行配置,以后在struts运行时,会自动根
据struts-config.xml中配置的DynaActionform来生成一个Action实例
为什么要使用DynaActionform
很显然随着应用程序的变大,数百个ActionForm 这样不仅编程起来麻烦,以后维护起来也麻烦,比如:
某个属性变化了,则需要修改源代码,然后重新编译,但是如果使用DynaActionform则只需要修改
struts-config.xml配置文件就行了。这样提高了应用程序的开发效率与应用程序的可维护性
声明动态Form
声明一个动态Form非常简单,只需要在struts- config.xml的<form-beans>元素中加入一个<form-bean>子元素,并使用<form- property>元素来定义动态Form的属性。我们可以定义的属性类型有简单属性(如String)、索引属性(如数组)、映射属性(如 HashMap)以及嵌套属性(属性类型是另一个类)。
对于动态Form来说,Form的类型必须是org.apache.struts.action.DynaActionForm或其子类。声明一个动态Form的代码如下:
<form-bean name="dynamicForm" type="org.apache.struts.action.DynaActionForm">
<!-- 声明一个简单属性 -->
<form-property name="simpleProp" type="java.lang.String" initial="bill"/>
<!-- 声明一个索引属性 -->
<form-property name="indexedProp" type="java.lang.String[]" />
<!-- 声明一个映射属性 -->
<form-property name="mappedProp" type="java.util.HashMap" />
<!-- 声明一个嵌套属性 -->
<form-property name="nestedProp" type="com.bean.MyBean" />
</form-bean>
动态Form的属性类型
下面列出了动态Form支持的简单属性的所有类型:
java.math.BigDecimal
java.math.BigInteger
java.lang.Boolean
java.lang.Byte
java.lang.Character
java.lang.Class
java.lang.Double
java.lang.Float
java.lang.Integer
java.lang.Long
java.lang.Short
java.lang.String
java.sql.Date
java.sql.Time
java.sql.Timestamp
DynaActionForm还支持由这些数据类型构成的数组(比如String)、Map接口的实 现类(比如java.util.HashMap)、
List接口的实现类(如 java.util.ArrayList)。如果你没有给属性设定初值,数字类属性会自动设定为0,对象类属性设定为null。
如果使用基本的 Struts标志库访问DynaActionForm对象的属性,访问的方法和访问普通ActionForm对象的方法相同。
如果使用动态Form,就无法使用泛型进行自动类型转换了
下面的代码演示了如何通过getter方法获得动态Form的属性值:
DynaActionForm dForm = (DynaActionForm)form;
String name = (String)dForm.get("name");
String[] hobbies = (String[])dForm.get(“hobbies”);
String value1 = (String)dForm.get(“myMap”, “key1”);
下面的代码演示了如何通过getString和getStrings方法获得动态Form的属性值:
String name = dForm.getString(“name”); // 相当于String name = (String)dForm.get("name");
String[] hobbies = dForm.getStrings(“hobbies”); // 相当于String[] hobbies = (String[])dForm.get(“hobbies”);
10 国际化
国际化资源文件命名规则: 前缀.<语言>_<地区>.properties
其中<语言>_<地区>一定要写正确,否则资源是无法正确加载的
ID lang_code lang_en lang_cn lang_hex lang_dec
1 af Afrikaans - South Africa 南非荷兰语 0x0436 1078
2 ar-ae Arabic(U.A.E.) 阿拉伯语 - 阿拉伯联合酋长国 0x3801 14337
3 ar-bh Arabic(Bahrain) 阿拉伯语 - 巴林 0x3C01 15361
4 ar-dz Arabic(Algeria) 阿拉伯语 - 阿尔及利亚 0x1401 5121
5 ar-eg Arabic(Egypt) 阿拉伯语 - 埃及 0x0C01 3073
6 ar-iq Arabic(Iraq) 阿拉伯语 - 伊拉克 0x0801 2049
7 ar-jo Arabic(Jordan) 阿拉伯语 - 约旦 0x2C01 11265
8 ar-kw Arabic(Kuwait) 阿拉伯语 - 科威特 0x3401 13313
9 ar-lb Arabic(Lebanon) 阿拉伯语 - 黎巴嫩 0x3001 12289
10 ar-ly Arabic(Libya) 阿拉伯语 - 利比亚 0x1001 4097
11 ar-ma Arabic(Morocco) 阿拉伯语 - 摩洛哥 0x1801 6145
12 ar-om Arabic(Oman) 阿拉伯语 - 阿曼 0x2001 8193
13 ar-qa Arabic(Qatar) 阿拉伯语 - 卡塔尔 0x4001 16385
14 ar-sa Arabic(Saudi Arabia) 阿拉伯语 - 沙特阿拉伯 0x0401 1025
15 ar-sy Arabic(Syria) 阿拉伯语 - 叙利亚 0x2801 10241
16 ar-tn Arabic(Tunisia) 阿拉伯语 - 突尼斯 0x1C01 7169
17 ar-ye Arabic(Yemen) 阿拉伯语 - 也门 0x2401 9217
18 be Belarusian 白俄罗斯语 0x0423 1059
19 bg Bulgarian 保加利亚语 0x0402 1026
20 ca Catalan 加泰罗尼亚语 0x0403 1027
21 cs Czech 捷克语 0x0405 1029
22 da Danish 丹麦语 0x0406 1030
23 de German(Standard) 德语 - 标准 0x0407 1031
24 de-at German(Austrian) 德语 - 奥地利 0x0C07 3079
25 de-ch German(Swiss) 德语 - 瑞士 0x0807 2055
26 de-li German(Liechtenstein) 德语 - 列支敦士登 0x1407 5127
27 de-lu German(Luxembourg) 德语 - 卢森堡 0x1007 4103
28 el Greek 希腊语 0x0408 1032
29 en English 英语
30 en-au English(Australian) 英语 - 澳大利亚 0x0C09 3081
31 en-bz English(Belize) 英语 - 伯利兹 0x2809 10249
32 en-ca English(Canadian) 英语 - 加拿大 0x1009 4105
33 en-gb English(British) 英语 - 英国 0x0809 2057
34 en-ie English(Ireland) 英语 - 爱尔兰 0x1809 6153
35 en-jm English(Jamaica) 英语 - 牙买加 0x2009 8201
36 en-nz English(New Zealand) 英语 - 新西兰 0x1409 5129
37 en-tt English(Trinidad) 英语 - 特立尼达岛 0x2C09 11273
38 en-us English(United States) 英语 - 美国 0x0409 1033
39 en-za English(South Africa) 英语 - 南非 0x1C09 7177
40 es Spanish(Spain - Modern Sort) 西班牙语 - 标准 0x040A 1034
41 es-ar Spanish(Argentina) 西班牙语 - 阿根廷 0x2C0A 11274
42 es-bo Spanish(Bolivia) 西班牙语 - 玻利维亚 0x400A 16394
43 es-cl Spanish(Chile) 西班牙语 - 智利 0x340A 13322
44 es-co Spanish(Colombia) 西班牙语 - 哥伦比亚 0x240A 9226
45 es-cr Spanish(Costa Rica) 西班牙语 - 哥斯达黎加 0x140A 5130
46 es-do Spanish(Dominican Republic) 西班牙语 - 多米尼加共和国 0x1C0A 7178
47 es-ec Spanish(Ecuador) 西班牙语 - 厄瓜多尔 0x300A 12298
48 es-gt Spanish(Guatemala) 西班牙语 - 危地马拉 0x100A 4106
49 es-hn Spanish(Honduras) 西班牙语 - 洪都拉斯 0x480A 18442
50 es-mx Spanish(Mexican) 西班牙语 - 墨西哥 0x080A 2058
51 es-ni Spanish(Nicaragua) 西班牙语 - 尼加拉瓜 0x4C0A 19466
52 es-pa Spanish(Panama) 西班牙语 - 巴拿马 0x180A 6154
53 es-pe Spanish(Peru) 西班牙语 - 秘鲁 0x280A 10250
54 es-pr Spanish(Puerto Rico) 西班牙语 - 波多黎各 0x500A 20490
55 es-py Spanish(Paraguay) 西班牙语 - 巴拉圭 0x3C0A 15370
56 es-sv Spanish(El Salvador) 西班牙语 - 萨尔瓦多 0x440A 17418
57 es-uy Spanish(Uruguay) 西班牙语 - 乌拉圭 0x380A 14346
58 es-ve Spanish(Venezuela) 西班牙语 - 委内瑞拉 0x200A 8202
59 et Estonian 爱沙尼亚语 0x0425 1061
60 eu Basque 巴斯克语 0x042D 1069
61 fa Farsi 波斯语 0x0429 1065
62 fi Finnish 芬兰语 0x040B 1035
63 fo Faeroese 法罗语 0x0438 1080
64 fr French(Standard) 法语 - 标准 0x040C 1036
65 fr-be French(Belgian) 法语 - 比利时 0x080C 2060
66 fr-ca French(Canadian) 法语 - 加拿大 0x0C0C 3084
67 fr-ch French(Swiss) 法语 - 瑞士 0x100C 4108
68 fr-lu French(Luxembourg) 法语 - 卢森堡 0x140C 5132
69 gd Gaelic(Scots) 盖尔语 - 苏格兰 0x043C 1084
70 gd-ie Gaelic (Ireland) 爱尔兰盖尔语 0x083c 2108
71 he Hebrew 希伯来语 0x040D 1037
72 hi Hindi 印地语 0x0439 1081
73 hr Croatian 克罗地亚语 0x041A 1050
74 hu Hungarian 匈牙利语 0x040E 1038
75 in Indonesian 印度尼西亚语 0x0421 1057
76 is Icelandic 冰岛语 0x040F 1039
77 it Italian(Standard) 意大利语 - 标准 0x0410 1040
78 it-ch Italian(Swiss) 意大利语 - 瑞士 0x0810 2064
79 ja Japanese 日语 0x0411 1041
80 ji Yiddish 意第绪语 0x043D 1085
81 ko Korean 朝鲜语 0x0412 1042
82 lt Lithuanian 立陶宛语 0x0427 1063
83 lv Latvian 拉脱维亚语 0x0426 1062
84 mk Macedonian 马其顿语 0x042F 1071
85 ms Malaysian 马来语 - 马来西亚 0x043E 1086
86 mt Maltese 马耳他语 0x043A 1082
87 nl Dutch(Standard) 荷兰语 0x0413 1043
88 nl-be Dutch(Belgian) 荷兰语 - 比利时 0x0813 2067
89 no Norwegian(Bokmal) 挪威语 - 博克马尔 0x0414 1044
90 pl Polish 波兰语 0x0415 1045
91 pt Portuguese(Standard) 葡萄牙语 - 标准 0x0816 2070
92 pt-br Portuguese(Brazilian) 葡萄牙语 - 巴西 0x0416 1046
93 rm Rhaeto-Romanic 拉托-罗马语 0x0417 1047
94 ro Romanian 罗马尼亚语 0x0418 1048
95 ro-mo Romanian(Moldavia) 罗马尼亚语 - 摩尔多瓦 0x0818 2072
96 ru Russian 俄语 0x0419 1049
97 ru-mo Russian(Moldavia) 俄语 - 摩尔多瓦 0x0819 2073
98 sb Sorbian 索布语 0x042E 1070
99 sk Slovak 斯洛伐克语 0x041B 1051
100 sl Slovenian 斯洛文尼亚语 0x0424 1060
101 sq Albanian 阿尔巴尼亚语 0x041C 1052
102 sr Serbian(Cyrillic) 塞尔维亚语 - 塞瑞利克 0x0C1A 3098
103 sv Swedish 瑞典语 0x041D 1053
104 sv-fi Swedish(Finland) 瑞典语 - 芬兰 0x081D 2077
105 sx Sutu 苏图语 0x0430 1072
106 sz Sami (Lappish) 芬兰地方语言 0x043b 1083
107 th Thai 泰语 0x041E 1054
108 tn Tswana 茨瓦纳语 0x0432 1074
109 tr Turkish 土耳其语 0x041F 1055
110 ts Tsonga 汤加语 0x0431 1073
111 uk Ukrainian 乌克兰语 0x0422 1058
112 ur Urdu 乌尔都语 - 巴基斯坦 0x0420 1056
113 ve Venda 文达语
114 vi Vietnamese 越南语 0x042A 1066
115 xh Xhosa 科萨语 0x0434 1076
116 zh-cn Chinese(PRC) 中文 - 中华人民共和国 0x0804 2052
117 zh-hk Chinese(Hong Kong SAR, PRC) 中文 - 中华人民共和国香港特别行政区 0x0C04 3076
118 zh-sg Chinese(Singapore) 中文 - 新加坡 0x1004 4100
119 zh-tw Chinese(Taiwan Region) 中文 - 台湾地区 0x0404 1028
120 zu Zulu 祖鲁语 0x0435 1077
1 修改浏览器语言
2 编码实现
把语言编码放进session中,其中session的名字为org.apache.struts.action.LOCALE,此后struts1就可以格局这个session值进行选择相对应的语言配置文件进行显示
例如
if(language.equals("chinese"))
session.setAttribute("org.apache.struts.action.LOCALE", Locale.CHINESE);
else
session.setAttribute("org.apache.struts.action.LOCALE", Locale.ENGLISH);
11 验证以及验证框架
一种是通过ActionForm的validate函数进行验证,另一种就是利用validate框架进行验证
校验没有通过 返回input指定的页面 必须配置input页面
六种类的关系:
1:普通form(从下向上继承)
ActionForm //不用验证框架作验证 如要验证 重写validate方法
|
|
validatorForm //使用验证框架时必须继承它,但只能做同一种验证(即form验证)
|
|
validatorActionForm //使用验证框架验证时,可以更为精确的去处理业务逻辑,针对的是不同的按键的path(即可以作不同的验证,如,既可以验证是否为空,又可以同时验证是否小于几位)
2:动态form(从下向上继承)
DynaActionForm //不用验证框架作验证 如要验证 写一个form类继承它 重写validate方法 struts-config.xml配置时改为你写的类
|
|
DynaValidatorForm
|
|
DynaValidatorActionForm
对于 validatorForm 和DynavalidatorForm 是针对form的验证
对于 validatorActionForm 和DynavalidatorActionForm 是针对path的验证
启动验证框架
在struts-config.xml配置验证框架插件
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
可以通过在struts-config.xml中配置action时指定 validate="false" 关闭验证框架
创建Validation.xml
下面介绍一下validation.xml配置文件的标签:
<form-validation></form-validation>是总框架
<formset></formset>是对Form里的数据进行配置
<form name="ActionForm对应的名称"></form>对一个ActionForm里的数据进行验证配置
<field property="ActionForm里的属性名" depends="验证规则,可以是Validation-rules里定义好的也可以是自定义的验证规则">这里配置一个属性的验证内容
<arg0 name="对应的验证规则名称" key="可以直接填入数值,也可填入变量表达式:${var:变量名}" resource="true/false"(代表是否从资源文件中读取信息,否则Key的值以参数的形式返回)>
<var></var>定义一个变量的标签体,可以在里面具体设置变量的名称以及数值
<var-name>对应Key里定义的变量名称</var-name>
<var-value>值</var-value>
<msg name="对应的验证规则名称" key="资源文件中定义的key名称">这里定义了key后,会使用自己的定义的key,否则使用验证规则默认定义的key
在验证规则中大部分可以使用已经预定义好的规则,它们在validator-rules.xml里,当然我们自己也可以定义规则。
其实,这个文件名可以是任意的,可以起成别的名字,比如:validators.xml,不过,也要相应修改struts-config.xml文件中的加入validator框架PlugIn中的value属性。这个value属性用来指定validator-rules文件和具体的验证文件。
1)根元素:
validators.xml文件的“根元素(Root)”是form-validation,
意味着整个文件的内容包含在“<form-validation>”和“</form-validation>”之间,
2)元素global:
这个东西包含constant子元素,用来定义一个全局的“验证限制”,
以便在这个文件的其他地方使用这些验证规则。
如下global phone的应用
<golobal>
<constant>
<constant-name>phone</ constant-name>
<constant-value>7</constant-value>
</constant>
</golobal>
<formset>
<form name="loginValidatorForm">
<field property="userName" depends="required">
<msg name="required" key="invalid"/>
<!--
<msg name="required" key="invalid"/>
意思是当不满足验证规则required时将会用资源文件中key为invalid的值填充actionerror,相当于
ActionErrors errors=new ActionErrors();
errors.add("userName", new ActionError("invalid"));<!--userName为验证的属性名-->
,之后在页面上用<html:errors property="userName"/>显示相应资源文件中的键值对应的提示信息
如果没有这句话,则不满足验证规则required时将会在资源文件中寻找默认的key值。默认的key值在验证规则文件中有,如required默认的key为errors.required
而如果设置resource="false" 即 <msg name="required" key="invalid" resource="false"/> ,则不使用资源文件 这里的key什么值,页面上就提示什么值
-->
<arg0 key="username" />
</field>
<field property="password" depends="required,minlength,maxlength">
<arg0 key="password"/>
<msg name="minlength" key="密码不能小于6位" resource="false"/>
<msg name="maxlength" key="密码不能大于8位" resource="false"/>
<var>
<var-name>minlength</var-name> <!--变量名必须为minlength -->
<var-value>${phone}</var-value> <!--phone为上面定义的常量 -->
</var>
<var>
<var-name>maxlength</var-name> <!--变量名必须为maxlength -->
<var-value>8</var-value>
</var>
</field>
</form>
</formset>
传参数到minlength
<field
property="password"
depends="required,minlength">
<arg0 key="LoginForm.password"/>
<arg1 key="${var:minlength}" name="minlength" resource="false"/> <!--resource="false" 表示不从资源文件取值,而是用当前值。而当前值${var:minlength}表示取变量名为minlength的值 -->
<var>
<var-name>minlength</var-name>
<var-value>6</var-value>
</var>
</field>
正则表达式例子
<field
property="password"
depends="required,mask">
<arg key="logonForm.password"/>
<var>
<var-name>mask</var-name>
<var-value>^[0-9a-zA-Z]*$</var-value> <!--数字与字母-->
</var>
</field>
日期验证例子
<field
property="date" <!--非常遗憾的通知你 date属性在form中的类型为字符串类型-->
depends="required,date">
<arg key="userForm.date"/>
<var>
<var-name>datePattern</var-name>
<var-value>yyyy-MM-dd</var-value>
</var>
</field>
基本验证规则:
名称 描述
byte,short,integer, 检验值是否能被转换成对应的基本数据类型
long,float,double
creditCard 检验输入域是否是一个合法的信用卡号码
date(有点失望) 检验输入域是否是一个合法日期 form中对应的date类型为字符串类型 只验证字符串类型 有点失望
email 检验输入是否是一个合法Email地址
mask 检验输入域是否能成功匹配一个正则表达式
maxLength 检验值的长度是否小于等于给定的最大长度
minLength 检验值的长度是否大于等于给定的最小长度
range 检验值的范围是否在最大值和最小值之间
required 检验输入域是否为不为空,或不包含空格值的长度是否大于零
12 tiles框架
Tiles框架提供了一种模板机制,它可以将网页内容和布局分离,并允许先创建模板,然后在页面中再插入具体的内容。
Tiles框架是Struts的一个插件。我们可以使用Tiles框架来进行页面布局设计。
使用tiles步骤
在所使用tiles标签页面引入 <%@taglib prefix="tiles" uri="/WEB-INF/struts-tiles.tld"%>
1 先定义一个模板 做好一个模板页面 例如 以下两种方式均可
1.1 使用<tiles:get>标签定义模板
<table border=1>
<tr>
<td><tiles:get name="header"/></td>
</tr>
<tr>
<td><tiles:get name="main"/></td>
</tr>
<tr>
<td><tiles:get name="footer"/></td>
</tr>
</table>
1.2 使用<tiles:insert>标签定义模板
<table border=1 bgcolor="red">
<tr>
<td><tiles:insert attribute="header"></tiles:insert> </td>
</tr>
<tr>
<td><tiles:insert attribute="main"></tiles:insert></td>
</tr>
<tr>
<td><tiles:insert attribute="footer"></tiles:insert></td>
</tr>
</table>
2 使用模板页面 使用<tiles:insert>与<tiles:put>标签
<tiles:insert page="模板页面.jsp" > <!--page为刚刚定义的模板页面 也可用template 如 <tiles:insert template="模板页面.jsp" > -->
<tiles:put name="header" value="header.jsp"></tiles:put>
<!--name 是刚刚在模板页面定义的名字 value表示要在该位置下放的页面 也可用content <tiles:put name="header" content="header.jsp"></tiles:put> -->
<tiles:put name="main" value="main.jsp"></tiles:put>
<tiles:put name="footer" value="footer.jsp"></tiles:put>
</tiles:insert>
在struts1使用tiles
1 在Struts应用程序中使用Tiles,我们需要添加如下<plug-in>定义到struts-config.xml文件。
<plug-in className="org.apache.struts.tiles.TilesPlugin" >
<set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
<set-property property="moduleAware" value="true" />
</plug-in>
2 tiles-defs.xml 以下示例 定义baseLayout friends和office都继承了它
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
<tiles-definitions>
<definition name="baseLayout" path="/模板页面.jsp">
<put name="header" value="/header.jsp" />
<put name="main" value="/menu.jsp" />
<put name="footer" value="/footer.jsp" />
</definition>
<definition name="friends" extends="baseLayout"><!--继承baseLayout-->
<put name="body" value="/friends.jsp" />
</definition>
<definition name="office" extends="baseLayout">
<put name="body" value="/office.jsp" />
</definition>
</tiles-definitions>
3 修改struts-config.xml 注意path的值 为 tiles-defs.xml文件中的定义definition name
<action-mappings>
<action path="/Link" parameter="method" type="com.vaannila.LinkAction">
<forward name="friends" path="friends"/> <!--这里的path 与原来不一样哦-->
<forward name="office" path="office"/>
</action>
<action path="/Welcome" forward="/welcomeStruts.jsp"/>
</action-mappings>
发表评论
-
简单上传文件插件
2017-07-12 11:46 675team777.upload.js js: ; ... -
利用html5进行城市定位!aqi指数的获取
2014-07-08 17:52 21396<html><head> < ... -
seajs打包部署工具spm的使用总结
2014-06-30 14:22 926相信使用seajs的好处大家都是知道的,接触seajs好像 ... -
eclispe 编辑XML时,输入<无法自动提示的修复
2014-02-20 14:40 1005eclispe 当编辑XML时,一 ... -
javaScript的性能优化
2014-01-17 14:05 1272随着网络的发展,网速 ... -
可以用来解析字符串表达式的包
2012-10-16 10:57 2107import com.singularsys.jep.J ... -
实现局部图片的懒加载
2012-08-31 14:52 5502此方式适用和iscroll结合使用,若用于普 ... -
java web中实现同一帐号同一时间只能一个地点登陆(类似QQ登录的功能)
2012-03-26 13:11 9743在java web中如何实现像QQ登录的功能,同一帐号不 ... -
根据sessionid获取session的被Servlet2.1抛弃getsession方法的解决方案
2012-01-17 23:15 11921最近一个项目中用到了getsession根据ses ... -
触屏中的JavaScript事件
2012-01-06 21:40 27287一、触摸事件ontouchstarto ... -
mysql函数大全
2011-12-16 10:00 10000控制流函数IFNULL(expr1,expr2) 如果expr ... -
【转载】ORACLE函数大全
2011-12-16 09:57 841SQL中的单记录函数1.ASCII返回与指定的字符对 ... -
Mysql数据库的优化三(索引优化)
2011-12-12 09:34 1422在一些情况下,MySQL可以直接使用索引来满足一个 ORD ... -
Mysql数据库的优化二(查询优化)
2011-12-12 09:32 1288糟糕的SQL查询语句可对整个应用程序的运行产生严重的影响, ... -
Mysql数据库的优化(参数优化)
2011-12-12 09:29 1493MySQL运行参数,修改/etc/my.cnf ... -
java路径问题总结
2011-12-09 15:26 899一 相对路径的获得说明:相对路径(即不写明时候到底相对谁) ... -
Spring声明式事务配置管理方法
2011-12-09 13:30 2898事务配置 首先在/WEB-INF/applicatio ... -
jboss-5.1.0.GA 有时出现的启动报错解决方案(java.lang.IllegalArgumentException: Wrong argumen)
2011-12-09 09:39 3130错误代码:(实例化名称为“AttachmentStore”出错 ... -
国外短信发送接口
2011-12-02 21:59 8690最近自己在弄一个英国的优惠券的网站!需要用到国外的短信发送接口 ... -
根据IP地址获取所在地
2011-06-08 16:46 5405主要Test.java public class Test ...
相关推荐
因为最近攻防演练,对公司的资产进行梳理,发现部分应用还使用的struts1框架,所以赶快收集整理了相关的漏洞以及相关的整改方案。提供给大家。
1. 虽然Struts2在安全方面有一些漏洞,但通过及时更新版本和合理配置,可以有效避免如S2-005、S2-016等已知漏洞。 七、最佳实践 1. 使用ActionSupport基类,可以自动处理表单回显和错误显示。 2. 避免过度依赖OGNL...
### Struts 1.x 总结 #### 一、Struts 框架概述 Struts 是一个基于 Java 的开源框架,它实现了 Model-View-Controller (MVC) 设计模式,帮助开发者构建可扩展、易于维护的 Web 应用程序。在 Struts 1.x 版本中,其...
### Struts1配置总结 #### 一、概述 在探讨Struts1的配置细节之前,首先需要明确的是,Struts1作为一个成熟的MVC框架,在Java Web应用开发领域扮演着重要的角色。为了能够顺利地利用Struts1框架进行开发,开发者...
相比于Struts1,Struts2提供了更强大的功能,包括但不限于拦截器、类型转换、文件上传/下载等。Struts2的核心思想是基于拦截器(Interceptor)的,这种设计使得开发者可以更容易地扩展框架的功能。 ### Struts2与...
这篇博文"Struts1验证总结"很可能详细介绍了Struts1中关于验证的各个方面,包括配置、自定义验证逻辑以及常见问题等。 在Struts1中,验证通常通过ActionForm对象进行,该对象对应于用户界面的表单。当用户提交表单...
Struts1和Struts2是两个非常著名的...然而,这并不意味着Struts1没有它的价值,对于一些简单项目或已有大量Struts1代码的项目,继续使用Struts1可能是更经济的选择。开发者应根据项目需求和团队技能选择合适的框架。
### Struts1、Spring与Hibernate整合详解 #### 一、整合背景及意义 在Java Web开发领域,Struts1、Spring以及Hibernate这三个框架被广泛应用于构建企业级应用系统。Struts1作为MVC架构模式的一个具体实现,在前端...
##### 总结1:Struts2 onsubmit 无法返回JavaScript进行验证 **问题描述**:在Struts2框架中,尝试使用`onsubmit`事件调用JavaScript进行表单验证时发现无效。 **原因分析**:`onsubmit`事件默认情况下并不会阻止...
### Struts2与Struts1的主要区别 #### 控制器类设计差异 在Struts2框架下,控制器类的设计思路有了显著的变化。相比于Struts1中的控制器类,Struts2中的控制器类更像是一个简单的POJO(Plain Old Java Object),...
总结,Struts1作为早期的Web框架,虽然现在已经被Struts2和Spring MVC等新框架所替代,但它在Java Web开发历史上的地位不容忽视,其设计理念和模式对理解现代框架仍有启发意义。通过学习Struts1,开发者能够更好地...
Struts2是Apache软件基金会下的一个开源项目,它继承了Struts1的优点并解决了其存在的问题,如性能和灵活性。Struts2的核心是Action类,它是业务逻辑和视图之间的桥梁。通过使用拦截器,Struts2能够提供诸如输入验证...
Struts1和Struts2是两个著名的...总结来说,Struts2在很多方面改进了Struts1.x的设计,提供了更灵活的架构、更简单的配置、更好的测试支持以及更直接的数据绑定方式。这使得Struts2成为Java Web开发中更受欢迎的选择。
1. **Struts2核心组件** - **FilterDispatcher**(或现在的`StrutsPrepareAndExecuteFilter`):这是Struts2的核心过滤器,它负责拦截请求,处理Action映射,并转发到相应的Action。 - **Action类**:实现业务逻辑...
Struts1学习笔记总结 Struts1是一种基于MVC模式的Web应用框架,它可以帮助开发人员快速构建高效、可维护的Web应用程序。下面是对Struts1学习笔记的总结,涵盖了Struts1的基本概念、工作流程、标签、国际化等方面的...
Struts1是一个经典的Java Web开发框架,其核心之一就是丰富的标签库,它简化了开发者在JSP页面上的工作。在本文中,我们将深入探讨Struts1的四个主要标签库:bean、logic、html和tiles,并重点讲解每个库中的关键...
Struts1.x与Struts2.x是两种非常流行的Java Web应用程序框架,它们都由Apache软件基金会开发,旨在简化MVC(Model-View-Controller)架构的实现。然而,两者在设计哲学、功能特性以及实现方式上存在显著差异。以下是...