【Struts2】(7)ModelDriven和类型转换器

10 篇文章 0 订阅

一. ModelDriven

我们可以通过对Action实现ModelDriven接口来做到更方便的传值。这样子,我们甚至不用写set和get方法:
public class UserAction implements ModelDriven {

	private User user;
	private String username;
	private String password;

	@Override
	public Object getModel() {
		if (user == null) {
			user = new User();
		}
		return user;
	}

	// public User getUser() {
	// return user;
	// }
	//
	// public void setUser(User user) {
	// this.user = user;
	// }
这样,我们在jsp中,也可以省去之前所写的user.xxx的user了:
	<form action="/web/test/user.action" method="post">
		Id:<input name="user.id" /><br />
		UserName:<input name="username" /><br />
		Password:<input name="password" type="password" /><br />
		Sex:<input name="sex"  /><br />
		Age:<input name="age" /><br />
		home add:<input name="address.homeAddress" /><br />
		company add:<input name="address.companyAddress" /><br />
		<input type="submit" name="method:add"	value="添加" />
	</form>

二. ModelDriven的一个问题

我们编写这样子的一个list界面:
	<table border="1">
		<tr align="center">
			<td>ID</td>
			<td>用户名</td>
			<td>密码</td>
			<td>操作</td>
		</tr>
		<tr align="center">
			<td>1</td>
			<td>张三</td>
			<td>1</td>
			<td>
				<a href="/web/test/user.action?method:updateInput&id=1">更新</a>
				<a href="/web/test/user.action?method:delete&id=1">删除</a>
			</td>
		</tr>
	</table>
点击更新会调用updateInput方法从数据库中查询出一个user,然后显示在jsp页面中:
		UserName:<input name="username" value='<s:property value="username"/>'/><br />
		Password:<input name="password" type="password" value='<s:property value="password"/>'/><br />
		Sex:<input name="sex" value='<s:property value="sex"/>'/><br />
		Age:<input name="age" value='<s:property value="age"/>'/><br />
	public String updateInput() {
		UserManager userManager = new UserManager();
		user = userManager.findUserById(user.getId());
		return "update_input";
	}
还是使用我们之前的getModel方法,运行,但是发现页面中并没有显示出我们所需要查询的user来。这个原因是什么呢?
通过断点调试我们发现:

此时处在值栈顶部的user的id是5303,而我们查出的user的id却是5601,这明显不是同一个user,必然不会再界面上显示出来了。
于是我们修改的方法有以下几种:
方法一:
	public String updateInput() {
		Object obj = ActionContext.getContext().getValueStack()
				.findValue("#root");
		UserManager userManager = new UserManager();
		User find = userManager.findUserById(user.getId());
		// 清掉原来的数据,放入新查询到的数据。
		ActionContext.getContext().getValueStack().getRoot().remove(obj);
		ActionContext.getContext().getValueStack().getRoot().push(find);
		return "update_input";
	}
我们强制调用值栈的remove方法,将之前的obj对象移除掉,然后在栈顶放入我们查询到的user,这样,处在栈顶的数据必然有数据了。
方法二:
我们可以将查询出来的user对象的各种属性赋给Action的成员变量的user的各个属性,然后user就会有数据了
方法三:
	public String updateInput() {
		Object obj = ActionContext.getContext().getValueStack()
				.findValue("#root");
		UserManager userManager = new UserManager();
		User find = userManager.findUserById(user.getId());
		try {
			BeanUtils.copyProperties(user, find);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return "update_input";
	}
这里需要导入两个包:commons-beanutils和commons-logging包。  
方法四:
在struts配置文件中加入配置:
			<interceptor-stack name="myStack">
				<interceptor-ref name="exception" />
				<interceptor-ref name="alias" />
				<interceptor-ref name="servletConfig" />
				<interceptor-ref name="i18n" />
				<interceptor-ref name="prepare" />
				<interceptor-ref name="chain" />
				<interceptor-ref name="scopedModelDriven" />
				<interceptor-ref name="modelDriven">
					<param name="refreshModelBeforeResult">true</param>
				</interceptor-ref>
				<interceptor-ref name="fileUpload" />
				<interceptor-ref name="checkbox" />
				<interceptor-ref name="datetime" />
				<interceptor-ref name="multiselect" />
				<interceptor-ref name="staticParams" />
				<interceptor-ref name="actionMappingParams" />
				<interceptor-ref name="params" />
				<interceptor-ref name="conversionError" />
				<interceptor-ref name="validation">
					<param name="excludeMethods">input,back,cancel,browse</param>
				</interceptor-ref>
				<interceptor-ref name="workflow">
					<param name="excludeMethods">input,back,cancel,browse</param>
				</interceptor-ref>
				<interceptor-ref name="debugging" />
				<interceptor-ref name="deprecation" />
				<!-- <interceptor-ref name="defaultStack" /> <interceptor-ref name="LoginInterceptor" 
					/> -->
			</interceptor-stack>
最主要的是给modelDriven配置一个refreshModelBeforeResult为true的参数。
updateInput方法还是用最初的代码:
	public String updateInput() {
		UserManager userManager = new UserManager();
		user = userManager.findUserById(user.getId());	
		return "update_input";
	}
当struts配置文件过大时,可以提取出来一个公共的配置文件,然后引用它,新建common.xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
	<constant name="struts.devMode" value="true" />
	<constant name="struts.action.extension" value="action,,do,webwork"></constant>
	<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
	<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>


	<package name="common" extends="struts-default" abstract="true">
		<interceptors>
			<interceptor name="LoginInterceptor"
				class="com.thr.struts2.interceptor.LoginInterceptor" />
			<interceptor-stack name="myStack">
				<interceptor-ref name="exception" />
				<interceptor-ref name="alias" />
				<interceptor-ref name="servletConfig" />
				<interceptor-ref name="i18n" />
				<interceptor-ref name="prepare" />
				<interceptor-ref name="chain" />
				<interceptor-ref name="scopedModelDriven" />
				<interceptor-ref name="modelDriven">
					<param name="refreshModelBeforeResult">true</param>
				</interceptor-ref>
				<interceptor-ref name="fileUpload" />
				<interceptor-ref name="checkbox" />
				<interceptor-ref name="datetime" />
				<interceptor-ref name="multiselect" />
				<interceptor-ref name="staticParams" />
				<interceptor-ref name="actionMappingParams" />
				<interceptor-ref name="params" />
				<interceptor-ref name="conversionError" />
				<interceptor-ref name="validation">
					<param name="excludeMethods">input,back,cancel,browse</param>
				</interceptor-ref>
				<interceptor-ref name="workflow">
					<param name="excludeMethods">input,back,cancel,browse</param>
				</interceptor-ref>
				<interceptor-ref name="debugging" />
				<interceptor-ref name="deprecation" />
				<!-- <interceptor-ref name="defaultStack" /> <interceptor-ref name="LoginInterceptor" 
					/> -->
			</interceptor-stack>
		</interceptors>
		<default-interceptor-ref name="myStack" />
	</package>
</struts>
我们的struts文件就会清爽许多:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
	
<struts>
	<include file="common.xml"></include>
	<package name="basicstruts2" extends="common"
		namespace="/test">
		<default-interceptor-ref name="myStack" />
		<global-results>
			<result name="login">/login.jsp?id=%{#loginid}</result>
		</global-results>
		<action name="user" class="com.thr.struts2.action.UserAction">
			<result name="add_input">/add_input.jsp</result>
			<result name="add_success">/add_success.jsp</result>
			<result name="update_input">/update_input.jsp</result>
			<result>/success.jsp</result>
			<result name="list">/list.jsp</result>
			<result name="static">/methodcalls.jsp</result>
		</action>
		<action name="login" class="com.thr.struts2.action.LoginAction">
			<!-- <interceptor-ref name="defaultStack" /> -->
			<result>/success.jsp</result>
		</action>
	</package>
</struts>

三. 类型转换器

我们要自定义转换器要继承类,覆写2个方法:
public class DateConverter extends StrutsTypeConverter {
	private SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");

	@Override
	public Object convertFromString(Map context, String[] values, Class toClass) {
		RuntimeException ex = null;
		String dateStr = null;
		if (values != null && values.length == 1) {
			dateStr = values[0];
			try {
				return format.parse(dateStr);
			} catch (ParseException e) {
				ex = new RuntimeException(e.getMessage());
			}
		}
		throw ex;
	}

	@Override
	public String convertToString(Map context, Object o) {
		if (o instanceof Date) {
			return format.format(o);
		}
		throw new RuntimeException("不是日期格式,请检查");
	}
}
1. 局部转换器
在需要转换的类的包下创建名为:类名-conversion.properties的文件,里面写入我们需要转换的属性:
birthday=com.thr.struts2.converter.DateConverter
2. 全局转换器
在src下创建名为:xwork-conversion.properties的文件,里面写我们要转换的类:
java.util.Date=com.thr.struts2.converter.DateConverter
当两种转换器都定义的时候,优先调用局部转换器。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值