1. struts2的简介
1.1. 什么是struts2
Struts2 是一个非常优秀的MVC框架,基于Model2 设计模型,由传统Struts1和WebWork两个经典框架发展而来.
Model -View-Controller: 前台页面与后台代码分离
1.2. struts2核心功能
允许对象作为Action。Action的execute 方法不再与Servlet API耦合,更易测试支持更多视图技术(JSP、FreeMarker、Velocity)基于Spring AOP思想的拦截器机制,更易扩展更强大、更易用输入校验功能,整合Ajax支持.
2. struts2的入门案例
2.1. struts2的目录结构
2.2. struts2的入门案例
1. 导入jar包
解压struts2的包下的apps/struts-blank.war中的jar包就是struts2使用到的基础包
2. 在web.xml中配置核心控制器
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>struts2_day01_demo02_start</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- 配置struts2的核心控制器 --> <filter> <filter-name>strutsPrepareAndExecuteFilter</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter>
<filter-mapping> <filter-name>strutsPrepareAndExecuteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
</web-app> |
3. 核心配置文件(struts.xml)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "struts-2.3.dtd" > <struts> <!-- name:可以为任意值,方便其他package继承 --> <package name="first">
<!-- 配置请求与处理类的关系 --> <action name="helloworld" class="com.ys.action.HelloAction" method="sayHello"></action> </package>
</struts>
|
4. 编写对应的处理类并配置在核心配置文件中
package com.ys.action;
publicclass HelloAction {
publicvoid sayHello(){ System.out.println("-----------sayHello--------"); } }
|
2.3. struts2的处理过程
3. struts2的核心配置文件
3.1. 常用的常量
在struts2核心包中/org/apache/struts2/default.properties找对应的常量
i18n:internationalization
1. <constantname="struts.i18n.encoding" value="UTF-8"/>
指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出
2. <constantname="struts.action.extension" value="action"/>
该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开
3. <constantname="struts.devMode" value="true" />
开发模式下使用,这样可以打印出更详细的错误信息
4. <constantname="struts.serve.static.browserCache" value="false"/>
是否缓存静态资源
5. <constantname="struts.objectFactory" value="spring" />
该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为 false
3.2. 指定多个struts配置文件
在大部分应用里,随着应用规模的增加,系统中Action的数量也会大量增加,导致struts.xml配置文件变得非常臃肿。为了避免struts.xml文件过于庞大、臃肿,提高struts.xml文件的可读性,我们可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml文件中包含其他配置文件。下面的struts.xml通过<include>元素指定多个配置文件:
<struts>
<includefile="struts-part1.xml"/>
<includefile="struts-part2.xml"/>
</struts>
通过这种方式,我们就可以将Struts 2的Action按模块添加在多个配置文件中。
3.3. 配置文件的代码
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "struts-2.3.dtd" > <struts> <!-- 配置对应的常量 --> <!-- 配置编码格式 --> <constant name="struts.i18n.encoding" value="UTF-8"/> <!-- 配置请求的后缀名 --> <constant name="struts.action.extension" value="action,do,"/> <!-- 开启开发者模式 --> <constant name="struts.devMode" value="true"/> <!-- 缓存静态资源 --> <constant name="struts.serve.static.browserCache" value="true"/>
<!-- name:当前package的名称,用户其他package继承 namespace:相当于给业务请求分包,请求具体的方法是需要把命名空间加上 extends:继承struts-default,struts-default有struts2内置的很多拦截器来帮助我们实现功能(文件上传,国际化) --> <package name="second" namespace="test" extends="struts-default"> <!-- 配置请求路径与处理类的映射 name:请求路径 class:请求处理类 method:请求处理方法,如果不配置method时,默认执行的方法为execute --> <action name="test" class="com.ys.action.TestAction"></action>
<action name="jumpIndex" class="com.ys.action.TestAction" method="jumpPage"> <!-- 根据处理方法的返回值,跳转到指定的页面 --> </action>
<action name="toRe" class="com.ys.action.TestAction" method="testRe"> </action>
</package>
</struts>
|
4. 访问Action
Action接口
struts2 的Action可以是普通类
为了让用户开发的Action更加规范struts2提供了一个Action接口
ActionSupport基类
Struts2为Action接口提供了一个实现类ActionSupport,定义了表单域校验、错误信息设置和获得国际化信息相关一些方法
4.1. 编写Action类的方案
1.用户编写Action 可以是普通类
2.用户编写Action 可以实现Action接口
可以使用结果集常量字符串
3.用户编写Action 可以继承ActionSupport基类
对请求参数进行校验,设置错误信息,读取国际化信息
execute方法编写注意细节,public 修饰符,String 返回值,无参数
4.2. 配置action映射的方式
4.2.1. 通过method属性指定Action执行方法
1. 没有指定method属性,默认执行execute方法
2. 通过method属性,指定调用Action相应方法处理请求
4.2.2. 使用通配符配置Action
1.在配置<action...>元素时,允许在指定name属性时,使用模式字符串(用"*"代表一个或多个任意字符)
2.在class、method属性及<result>子元素中通过 {N} 形式代表前面地N个* 匹配子串
<!-- 配置MultipartAction的请求映射关系 *匹配任意长度字符,{N}取的是实际上第几个*的值作为填充内容 --> <!-- <action name="*" class="com.ys.action.MultipartAction" method="{1}"> <result name="{1}">/{1}.jsp</result> </action> --> <!-- 请求的路径为test_index --> <action name="*_*" class="com.ys.action.MultipartAction" method="{1}"> <result name="success">/{2}.jsp</result> </action> |
4.2.3. 使用Action的动态方法调用
通过url动态指定调用Action哪个方法而无需配置<action>的method属性
通过 !方法名指定调用Action哪个方法
注意事项:使用格式需要在struts.xml中设置对应的常量
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant> |
5. 结果处理Result
5.1. 理解结果处理
Action处理完用户请求后,将返回一个普通字符串整个普通字符串就是一个逻辑视图名
Struts2 根据逻辑视图名,决定响应哪个结果,Struts2处理结果使用<result>元素配置
局部结果:将<result>作为<action>子元素配置
全局结果:将<result>作为<global-results>元素的子元素配置
配置<result>元素通常需要指定两个属性
name 该属性指定配置逻辑视图名
type 该属性指定结果类型
5.2. 全局结果
当多个action中都使用到了相同result,这时我们应该把result定义为全局结果
<package ....> <global-results> <result name="message">/message.jsp</result> </global-results> </package> |
5.3. 示例代码:
<package name="default" namespace="/" extends="struts-default"> <!-- 配置全局的结果映射 --> <global-results> <result name="global">/index.jsp</result> </global-results>
<!-- 配置请求url与action处理方法的映射 --> <action name="login" class="com.ys.action.LoginAction" method="login"> <result name="local">/login.jsp</result> <result name="global">/global.jsp</result> </action>
</package> |
注意事项:
局部的会覆盖全局(局部优先于全局)
Struts1中应用范围内action的实例 action是单实例(执行时,现在缓存中查找实例,有用,没有创建新的实例)
Struts2中 应用范围内action的实例,每个请求都会创建一个action实例
Servlet属于单实例多线程的应用,实例只在初始化时被加载
多实例比单实例的优点,不会产生并发问题,但执行速度不如单实例
5.4. 结果类型
<result-types> <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/> <result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/> <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/> <result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/> <result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/> <result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/> <result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/> <result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/> <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/> <result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" /> <result-type name="postback" class="org.apache.struts2.dispatcher.PostbackResult" /> </result-types> |
5.4.1. dispatcher
把控制权转发给应用程序里的某个资源(请求转发到页面)
5.4.2. redirect
把响应重定向到另一个资源, 而不是转发给该资源(重定向到页面)
5.4.3. chain
把响应转发到另外一个Action(转发到具体的指定的action)
5.4.4. redirectAction
把响应重定向到另一个Action
redirectAction 结果类型接受下面这些参数:
actionName: 指定 “目的地” 动作的名字. 它是默认属性
namespace: 用来指定 “目的地” 动作的命名空间. 如果没有配置该参数,Struts 会把 当前 Action 所在的命名空间作为 “目的地” 的命名空间
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "struts-2.3.dtd" > <struts>
<!-- 配置动态方法映射 --> <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<package name="default" namespace="/" extends="struts-default"> <!-- 配置全局的结果映射 --> <global-results> <result name="global">/index.jsp</result> </global-results>
<!-- 配置请求url与action处理方法的映射 --> <action name="login" class="com.ys.action.LoginAction" method="login"> <result name="local">/login.jsp</result> <result name="global">/global.jsp</result> </action>
<!-- 动态方法绑定 --> <!-- 当处理结果跳转到的是具体的action处理方法时,result的值为action的name即可 --> <action name="result" class="com.ys.action.ResultTypeAction"> <result name="resultOne" type="dispatcher">/resultOne.jsp</result> <result name="resultTwo" type="chain">chainAction</result> <result name="resultThree" type="redirect">/resultThree.jsp</result> <result name="resultFour" type="redirectAction">redirectAction</result> </action>
<action name="chainAction" class="com.ys.action.ResultTypeAction" method="chainAction"></action> <action name="redirectAction" class="com.ys.action.ResultTypeAction" method="redirectAction"></action>
</package> </struts>
|
namespace是的注意事项:
访问路径为:http://localhost:8080/a/b/test.action
首先,会去命名空间”/a/b”去找test.action,如果没有找到则去下一级命名空间(/a)找。
如果在找不到则去默认的命名空间(/)中找.
5.4.5. 动态结果
根据action类中属性的getter方法获取值,作为结果视图的名称
5.5. ActionSuport的常量
SUCCESS:行动的执行是成功的。结果视图展示给最终用户
NONE:Action执行成功,但是不会显示一个视图。通常产生这种情况的原因是被其他视图重定向了。
ERROR:Action执行失败。显示一个错误的视图(页面),这个页面可以要求用户再次输入相关数据
INPUT:Action的执行成功需要更多的输入。这个结果是一个典型的结果,它表明如果一个表单通过提供默认的表单来操作一个Action。这个表单会显示给最终用户。
这个结果也用于用户输入无效,意味着用户需要再次输入。
LOGIN:Action不能执行,因为用户没有登录。已登录的画面会被关闭。
6. 参数绑定
Servlet:request.getParamter(“key”);
Struts2:字段,实体,ModelDriven
页面数据---->action
6.1. 字段绑定
页面代码: <form action="${pageContext.request.contextPath}/login.action" method="post"> 用户名:<input type="text" name="username"/><br/> 密码:<input type="text" name="password"/><br/> <input type="submit" value="提交"/><br/> </form>
|
action的代码: publicclass LoginAction extends ActionSupport{
private String username; private String password; publicvoid setUsername(String username) { this.username = username; } publicvoid setPassword(String password) { this.password = password; } publicvoid login(){ System.out.println("用户登录:"+username+":"+password); //获取到用户名和密码 } }
|
6.2. 实体类绑定
页面代码: <form action="${pageContext.request.contextPath}/loginEntity.action" method="post"> 用户名:<input type="text" name="user.username"/><br/> 密码:<input type="text" name="user1.password"/><br/> <input type="submit" value="提交"/><br/> </form> |
业务控制器代码: package com.ys.action;
import com.opensymphony.xwork2.ActionSupport; import com.ys.entity.User;
//user.username setUser().setUsername(); publicclass LoginEntityAction extends ActionSupport{
//必须给user属性添加setter/getter方法 private User user;
public void setUser(User user) { this.user = user; }
public User getUser() { return this.user; }
publicvoid login(){ System.out.println("用户登录LoginEntityAction---》"+user); }
}
|
实体类代码: package com.ys.entity;
publicclass User {
private String username; private String password;
public String getUsername() { returnusername; } publicvoid setUsername(String username) { this.username = username; } public String getPassword() { returnpassword; } publicvoid setPassword(String password) { this.password = password; } @Override public String toString() { return"User [username=" + username + ", password=" + password + "]"; } }
|
6.3. ModelDriven绑定
页面代码: <form action="${pageContext.request.contextPath}/loginModelDriven.action" method="post"> 用户名:<input type="text" name="username"/><br/> 密码:<input type="text" name="password"/><br/> <input type="submit" value="提交"/><br/> </form> |
业务控制器代码: publicclass LoginModelDrivenAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
publicvoid login(){ System.out.println("通过ModelDriven绑定参数:"+user); }
@Override public User getModel() { returnuser; } }
|
实体类代码: package com.ys.entity;
publicclass User {
private String username; private String password;
public String getUsername() { returnusername; } publicvoid setUsername(String username) { this.username = username; } public String getPassword() { returnpassword; } publicvoid setPassword(String password) { this.password = password; } @Override public String toString() { return"User [username=" + username + ", password=" + password + "]"; } }
|
6.4. 将数据封装到List集合
页面代码: <form action="${pageContext.request.contextPath}/list.action" method="post"> 用户名:<input type="text" name="list" /><br />密码:<input type="text" name="list" /><br /> 用户名:<input type="text" name="userList[0].username" /><br />密码:<input type="text" name="userList[0].password" /><br />用户名:<input type="text" name="userList[1].username" /><br />密码:<input type="text" name="userList[1].password" /><br /> <input type="submit" value="提交" /><br /> </form> |
业务控制器代码: package com.ys.action;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport; import com.ys.entity.User;
publicclass ListAction extends ActionSupport{
//提交多个checkbox的值时,可以这么使用 private List<String> list;
private List<User> userList;
publicvoid setList(List<String> list) { this.list = list; }
public List<User> getUserList() { returnuserList; } publicvoid setUserList(List<User> userList) { this.userList = userList; } publicvoid login(){ System.out.println("集合为:"+list); System.out.println(userList); } } |
6.5. 将数据封装到Map集合
页面代码: <form action="${pageContext.request.contextPath}/map.action" method="post"> 用户名:<input type="text" name="maps['first'].username" /><br /> 密码:<input type="text" name="maps['first'].password" /><br /> <input type="submit" value="提交" /><br /> </form> |
业务控制器代码: publicclass MapAction extends ActionSupport{
private Map<String,User> maps;
publicvoid setMaps(Map<String, User> maps) { this.maps = maps; } public Map<String, User> getMaps() { returnmaps; }
publicvoid login(){ Set<String> keySet = maps.keySet(); for (String string : keySet) { User user = maps.get(string); System.out.println(user); } } }
|
7. Action访问Servlet API
actionContext:与servletapi解耦
实现接口:
ServletActionContext:与servletapi耦合
7.1. ActionContext
1)通过 ActionContext 访问 Web 资源:ActionContext是 Action 执行的上下文对象, 在 ActionContext 中保存了 Action 执行所需要的所有对象, 包括 parameters, request, session, application 等.
2)获取 HttpSession 对应的 Map 对象: publicMap getSession() , session 对应的Map 实际上是SessionMap 类型的,强转之后调用其invalidate() 方法,可以使其session 失效
3)获取 ServletContext 对应的 Map 对象: publicMap getApplication()
4)获取请求参数对应的 Map 对象: publicMap getParameters()
5)获取 HttpServletRequest对应的 Map 对象: public Object get(Object key):ActionContext 类中没有提供类似getRequest() 这样的方法来获取 HttpServletRequest 对应的 Map 对象. 要得到 HttpServletRequest 对应的 Map 对象, 可以通过为 get() 方法传递“request”参数实现
package com.ys.action;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport;
/** * 访问ServletAPI的第一种方式 * @author Administrator * */ public class ServletOneAction extends ActionSupport{
//把数据带回页面 public String transferData(){
//获取到ActionContext ActionContext actionContext = ActionContext.getContext(); //把数据添加到request域 Map<String,Object> request = (Map<String, Object>) actionContext.get("request"); request.put("requestText","requestText"); //把数据局添加到Session域 Map<String, Object> session = actionContext.getSession(); session.put("sessionText", "session作用域的值"); //把数据局添加都application域 Map<String, Object> application = actionContext.getApplication(); application.put("applicationText", "session作用域的值");
return ActionSupport.SUCCESS; } }
|
7.2. 实现接口
实现ServletContextAware,ServletRequestAware,ServletResponseAware注入servletAPI
package com.ys.action;
import java.util.Map;
import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport;
public class ServletTwoAction implements ServletRequestAware,ServletResponseAware,ServletContextAware{
private HttpServletRequest request; private HttpServletResponse response; private ServletContext servletContext;//application
//注入request @Override public void setServletRequest(HttpServletRequest request) { this.request = request; }
//注入Reponse @Override public void setServletResponse(HttpServletResponse response) { this.response = response; }
//注入Application @Override public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; }
//把数据带回页面 public String transferData(){
request.setAttribute("requestText","r12345678t");
HttpSession session = request.getSession(); session.setAttribute("sessionText", "session作用域的值"); servletContext.setAttribute("applicationText", "session作用域的值");
return ActionSupport.SUCCESS; }
}
|
7.3. ServletActionContext
1) 直接访问 ServletAPI 将使 Action 与 Servlet 环境耦合在一起, 测试时需要有Servlet 容器, 不便于对 Action 的单元测试;
2) 直接获取 HttpServletRequest 对象: ServletActionContext.getRequest();
3) 直接获取HttpSession 对象:ServletActionContext.getRequest().getSession();
4) 直接获取 ServletContext 对象:ServletActionContext.getServletContext();
package com.ys.action;
import java.util.Map;
import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport;
publicclass ServletThreeAction {
// 把数据带回页面 public String transferData() {
HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); ServletContext servletContext = ServletActionContext.getServletContext();
request.setAttribute("requestText","asdfghjklqwertyui");
HttpSession session = request.getSession();
session.setAttribute("sessionText", "session作用域的值"); servletContext.setAttribute("applicationText", "session作用域的值");
return ActionSupport.SUCCESS;
}
}
|
8. struts标签
引入struts标签库
<%@taglib prefix="s" uri="/struts-tags"%> |
8.1. 数据标签
8.1.1. property标签
${}
1.功能说明
获取对象的属性值,目标对象默认位于ValueStack栈顶
2.标签属性
3.示例代码
<s:property value="user.userName"/> |
8.1.2. set 标签
1. 功能说明
设定指定 scope 范围内对象的属性值。指出:这里的scope 只能修改如下表格中的属性。
2. 标签属性
8.2. form表单UI标签
8.2.1. Form UI 简单表单
8.2.2. select 标签
1.功能说明:
生成 select 标签(含option)
2.标签属性:
3.示例代码
<s:select list="products" listKey="id" listValue="name" label="产品" /> |
8.2.3. checkboxlist 标签
1.功能说明:
生成一组 checkbox
2. 标签属性:
3.示例代码:
<s:checkboxlist name="favors" list="products" listKey="id" listValue="name"/> |
8.2.4. Radio 标签
1.功能说明:
生成一组 radio
2. 标签属性:
3.示例代码
<s:radio name="favorite" list="products" listKey="id" listValue="name"/> |
action代码: package com.ys.action; import java.util.HashMap; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; /** * * 业务控制器的三种编写方式 * 1.普通java类 * 2.实现Action接口 * 3.继承ActionSupport(数据校验,国际化之类...) * @author Administrator * */ public class LoginAction extends ActionSupport{ private Map<String,String> radioMap = new HashMap<String,String>(); private Map<String,Object> hobbysMap = new HashMap<String,Object>(); public Map<String, String> getRadioMap() { return radioMap; } public void setRadioMap(Map<String, String> radioMap) { this.radioMap = radioMap; } public Map<String, Object> getHobbysMap() { return hobbysMap; } public void setHobbysMap(Map<String, Object> hobbysMap) { this.hobbysMap = hobbysMap; } public String toPage(){ radioMap.put("0", "男"); radioMap.put("1", "女"); radioMap.put("2", "人妖"); hobbysMap.put("eat","吃饭"); hobbysMap.put("sleep","睡觉"); hobbysMap.put("hitdoudou","打豆豆"); Map<String,String> maps = new HashMap<String,String>(); maps.put("a","a"); maps.put("b","b"); ActionContext context = ActionContext.getContext(); Map<String,Object> request = (Map<String, Object>) context.get("request"); request.put("requstMaps", maps); System.out.println(hobbysMap);
return "index"; } } |
页面代码: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body>
<s:property value="#request.list"/> <h2>radio</h2> <s:radio list="radioMap" name="sex" /> <h2>checkbox</h2> <s:checkbox name="hobby" value="篮球" label="篮球"></s:checkbox> <s:checkbox name="hobby" value="王者" label="王者"></s:checkbox> <s:checkbox name="hobby" value="吃鸡" label="吃鸡"></s:checkbox>
<h2>使用checkboxlist实现复选框</h2> <s:checkboxlist list="#{'lanqiu':'篮球','zuqiu':'足球'}" name="aihao"></s:checkboxlist> <s:checkboxlist list="hobbysMap" name="hobbys"></s:checkboxlist>
<s:checkboxlist list="#request.requstMaps" name="hobbyrequest"></s:checkboxlist>
<h2>property标签</h2> ${radioMap1} <s:property value="radioMap1" default="11111"/> <s:set value="xiaoming" var="username" scope="request"></s:set> <s:property value="#request.username" /> </body> </html> |
8.3. 控制标签
8.3.1. if-elseif-else 标签
1. 功能说明:
替代 Java 语法中的if/else
2. 2.标签属性:
3.示例代码
欢迎${user.name} , <s:if test="user.role == 'admin'">系统管理员</s:if> <s:elseif test="user.role == 'member'">会员</s:elseif> <s:else>游客</s:else> |
action的代码: package com.ys.action;
import java.util.ArrayList; import java.util.List;
import com.opensymphony.xwork2.ActionSupport; import com.ys.entity.User;
publicclass ControllerAction extends ActionSupport{
private User user; public User getUser() { returnuser; } publicvoid setUser(User user) { this.user = user; } public String toControllerTag(){ user = new User(); user.setUsername("张三"); return ActionSupport.SUCCESS; }
}
|
<h1>if elseif else标签</h1> <s:if test="user.username==null"> 用户名为空 </s:if> <s:else> <s:property value="user.username"/> </s:else> <s:if test="user.password==null"> 密码为空 </s:if> <s:else> <s:property value="user.password"/> </s:else> |
8.3.2. iterator 标签
1.功能说明:
替代 Java 语言中 foreach 的功能
2.标签属性:
3.示例代码
<s:iterator value="products"> <s:property value="name"/>,<s:property value="price"/> <br /> </s:iterator> |
package com.ys.action;
import java.util.ArrayList; import java.util.List;
import com.opensymphony.xwork2.ActionSupport; import com.ys.entity.User;
publicclass ControllerAction extends ActionSupport{
private List<User> userList = new ArrayList<User>();
public List<User> getUserList() { returnuserList; } publicvoid setUserList(List<User> userList) { this.userList = userList; } public String toControllerTag(){ for(inti=1;i<20;i++){ User user = new User(); user.setUsername("username"+i); user.setAge(i); user.setPassword("pwd"+i); userList.add(user); } return ActionSupport.SUCCESS; } } |
<h1>iterator标签</h1> <s:iterator value="userList" id="tempUser" > <s:property value="username"/> <s:property value="password"/> <s:property value="age"/> <br/> </s:iterator> |
注意事项:在遍历集合时,可以直接通过属性名获取到其内容
9. 数据校验
9.1. 什么是数据校验
Struts2支持设置字段的规则来验证表单传过来的数据
客户端校验 过滤正常用户的误操作,通过JS代码完成
服务器端校验,整个应用阻止非法数据的最后防线
9.2. struts校验方式
9.2.1. 手动完成输入校验
<s:fielderror/>
对action指定方法进行校验
校验指定的方法通过重写validateXxx()方法实现,validateXxx()只会校验action中
方法名为Xxx的方法。其中Xxx的第一个字母要大写。
action代码: package com.ys.action;
import com.opensymphony.xwork2.ActionSupport;
publicclass ValidationAction extends ActionSupport {
private String username; private String password;
public String getUsername() { returnusername; } publicvoid setUsername(String username) { this.username = username; }
public String getPassword() { returnpassword; } publicvoid setPassword(String password) { this.password = password; }
//重写validate方法 //在该方法进行数据校验 @Override publicvoid validate() { if(username==null|| "".equals(username)){ //错误信息 this.addFieldError("username", "用户名不能为空"); } if(password==null|| "".equals(password)){ //错误信息 this.addFieldError("password", "密码不能为空"); } System.out.println("校验"); }
public String login() { System.out.println("username:"+username+",password:"+password); return ActionSupport.SUCCESS; } }
|
页面代码: <!-- 显示所有的错误信息 --> <s:fielderror></s:fielderror> <!-- 显示对应表单的错误信息 --> <s:form action="loginValidate.action" method="post"> <s:textfield name="username" errorPosition="bottom"></s:textfield> <s:textfield name="password" errorPosition="bottom" cssErrorStyle="color:red;"></s:textfield> <s:submit value="提交"></s:submit> </s:form> |
9.2.2. 编写校验规则文件
验证的xml文件的规范在xwork-core-xxx.jar包下的:xwork-validator-1.0.3.dtd
该文件需要和action类放在同一个包下,文件的取名应遵守
ActionClassName-validation.xml规则,其中ActionClassName为action
的简单类名,-validation为固定写法。
校验文件的元素介绍
<validators>:根元素
<field>:指定action中要校验的属性,name属性指定将被验证的表单字段的名字
<field-validator>:指定校验器, type 指定验证规则
<param>:子元素可以向验证程序传递参数
<message>:子元素为校验失败后的提示信息,如果需要国际化,可以为message
指定key属性,key的值为属性文件中的key。
系统提供的校验器
required (必填校验器,要求被校验的属性值不能为null)
requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
stringlength(字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
regex(正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
fieldexpression(字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)
url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)
date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
conversion(转换校验器,指定在类型转换失败时,提示的错误信息)
visitor(用于校验action中复合类型的属性,它指定一个校验文件用于校验复合类型属性中的属性)
expression(OGNL表达式校验器,它是一个非字段校验器, expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)
示例代码:
页面代码: <!-- 显示所有的错误信息 --> <s:fielderror></s:fielderror> <!-- 显示对应表单的错误信息 --> <s:form action="loginValidate.action" method="post"> <s:textfield name="username" errorPosition="bottom"></s:textfield> <s:textfield name="password" errorPosition="bottom" cssErrorStyle="color:red;"></s:textfield> <s:submit value="提交"></s:submit> </s:form> |
action代码: package com.ys.action;
import com.opensymphony.xwork2.ActionSupport;
publicclass ValidationFileAction extends ActionSupport {
private String username; private String password;
public String getUsername() { returnusername; }
publicvoid setUsername(String username) { this.username = username; }
public String getPassword() { returnpassword; }
publicvoid setPassword(String password) { this.password = password; }
public String loginValidate() { System.out.println("username:"+username+",password:"+password); return ActionSupport.SUCCESS;
} }
|
校验文件代码: <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "xwork-validator-1.0.3.dtd" > <validators> <!-- 配置对应的字段约束 --> <!-- name:表单的name属性对应的值 --> <field name="username"> <!-- type属性值在如下文件找: /com/opensymphony/xwork2/validator/validators/default.xml --> <field-validator type="requiredstring"> <message>用户名不能为空</message> </field-validator> <field-validator type="stringlength"> <param name="minLength">3</param> <param name="maxLength">10</param> <message>用户名的长度必须在${minLength}到${maxLength}</message> </field-validator> </field> </validators>
|
9.2.3. 基于Annotation的输入校验
10.struts2国际化
10.1. 什么是国际化
可以为不同语言环境的用户,提供不同语言界面。struts2中对国际化进行了封装,我们只需要根据其提供的API进行访问就可以。
10.2. 国际化配置
10.2.1. 全局国际化信息文件
在struts.xml中配置相应的常量
<constant name="struts.custom.i18n.resources" value="messages"></constant> messages.properties 在classpath |
注意事项:
配置全局的国际化文件时,value值为资源文件的文件名,不带语言版本。
如果该资源文件放在具体的包中是,value的值必须带上包名。
资源文件存放的目录及文件名如下:
struts.xml配置文件中的配置如下: <constantname="struts.custom.i18n.resources" value="messages,i18nmessages,com.ys.i18n.pageckagei18n"></constant> |
使用国际化资源: <s:text name="username.tip"></s:text> <s:text name="username"></s:text> <s:text name="password"></s:text> <s:text name="tip"></s:text> <s:form action="login.action" method="post"> <s:textfield name="username" key="username"></s:textfield> <s:textfield name="password" key="password"></s:textfield> <s:submit value="提交"></s:submit> </s:form> |
使用国际化信息
1.在Action中使用 :this.getText("msg");
示例代码: public String login() { String text = this.getText("username.tip"); System.out.println("内容为:" + text); return ActionSupport.SUCCESS; } |
2.在jsp中使用 :<s:textname="msg" />
示例代码: <body> <s:text name="username.tip"></s:text> <s:text name="username"></s:text> <s:text name="password"></s:text> <s:text name="tip"></s:text> <s:form action="login.action" method="post"> <s:textfield name="username" key="username"></s:textfield> <s:textfield name="password" key="password"></s:textfield> <s:submit value="提交"></s:submit> </s:form> </body> |
3.在配置文件中(校验xml) : <messagekey="agemsg"></message>
示例代码: <validators> <field name="username"> <field-validator type="requiredstring"> <message key="username.notnull"/> </field-validator> </field> </validators> |
配置国际化时需要有不同语言版本的内容(properites文件)
baseName_语言的简写_国家地区的简写.properites
例如:
中国:messages_zh_CN.properties
美国:messages_en_US.properties
10.2.2. Action范围信息文件
数据只能在对应Action中使用,在Action类所在包创建 Action类名.properties
--------- 无需配置
中文;Action类名_zh_CN.properties
英文;Action类名_en_US.properties
10.2.3. package范围信息文件
数据对包(包括子包)中的所有Action 都有效, 在包中创建package.properties
----- 无需配置
中文;package_zh_CN.properties
英文;package_en_US.properties
11.struts2的类型转换器
11.1. Struts2内置的类型转换器
对于大部分常用类型,开发者根本无需创建自己的转换器,Struts2内置了常见数据类型多种转换器
boolean 和 Boolean,char和 Character,int 和 Integer,long 和 Long
float 和 Float,double 和 Double
数组 可以将多个同名参数,转换到数组中
集合 支持将数据保存到 List或者 Map 集合
11.2. 自定义类型转换器
实现TypeConverter接口
继承StrutsTypeConverter类来实现自定义类型转换器
示例代码:
package com.ys.converter;
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
public class DateConverter extends StrutsTypeConverter{
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Override public Object convertFromString(Map context, String[] values, Class toClass) { System.out.println("类型转换器执行--->convertFromString"); for (String string : values) { System.out.println("value为:"+string); } //非空判断 if(values!=null && values[0]!=null && !"".equals(values[0])){ try { Date parse = format.parse(values[0]); return parse; } catch (ParseException e) { e.printStackTrace(); } } return null; }
@Override public String convertToString(Map context, Object o) { System.out.println("类型转换器执行--->convertToString"); return null; }
}
|
11.3. 注册类型转换器
11.3.1. 全局类型转换器
在classpath下放置xwork-conversion.properties文件 。
在properties文件中的内容为:待转换的类型=类型转换器的全类名
java.util.Date=com.ys.converter.DateConverter |
11.3.2. 局部类型转换器
在Action类所在的包下放置ActionClassName-conversion.properties文件,
ActionClassName是Action的类名,后面的-conversion.properties是固定写法。
在properties文件中的内容为:属性名称=类型转换器的全类名
12.struts2拦截器
Struts2 拦截器在访问某个 Action 方法之前或之后实施拦截,Struts2 拦截器是可插拔的, 拦截器是 AOP 的一种实现.
拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在访问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用。
12.1. 拦截器的生命周期
init: 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化
interecept: 每拦截一个动作请求, 该方法就会被调用一次. (拦截器的核心方法)
destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次
12.2. 自定义拦截器
自定义拦截器的步骤:
自定义拦截器
1.实现Interceptor接口
2.继承AbstractInterceptor抽象类
在 struts.xml 文件中配置自定义的拦截器
注意事项:
因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。
如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref name=“permissionStack”/>把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用。
示例代码:
自定义Interceptor: package com.ys.interceptor;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class NoLoginInterceptor extends AbstractInterceptor {
@Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("noLoginInterceptor---------"); HttpServletRequest request = ServletActionContext.getRequest(); HttpSession session = request.getSession(); Object object = session.getAttribute("loginUser"); if(object==null){//用户未登录,跳回登录页面 return "login"; }else{ /*String invoke = System.out.println("invoke:"+invoke);*/ return invocation.invoke(); //return invoke; } }
}
|
配置拦截器:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "struts-2.3.dtd" > <struts> <!-- 配置国际化的资源文件为xxxx --> <package name="default" namespace="/" extends="struts-default">
<!-- 配置拦截器 --> <interceptors> <interceptor name="myInterceptor" class="com.ys.interceptor.MyInterceptor"></interceptor> <!-- 配置未登录的拦截器 --> <interceptor name="noLoginInterceptor" class="com.ys.interceptor.NoLoginInterceptor"></interceptor> <!-- 拦截器栈 --> <interceptor-stack name="myInterceptorStack"> <interceptor-ref name="myInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors>
<action name="login" class="com.ys.action.LoginAction" method="login"> <result name="input">/login.jsp</result> <result name="success" type="chain">index</result>
<interceptor-ref name="myInterceptorStack"></interceptor-ref> <!-- 引入自定义的拦截器 注意事项:引用了自定义的拦截器之后,原来默认的拦截器会失效, 如果需要使用需要手动引入
<interceptor-ref name="myInterceptor"></interceptor-ref> 在此引用默认的拦截器 <interceptor-ref name="defaultStack"></interceptor-ref> --> </action> <!-- 首页的Action --> <action name="index" class="com.ys.action.IndexAction" method="index"> <result name="success">/index.jsp</result> <result name="login">/login.jsp</result> <interceptor-ref name="noLoginInterceptor"></interceptor-ref> <interceptor-ref name="myInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package> </struts> |
配置拦截器:
在<package>中定义拦截器以及拦截器栈
然后在对应的action中引人定义的拦截器即可
注意事项:放行拦截器调用ActionInvocation的invoke()方法,该方法会链式调用其他拦截器
12.3. 配置拦截器对action中的某些方法进行拦截
编写拦截器继承MethodFilterInterceptor类
package com.ys.interceptor;
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class MyMethodInterceptor extends MethodFilterInterceptor {
@Override protected String doIntercept(ActionInvocation invocation) throws Exception { System.out.println("拦截了"); return invocation.invoke(); } } |
在struts.xml中配置拦截器
<interceptor name="myMethodInterceptor" class="com.ys.interceptor.MyMethodInterceptor"> <!-- 不拦截方法 --> <param name="excludeMethods">find</param> <!-- 拦截方法 --> <param name="includeMethods">add,delete</param> </interceptor> |
<action name="*" class="com.ys.action.MethodInterceptorAction" method="{1}"> <result>/index.jsp</result> <interceptor-ref name="myMethodInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
|
13.struts2文件上传下载
13.1. springmvc的文件上传
commons-fileupload
commons-io
页面
<form action=”” method=”post” enctype=”multipart/form-data”>
<input type=”file” name=”uploadFile”/>
</form>
Controller
public String upload(Multipart uploadFile){
uploadFile.transferTo();
}
springmvc的核心配置文件中
配置文件上传解析器
13.2. 文件上传步骤
1. 在 Jsp 页面的文件上传表单里使用file 标签. 如果需要一次上传多个文件, 就必须使用多个 file 标签, 但它们的名字必须是相同的
2. 在 Action 中新添加 3 个和文件上传相关的属性. 这 3 个属性的名字必须是以下格式
private File uploadImage; //上传的文件
private String uploadImageContentType; //上传的文件的类型
private String uploadImageFileName; //上传文件的名称
uploadImage 是 jsp 页面上的 file 标签的名字.
上传文件:<inputtype="file" name="uploadImage">
3.如果是上传单个文件,uploadImage属性的类型就是 java.io.File, 它代表被上传的文件, 第二个和第三个属性的类型是 String, 它们分别代表上传文件的文件名和文件类型
定义方式是分别是jsp页面file组件的名称+ContentType, jsp页面file组件的名称+FileName
4. 如果上上传多个文件, 可以使用数组或 List
单文件上传示例代码:
package com.ys.action;
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
publicclass FileUploadAction extends ActionSupport {
// 文件上传必须要有的属性
private File uploadFile; //文件属性和表单中的file表单中的name属性一致 private String uploadFileContentType;//类型名称为 File属性名+ ContentType private String uploadFileFileName;//文件名为File属性名+FileName
public File getUploadFile() { returnuploadFile; } publicvoid setUploadFile(File uploadFile) { this.uploadFile = uploadFile; } public String getUploadFileContentType() { returnuploadFileContentType; } publicvoid setUploadFileContentType(String uploadFileContentType) { this.uploadFileContentType = uploadFileContentType; } public String getUploadFileFileName() { returnuploadFileFileName; } publicvoid setUploadFileFileName(String uploadFileFileName) { this.uploadFileFileName = uploadFileFileName; } @Override public String execute() throws Exception {
//保存到D:/upload文件夹中 //commons-io包下有一个工具类:把源文件复制到目标文件 //构建目标文件 File destFile = new File("D:/upload/",uploadFileFileName); FileUtils.copyFile(uploadFile, destFile);
System.out.println("文件名:"+this.uploadFileFileName); System.out.println("文件类型:"+this.uploadFileContentType); System.out.println("文件上传成功。。。。。。。");
return ActionSupport.SUCCESS; } }
|
<s:form action="fileupload.action" method="post" enctype="multipart/form-data"> <s:file name="uploadFile"></s:file> <s:submit value="提交"></s:submit> </s:form> |
多文件上传:
package com.ys.action;
import java.io.File; import java.util.List;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
/** * 多文件上传 */ public class MutipartFileUploadAction extends ActionSupport {
//属性的类型为集合或者数组都ok private List<File> uploadFile; private List<String> uploadFileContentType; private List<String> uploadFileFileName;
public List<File> getUploadFile() { return uploadFile; }
public void setUploadFile(List<File> uploadFile) { this.uploadFile = uploadFile; }
public List<String> getUploadFileContentType() { return uploadFileContentType; }
public void setUploadFileContentType(List<String> uploadFileContentType) { this.uploadFileContentType = uploadFileContentType; }
public List<String> getUploadFileFileName() { return uploadFileFileName; }
public void setUploadFileFileName(List<String> uploadFileFileName) { this.uploadFileFileName = uploadFileFileName; }
@Override public String execute() throws Exception { for(int i=0;i<uploadFile.size();i++){ File destFile = new File("d:/upload/"+uploadFileFileName.get(i)); FileUtils.copyFile(uploadFile.get(i) , destFile); }
for (String filename : uploadFileFileName) { System.out.println("上传的文件名为:"+filename); } System.out.println("文件上传成功。。。。。。。。。。。"); return ActionSupport.SUCCESS; }
}
|
<body> <s:fielderror></s:fielderror> <s:actionerror/> <s:form action="multipartfileupload.action" method="post" enctype="multipart/form-data"> <s:file name="uploadFile"></s:file> <s:file name="uploadFile"></s:file> <s:file name="uploadFile"></s:file> <s:submit value="提交"></s:submit> </s:form> </body> |
13.3. 定义文件上传错误指向的页面
显示文件上传的错误信息: <s:actionerror/> |
13.4. 设置文件上传的大小限制
在struts.xml中配置静态常量,改变文件上传的默认大小限制。
<!-- 配置文件上传的大小 --> <constant name="struts.multipart.maxSize" value="20971520"></constant> |
控制每一个上传文件的大小以及上传文件的类型
在fileupload拦截器中,通过其属性进行控制.
maximumSize---每一个上传文件大小
allowedTypes--允许上传文件的mimeType类型.
allowedExtensions--允许上传文件的后缀名.
示例代码:
13.5. struts2文件下载
struts2提供了stream结果类型,该结果类型就是专门用于支持文件下载功能的
contentType----下载文件的mimeType类型
contentDisposition---进行下载操作以及下载文件名
inputStream--下载文件对应的流
示例代码:
<a href="${pageContext.request.contextPath}/downloadfile.action?filename=download.txt">下载download.txt</a> <br/> <a href="${pageContext.request.contextPath}/downloadfile.action?filename=struts2-01.docx">下载struts2-01.docx</a> <br/> <a href="${pageContext.request.contextPath}/downloadfile.action?filename=小明.txt">下载小明.txt</a> |
package com.ys.action;
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder;
import com.opensymphony.xwork2.ActionSupport;
publicclass DownloadAction extends ActionSupport {
private String filename;
public String getFilename() { returnfilename; } publicvoid setFilename(String filename) { this.filename = filename; }
//下载文件的名字 public String getDownloadFileName() throws UnsupportedEncodingException{ //处理中文文件名 return URLEncoder.encode(this.filename,"utf-8"); }
//下载文件对应的流 public InputStream getInputStream() throws FileNotFoundException{ System.out.println("获取下载文件的流。。。。。。。。"); //下载的文件 File downloadFile = new File("D:/upload/",this.filename); FileInputStream fis = new FileInputStream(downloadFile);
returnfis; } @Override public String execute() throws Exception { System.out.println("文件下载。。。。。。。。。"); return ActionSupport.SUCCESS; }
}
|
<!-- 配置下载的action --> <action name="downloadfile" class="com.ys.action.DownloadAction"> <result name="success" type="stream"> <!--下载文件对应的流 --> <param name="inputStream">${inputStream}</param> <!-- 下载的行为以及下载的文件名 --> <param name="contentDisposition">attachment;filename=${downloadFileName}</param> </result> </action> |
14.struts2对json的支持
1. 导入struts2-json-plugin-2.3.24.jar
2. struts.xml中package 继承 json-default
3. action的返回结果类型为json
示例代码:
<package name="default" namespace="/" extends="json-default"> <action name="getJson" class="com.ys.action.JsonAction"> <result name="success" type="json"></result> </action> </package> |
package com.ys.action;
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
import com.opensymphony.xwork2.ActionSupport; import com.ys.entity.User;
publicclass JsonAction extends ActionSupport {
private Map<String,String> maps = new HashMap<String,String>();
public Map<String, String> getMaps() { System.out.println("getMaps"); returnmaps; } publicvoid setMaps(Map<String, String> maps) { System.out.println("setMaps"); this.maps = maps; }
@Override public String execute() throws Exception { System.out.println("加载json数据。"); maps.put("1", "aaaaa"); maps.put("2", "bbbbb"); maps.put("3", "ccccc"); maps.put("4", "ddddd"); return ActionSupport.SUCCESS; }
}
|
15.OGNL表达式
15.1. OGNL的简介
OGNL(Object Graph Navigating Language)即对象导航图语言,是表达式语言的一种。通常用来绑定Java 对象的属性,用一个表达式就可以读取和设置对应Java 对象的属性,所以可以用来沟通Web 组件和业务逻辑的模型部分。它是Jakarta“属性存取语言”项目和JSTL 的表达式语言的良好替代,常用的标号有#,%,$
15.2. ValueStack
15.2.1. 什么是ValueStack
它是一个接口com.opensymphony.xwork2.util.ValueStack。
我们使用它是将其做为一个容器,用于携带action数据到页面.
在在页面上通过ognl表达式获取数据。
15.3. #的作用
1. 访问 OGNL 上下文和 Action 上下文, #相当于ActionContext.getContext()
下表有几个 ActionContext 中有用的属性:
parameters:包含当前 HTTP 请求参数的 Map#parameters.id[0]作用相当于
request.getParameter("id")
request:包含当前HttpServletRequest 的属性(attribute)的 Map
#request.userName 相当于request.getAttribute("userName")
session:包含当前 HttpSession 的属性(attribute)的 Map
#session.userName 相当于session.getAttribute("userName")
application:包含当前应用的 ServletContext 的属性(attribute)的 Map
#application.userName 相当于application.getAttribute("userName")
attr:用于按 request > session > application 顺序访问其属性(attribute)
#attr.userName 相当于按顺序在以上三个范围(scope)内读取 userName
属性,直到找到为止
2. 用于过滤和投影(projecting)集合
#request.books.{?#this.price<100};
?:显示所有满足条件的对象信息
^:显示满足条件的第一个对象信息
$:显示满足条件的最后一个对象信息
示例代码:
<s:iterator value="#request.users.{?#this.role=='admin'}"> <tr> <td><s:property value="name"/></td> <td><s:property value="password"/></td> <td><s:property value="role"/></td> </tr> </s:iterator> |
3. 构造 Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
<s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" /> <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p> |
15.4. %的作用
1. 在标志的属性为字符串类型时,计算 OGNL 表达式的值。
2.国际化时,读取资源文件的数据
%{}
15.5. $的作用${}
1. 用于在国际化资源文件中,引用 OGNL 表达式
2. 在 Struts 2 配置文件中,引用 OGNL 表达式
示例代码:
<action name="downloadfile" class="com.ys.action.DownloadAction"> <result name="success" type="stream"> <!--下载文件对应的流 --> <param name="inputStream">${inputStream}</param> <!-- 下载的行为以及下载的文件名 --> <param name="contentDisposition">attachment;filename=${downloadFileName}</param> </result> </action> |
3.在验证框架引用变量
示例代码
<field-validator type="stringlength"> <param name="minLength">3</param> <param name="maxLength">10</param> <message>用户名的长度必须在${minLength}到${maxLength}</message> </field-validator> |
16.struts2注解的使用
导入jar包:struts2-convention-plugin-2.3.24.jar
16.1. Struts2使用注解开发需要遵循一些规范
1、Action要必须继承ActionSupport父类。
2、Action所在的包名必须以 .action 结尾。
16.2. action中常用的注解
1、@ParentPackage:对应xml配置文件中的package的父包,一般需要继承struts-default。
2、@Namespace:对应配置文件中的nameSpace,命名空间。
3、写在方法前边的注解:
@Action,这个注解对应<action>节点
4、action中最常用的results
@Result
注意事项:拦截器还的在配置文件中进行配置
示例代码:
package com.ys.action;
import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.InterceptorRef; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result;
import com.opensymphony.xwork2.ActionSupport;
/** * * 使用注解的步骤: 1.导入jar包 struts2-convention-plugin-2.3.24.jar 2.编写Action类注意事项: * 1.Action类必须继承ActionSupport 2.Action类必须在.action的包下 * */ @ParentPackage(value = "struts-default") // 继承什么包 @Namespace(value = "/annotation") // 命名空间 publicclass AnnotationAction extends ActionSupport {
private String username; private String password;
public String getUsername() { returnusername; }
publicvoid setUsername(String username) { this.username = username; }
public String getPassword() { returnpassword; }
publicvoid setPassword(String password) { this.password = password; }
@Action(value = "login", results = { @Result(name = "success", location = "/index.jsp"), @Result(name="input",location="/login.jsp")} ) // 说明这是一个Action处理方法 public String login() { System.out.println(username+" : "+password); return ActionSupport.SUCCESS; } } |
17.三大框架整合
struts2-spring-plugin-2.3.24.jar
17.1. 整合spring4和hibernate3
17.2. struts2的action交给spring管理
导入jar包struts2-spring-plugin-2.3.24.jar
在struts.xml的配置文件中加上如下代码:
<!-- 叫action的创建权交给spring --> <constant name="struts.objectFactory" value="spring"></constant> |