孙殿英先盗的谁的墓:action接收请求复合类型参数(反射机机制原理)
action接收请求参数
接受请求参数的原理
在struts2中没有actionForm ,jsp中的表单元素可以在action中定义同名的名称来接受请求参数 然后生成set方法.
内部机制:struts2的拦截器,会根据页面提交到action中的参数,用反射技术在action类中寻找同名的属性,然后调用action的set方法注入属性值 。
此外,如果在action中的属性太多,可以包装成一个对象 ,用法参考下面的代码
原理解析:根据表单元素的名称,person.**去寻找action类中定义的person属性,如果person为空, 则用反射机制new出person对象 ,然后注入person的属性值 ,也因此person类必须要有默认的构造函数 。
一、采用基本类型接收请求参数(get/post)
在Action类中定义与请求参数同名的属性,struts2便能接收自动接收请求参数并赋给同名属性。
action的代码:
Java代码
- public class ParamAction {
- private Integer id;
- private String name;
- public String execute(){
- return "success";
- }
- public void setId(Integer id) { //通过反射技术调用与请求参数同名的属性的setter方法来获取请求参数值
- this.id = id;
- }
- }
public class ParamAction {
private Integer id;
private String name;
public String execute(){
return "success";
}
public void setId(Integer id) { //通过反射技术调用与请求参数同名的属性的setter方法来获取请求参数值
this.id = id;
}
}
配置文件:
Xml代码
form页面,此页面直接保存在根目录下:
Java代码
- id:
- name:
id:
name:
在id与name中分别填写信息后,如:123, testParam,点击提交按钮,在result.jsp页面中就会看到相应的值。
result.jsp页面如下所示:
Java代码
- <%@ taglib uri="/struts-tags" prefix="s"%>
- id:${id}
- name:
<%@ taglib uri="/struts-tags"prefix="s"%>
id:${id}
name:
测试的页面输出结果为:id:123 name:testParam
二、采用复合类型接收请求参数
action代码如下所示:
Java代码
- public class TestAction {
- private Person person;
- public Person getPerson() {
- return person;
- }
- public void setPerson(Person person) {
- this.person = person;
- }
- public String execute(){
- return "success";
- }
- }
public class TestAction {
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String execute(){
return "success";
}
}
Person类的代码如下所示:
Java代码
- public class Person {
- private Integer id;
- private String name;
- //setter和getter方法
- }
public class Person {
private Integer id;
private String name;
//setter和getter方法
}
配置文件如下:
Xml代码
from页面的代码如下:
Java代码
- person.id:
- person.name:
person.id:
person.name:
在person.id与person.name中分别填写信息后,如:123, testParam,点击提交按钮,在result.jsp页面中就会看到相应的值。Person.id:123 Person.name:testParam
result.jsp中的代码如下所示:
Java代码
- <%@ taglib uri="/struts-tags" prefix="s"%>
- Person.id:${person.id}
- Person.name:
<%@ tagliburi="/struts-tags" prefix="s"%>
Person.id:${person.id}
Person.name:
说明:struts2首先通过反射技术调用Person类的默认构造器创建Person对象,然后通过反射技术调用Person类中与请求参数同名的属性的setter方法来获取请求参数值。在这里需要注意的一点是:Person类中一定要有默认的构造器。
采用复合类型接收请求参数的好处,可以减少action中的setter和getter方法,同时可以把相应的属性组合成一个类,这样使代码更好清晰,代码有更好的结构。
注意: 在struts2.1.6版本中存在一个bug,即配置了struts.i18n.encoding常量也不能解决接收到的中文请求参数为乱码(以 post方式提交)的问题,原因是此版本在获取请求参数后才调用了HttpServletRequest的setCharacterEncoding() 方法进行编码设置,导致应用使用的就是乱码请求参数。此bug在struts2.1.8中已经解决,并且解决了2.1.6中存在的其它bug,如果你使用 的是struts2.1.6,解决此bug的方法是配置一个filter,把这个Filter放置在Struts2的Filter之前,并在 doFilter方法中增加如下代码:
Java代码
- public void doFilter(...){
- HttpServletRequest req = (HttpServletRequest) request;
- req.setCharacterEncoding("UTF-8");//应该根据你使用的编码替换UTF-8
- filterChain.doFilter(request,response);
- }
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
在Struts2.0里面有一个非常牛*的功能就是支持更高级的POJO访问
登陆页面login.jsp:
<%@ page language="java" contentType="text/html;charset=utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
新增实体类User.java:
package tutorial;
public class User {
private String userName;
private String password;
//必须要有一个默认的构造器
Public User(){
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public voidsetUserName(String userName) {
this.userName = userName;
}
}
请求处理LoginAction.java:
package tutorial;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private String msg="显示默认消息";
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getMsg() {
return msg;
}
public String execute(){
if("xiaozhu".equals(user.getUserName())&&"111111".equals(user.getPassword()))
msg="welcome,"+user.getUserName();
else
msg="用户名或密码错误";
return this.SUCCESS;//
}
}
响应页面HelloWorld.jsp:
<%@ page language="java" contentType="text/html;charset=utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
新建了一个User实体类,用于封装从表单中接收的数据,而在action中就不用设置相应的属性和方法了,并且这样做能够让我们的软件层次感更加明显,系统结构也更加清晰。以User为例,描述一下采用这种方式的关键步骤:
1. 在action中定义一个User类型的对象:User user;
2. 表单中各个控件的name属性要采取如下命名规则:对象名.属性名,注意对象名必须与action中定义的一样,属性名也必须和该对象的属性一一对应。如上例中的user.userName和user.password。
注意:
public User getUser() {
return user;
}
/Action中的这个get方法必须,否则会出现丢值的现象;set方法就更不用说了,必须的。
上述原理解释:
1. 前面讲的自定义类型转换器是基于 OGNL 的 DefaultTypeConverter 类并实现 convertValue() 方法,两个转换方向的逻辑都写在这一个方法中。而Struts 2 为我们提供了一个 DefaultTypeConverter 的抽象子类 StrutsTypeConverter 来继承,并实现其中两个抽象方法convertFromString()和 convertToString(),这要简单易懂。对比Struts 1 的转换器是要实现org.apache.commons.beanutils.Converter接口,以及它的 convert() 方法的。
2. 注意,上面的 convertFromString() 的第二个参数是一个字符串数组,所以可为请求的数组(如请求串为 ?u=1&u=2&u=3)定义转换器,Action 中相应的属性就应为数组或 List,这一方法的返回值也该为相应的类型(数组或List,要通过第三个参数toClass 来判断是返回数组还是 List 了)。
3. 字符串(如 "user,pass") 转换成 Action 中的复合属性(如User user) 前面是自定了类型转换器。除此之外,还可以 Struts 2 内置的OGNL 表达式,更简单的转换,不用写转换器。例如,你的 Action 有属性 User user,只要在 jsp 页面的输入框命名为 user.name 和user.pass 即可:
或用标签:
或用标签: