1、我们可以自定义异常,并且指定当异常出现时,转向哪一个处理页面,首先针对LoginAction这个Action来说,在execute()方法中手工抛出两个异常:
UsernameException和PasswordException,异常定义:
package com.cdtax.exception; public class UsernameException extends Exception { private String message; public UsernameException(String message) { super(message); this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
package com.cdtax.exception; public class PasswordException extends Exception { private String message; public PasswordException(String message) { super(message); this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
然后配置struts.xml文件:
<action name="aas" class="com.cdtax.struts2.LoginAction"> <exception-mapping result="usernameinvalid" exception="com.cdtax.exception.UsernameException"></exception-mapping> <exception-mapping result="passwordinvalid" exception="com.cdtax.exception.PasswordException"></exception-mapping> <result name="success">/result.jsp</result> <result name="usernameinvalid">/usernameexception.jsp</result> <result name="passwordinvalid">/passwordexception.jsp</result> </action>
增加了两个exception-mapping和两个result
然后创建两个异常的处理页面usernameexception.jsp和passwordexception.jsp,这样当用户名抛出异常时,页面转向usernameexception.jsp,密码出现异常时,转向passwordexception.jsp。
2、全局的异常处理和全局的结果
全局的异常处理:struts.xml:
<global-results> <result name="usernameinvalid">/usernameexception.jsp</result> <result name="passwordinvalid">/passwordexception.jsp</result> </global-results> <action name="aas" class="com.cdtax.struts2.LoginAction"> <exception-mapping result="usernameinvalid" exception="com.cdtax.exception.UsernameException"></exception-mapping> <exception-mapping result="passwordinvalid" exception="com.cdtax.exception.PasswordException"></exception-mapping> <result name="success">/result.jsp</result> </action>
这时全局的异常处理:局部的优于全局的,就是说,如果在Action标签中也有<result name="usernameinvalid">/passwordexception.jsp</result>,那么页面将优先转向局部的result指向的页面,这里就是passwordexception.jsp。
全局的异常struts.xml:
<global-results> <result name="usernameinvalid">/usernameexception.jsp</result> <result name="passwordinvalid">/passwordexception.jsp</result> </global-results> <global-exception-mappings> <exception-mapping result="usernameinvalid" exception="com.cdtax.exception.UsernameException"></exception-mapping> <exception-mapping result="passwordinvalid" exception="com.cdtax.exception.PasswordException"></exception-mapping> </global-exception-mappings> <action name="aas" class="com.cdtax.struts2.LoginAction"> <result name="success">/result.jsp</result> </action>
也是局部优于全局的。
我们可以在action中定义异常与结果,也可以定义全局的异常和结果,局部总是优于全局的,如果定义成全局,俺么可以为所有action所共享,而局部的异常与结果只能被当前的action所独享,不能为其他action所共享。
3、struts2应用的分层体系结构:
登录的整个流程程序:
login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'login.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="aas.action"> username:<input type="text" name="username"><br> password:<input type="password" name="password"><br> age:<input type="text" name="aaa"> date:<input type="text" name="date"> <input type="submit" value="submit"> </form> </body> </html>
LoginAction:
package com.cdtax.struts2; import java.util.Date; import com.cdtax.exception.PasswordException; import com.cdtax.exception.UsernameException; import com.cdtax.service.LoginService; import com.cdtax.service.impl.LoginServiceImpl; import com.opensymphony.xwork2.ActionSupport; public class LoginAction extends ActionSupport { private String username; private String password; private int age; private Date date; private LoginService loginService = new LoginServiceImpl(); public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute() throws Exception { // if(!"hello".equals(username)) // { // throw new UsernameException("username invalid"); // } // if(!"world".equals(password)) // { // throw new PasswordException("password invalid!"); // } if(this.loginService.isLogin(username, password)) { return SUCCESS; } return INPUT; } public String myExecute() { System.out.println("myExecute invoke!"); return SUCCESS; } }
在这里,action增加了一个成员变量,作为对service的引用,execute方法进行业务逻辑判断,调用此service。
service接口定义对上层的服务:
package com.cdtax.service; public interface LoginService { public boolean isLogin(String username,String password); }
具体的service实现:
package com.cdtax.service.impl; import com.cdtax.service.LoginService; public class LoginServiceImpl implements LoginService { @Override public boolean isLogin(String username, String password) { if("hello".equals(username) && "world".equals(password)) { return true; } return false; } }
struts.xml:
<action name="aas" class="com.cdtax.struts2.LoginAction"> <result name="success">/result.jsp</result> <result name="input">/login.jsp</result> </action>
定义成功后的转向页面result.jsp。
4、struts2的模型驱动(Model Driven)
相对于上面的action模式,叫做属性驱动(Property Driven)
要想实现模型驱动,我们写的action还需要实现ModelDriven接口。
编写一个bean:Person,作为页面提交参数的对象
package com.cdtax.bean; import java.util.Date; public class Person { private String username; private String password; private int age; private Date date; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
编写模型驱动的Action:LoginAction2:
package com.cdtax.struts2; import com.cdtax.bean.Person; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; public class LoginAction2 extends ActionSupport implements ModelDriven<Person> { private Person person = new Person(); @Override public Person getModel() { return person; } @Override public String execute() throws Exception { System.out.println(person.getUsername()); return SUCCESS; } }
在struts.xml中添加action:
<action name="login2" class="com.cdtax.struts2.LoginAction2"> <result name="success">/result.jsp</result> </action>
编写登录jsp页面:login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'login.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="login2a.action"> username:<input type="text" name="username"><br> password:<input type="password" name="password"><br> age:<input type="text" name="aaa"> date:<input type="text" name="date"> <input type="submit" value="submit"> </form> </body> </html>
编写结果页面result.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'result.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> username:${requestScope.username } <br> password:${requestScope.password }<br> age:${requestScope.age } date:${requestScope.date } aaa:${requestScope.aaa } </body> </html>
属性驱动与模型驱动的比较:
1)属性驱动灵活,准确;模型驱动不灵活,因为很多时候,页面提交过来的参数并不属于模型中的属性,也就是说页面所提交过来的参数与模型中的属性并不一致,这是很常见的情况。
2)模型驱动更加符合面向对象的编程风格,使得我们获得是对象而不是一个一个的离散的值。
小结:推荐使用属性驱动编写Action。