Action处理请求参数
第一种 :Action 本身作为model对象,通过成员setter封装 (属性驱动 )
第一种方式:<br> <form action="${pageContext.request.contextPath}/MyAction1" method="post"> username:<input type="text" name="username"><br> password:<input type="password" name="password"><br> <input type="submit"><hr> </form>
public class MyAction1 extends ActionSupport{ private String username; private String password; public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public String execute() throws Exception { System.out.println(username+" "+password); return null; } }
问题: Action封装数据,会不会有线程问题 ?
struts2 Action 是多实例 ,为了在Action封装数据 (struts1 Action 是单例的 )
缺点:需要单独定义javaBean,将action中属性copy到javaBean中。
优点:简单。
第二种 :创建独立model对象,页面通过ognl表达式封装 (属性驱动)
第二种方式:<br> <form action="${pageContext.request.contextPath}/MyAction2" method="post"> username:<input type="text" name="user.username"><br> password:<input type="password" name="user.password"><br> <input type="submit"><hr> </form>
public class MyAction2 extends ActionSupport{ private User user; public void setUser(User user) { this.user = user; } public User getUser() {//不写这个密码获取不到?不懂..希望知道的人留言告知,感谢 return user; } public String execute() throws Exception { System.out.println(user.getUsername()+" "+user.getPassword()); return null; } }
问题: 谁来完成的参数封装
<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
优点:简单,解决了第一种封装的问题
缺点:在页面上使用了ognl表达式,页面不通用了
第三种 :使用ModelDriven接口,对请求数据进行封装 (模型驱动 ) ----- 主流,最常用
第三种方式:<br> <form action="${pageContext.request.contextPath}/MyAction3" method="post"> username:<input type="text" name="username"><br> password:<input type="password" name="password"><br> <input type="submit"><hr> </form>
public class MyAction3 extends ActionSupport implements ModelDriven<User>{ private User user=new User(); public String execute() throws Exception { System.out.println(user.getUsername()+" "+user.getPassword()); return null; } @Override public User getModel() { return user; } }
优点:解决了属性驱动存在的问题
缺点:一次只能封装一个model对象.
struts2 有很多围绕模型驱动的特性
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 为模型驱动提供了更多特性
对比第二种、第三种 : 第三种只能在Action中指定一个model对象,第二种可以在Action中定义多个model对象
<input type="text" name="user.username" /> <input type="text" name="product.info" />
1 public class StrutsFilter implements Filter { 2 3 public void init(FilterConfig filterConfig) throws ServletException {} 4 public void doFilter(ServletRequest req, ServletResponse resp, 5 FilterChain chain) throws IOException, ServletException { 6 // 1.强转 7 HttpServletRequest request = (HttpServletRequest) req; 8 HttpServletResponse response = (HttpServletResponse) resp; 9 // 2.操作 10 // 2.1 得到请求资源路径 11 String uri = request.getRequestURI(); 12 String contextPath = request.getContextPath(); 13 String path = uri.substring(contextPath.length() + 1); 14 // 2.2 使用path去struts.xml文件中查找某一个<action name=path>这个标签 15 SAXReader reader = new SAXReader(); 16 try { 17 // 得到struts.xml文件的document对象。 18 Document document = reader.read(new File(this.getClass().getResource("/struts.xml").getPath())); 19 Element actionElement = (Element) document 20 .selectSingleNode("//action[@name='" + path + "']"); // 查找<action 21 // name='hello'>这样的标签 22 if (actionElement != null) { 23 // 得到<action>标签上的class属性以及method属性 24 String className = actionElement.attributeValue("class"); // 得到了action类的名称 25 String methodName = actionElement.attributeValue("method");// 得到action类中的方法名称。 26 // 2.3通过反射,得到Class对象,得到Method对象 27 Class actionClass = Class.forName(className); 28 Method method = actionClass.getDeclaredMethod(methodName); 29 30 31 32 // 处理请求参数封装: 33 Object actionObj = actionClass.newInstance(); 34 // 模型驱动 35 if (actionObj instanceof MyModelDriven) { 36 MyModelDriven mmd = (MyModelDriven) actionObj; 37 BeanUtils.populate(mmd.getModel(),request.getParameterMap()); 38 } else { 39 // 属性驱动 40 BeanUtils.populate(actionObj, request.getParameterMap());// 41 } 42 // 2.4 让method执行. 43 String returnValue = (String) method.invoke(actionObj); // 是让action类中的方法执行,并获取方法的返回值。 44 45 46 47 48 // 2.5 49 // 使用returnValue去action下查找其子元素result的name属性值,与returnValue做对比。 50 Element resultElement = actionElement.element("result"); 51 String nameValue = resultElement.attributeValue("name"); 52 if (returnValue.equals(nameValue)) { 53 // 2.6得到了要跳转的路径。 54 String skipPath = resultElement.getText(); 55 request.getRequestDispatcher(skipPath).forward(request,response); 56 return; 57 } 58 } 59 } catch (Exception e) { 60 e.printStackTrace(); 61 } 62 // 3.放行 63 chain.doFilter(request, response); 64 } 65 public void destroy() {} 66 }
1 public interface MyModelDriven<T> { 2 public T getModel(); 3 }
封装数据到Collection和Map
1) 封装数据到Collection 对象
第四种方式(list):<br> <form action="${pageContext.request.contextPath}/MyAction4" method="post"> username:<input type="text" name="users[0].username"><br> password:<input type="password" name="users[0].password"><br> username:<input type="text" name="users[1].username"><br> password:<input type="password" name="users[1].password"><br> <input type="submit"><hr> </form>
public class MyAction4 extends ActionSupport{ private List<User>users; public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } public String execute() throws Exception { System.out.println(users); return null; } }
2) 封装数据到Map 对象
第五种方式(map):<br> <form action="${pageContext.request.contextPath}/MyAction5" method="post"> username:<input type="text" name="users['zs'].username"><br> password:<input type="password" name="users['zs'].password"><br> username:<input type="text" name="users['ls'].username"><br> password:<input type="password" name="users['ls'].password"><br> <input type="submit"><hr> </form>
public class MyAction5 extends ActionSupport{ private Map<String, User>users; public Map<String, User> getUsers() { return users; } public void setUsers(Map<String, User> users) { this.users = users; } public String execute() throws Exception { System.out.println(users); return null; } }