Struts2_實戰演練(中)
面向切面編程
針對特定功能寫出通用類,所關注的業務方面即切面
Login.Jsp->login.do
攔截器攔截login.do 所對應的action對象
攔截器可以控制action before/after ;
攔截器的內部會以被攔截的action爲原始版本 創建一個與之相同的action
攔截器配置:
² 聲明
² 引用
Web.xml |
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
<filter> <filter-name>filterDispatcher</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter>
<!—此兩個配置部分針對於SiteMesh--> <filter> <filter-name>struts-cleanup</filter-name> <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class> </filter>
<filter> <filter-name>sitemesh</filter-name> <filter-class>org.apache.struts2.sitemesh.FreeMarkerPageFilter</filter-class> </filter>
<filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<filter-mapping> <filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<filter-mapping> <filter-name>filterDispatcher</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
</web-app>
|
裝飾所有頁面
decorators.xml |
<?xml version="1.0" encoding="UTF-8"?> <decorators defaultdir="/decorator"> <!-- 例外情況,對於哪些頁面不使用裝飾器 --> <excludes> <pattern>/foodlist.jsp</pattern> </excludes> <decorator name="main" page="decorator.jsp"> <!-- 使用main裝飾器裝飾所有的JSP頁面 --> <pattern>/*</pattern> </decorator> </decorators>
|
攔截器使用
配置文件
Struts.xml |
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="loginpackage" extends="struts-default"> <!-- 自定義攔截器的聲明 --> <interceptors> <interceptor name="checkUser" class="com.ibm.myiterceptor.CheckUserInterceptor"></interceptor> </interceptors>
<action name="login" class="com.ibm.action.LoginAction"> <result name="success">main.jsp</result> <result name="input">fail.jsp</result> </action>
<action name="showfoodlist" class="com.ibm.action.FoodOperAction"> <result name="success">foodlist.jsp</result> <result name="input">main.jsp</result> <!-- 引用自定義的攔截器 --> <interceptor-ref name="checkUser"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
</package> </struts> |
登錄
Index.jsp |
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <% 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>用戶登錄頁面</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>
<s:property value="message"/>
用戶登錄 <hr/> <form action="login.do" method="post" name="loginform" id="loginform"> 用戶姓名:<input type="text" name="uname" id="uname"> <br/> 用戶密碼:<input type="text" name="upwd"> <br/> <input type="submit" value="用戶登錄"/> </form>
</body> </html>
|
經過配置文件指定後跳轉到LoginActin.java中,默認執行execute方法
LoginAction.java |
package com.ibm.action;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport implements SessionAware{
private String uname;
private String upwd;
private Map session;
//提示消息 private String message;
@Override public String execute() throws Exception { //進行判斷,如果用戶輸入框不爲空則把session中放入值,返回“success”,跳轉到main.jsp if(uname!=null){ session.put("userName", uname); return "success"; } return "input"; }
public String getUname() { return uname; }
public void setUname(String uname) { this.uname = uname; }
public String getUpwd() { return upwd; }
public void setUpwd(String upwd) { this.upwd = upwd; }
public void setSession(Map<String, Object> arg0) { this.session=arg0;
}
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; } }
|
點擊showfoodlist跳轉到FoodOperAction.java執行默認方法execute
Main.jsp
Main.jsp |
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <% 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>系統導航</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> 系統導航 <a href="showfoodlist.do">食品列表</a> //escape爲false指的是可以使用html標記語言,並生效 <s:property value="message" escape="false"/>
</body> </html>
|
此處有攔截器
CheckUserInterceptor.java |
package com.ibm.myiterceptor;
import java.util.ArrayList; import java.util.List; import java.util.Map;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/** * 用戶檢查攔截器 * @author Administrator * */ public class CheckUserInterceptor extends AbstractInterceptor { // // @Override // public String intercept(ActionInvocation arg0) throws Exception { // //得到被攔截的Action的上下文信息 // ActionContext context=arg0.getInvocationContext(); // // Map map=context.getSession(); // String uName=(String) map.get("userName"); //如果用戶名不爲空則放行,否則不放行 // if(uName!=null){ // return arg0.invoke(); // } // context.put("message", "請登錄後再來訪問<a href='index.jsp'>登錄</a>"); // return "input"; // }
/** * 設計權限校驗 */ public String intercept(ActionInvocation arg0) throws Exception{ //此部分的內容是需要根據登錄的用戶名稱入庫進行查詢的 //利用hibernate查詢出用戶的權限列表
//僞代碼部分 假設用戶有showfoodlist addfood的權限 List<String> list = new ArrayList<String>(); list.add("showfoodlist"); list.add("addfood");
//得到攔截的Action的上下文信息 ActionContext context = arg0.getInvocationContext(); System.out.println("用戶訪問的欄目:"+context.getName());
String actionName=context.getName(); if (list.contains(actionName)) { return arg0.invoke(); } context.put("message","權限不足,此部分功能受限"); return "input"; }
} |
|
FoodOperAction.java |
package com.ibm.action;
import com.opensymphony.xwork2.ActionSupport;
public class FoodOperAction extends ActionSupport{ private String message;
@Override public String execute() throws Exception { System.out.println("訪問成功"); return "success"; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
} |
攔截放行後正常跳轉到foodlist.jsp頁面
foodlist.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>食品列表頁</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> 食品列表頁 </body> </html>
|
動態代理
Isaler.java |
package com.ibm.proxydemo;
/** * 統一的規則 * @author Administrator * */ public interface ISaler {
public void buy(int num);
}
|
CpuSaler.java |
package com.ibm.proxydemo;
public class CpuSaler implements ISaler{
public void buy(int num) { System.out.println("買"+num+"個CPU");
}
}
|
KeyBoardSaler.java |
package com.ibm.proxydemo;
public class KeyBoardSaler implements ISaler{
public void buy(int num) { System.out.println("買"+num+"個鍵盤"); }
}
|
SaleProxyer.java |
||
package com.ibm.proxydemo;
public class SaleProxyer { ISaler isaler;
public SaleProxyer(ISaler isaler) { this.isaler=isaler; }
public void buy(int num) { System.out.println("買的商品是:"+isaler.getClass().getName()); System.out.println("客戶買了"+num+"個");
}
}
|
動態代理
DySaleProxy.java(動態代理) |
||
package com.ibm.proxydemo.dynamicproxy;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class DySaleProxy implements InvocationHandler{
private static Object targetObj;
//此構造函數 非使用者自行調用,由JAVA自行控制調用 //此構造函數的作用即將產生的代理對象作爲invoke方法中的 //目標對象參數 public DySaleProxy(Object obj){ System.out.println("產生的目標對象是:"+obj.getClass().getName()); this.targetObj=obj; }
public static Object getProxy(Object delegate){ //根據調用的對象類型 動態產生匹配的代理類,因爲指定的調用類類型不確定,所有用Object代替 Object obj=Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), new DySaleProxy(delegate)); return obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("傳遞的參數是:"+args[0]); return method.invoke(targetObj, args); }
}
|
日期類型轉換
Index.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 'index.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> 用戶註冊 <hr> <form action="register.do" name="userform" id="userform"> 用戶姓名:<input type="text" name="uname" id="uname"/> <br/> 用戶年齡:<input type="text" name="age" id=age/> <br/> 出生日期:<input type="text" name="birthday" id="birthday"/> <br/> <input type="submit" value="用戶註冊"/> </form> </body> </html> |
Struts.xml |
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="userpackage" extends="struts-default"> <action name="register" class="com.ibm.action.UserOperActiond"> <result name="success">success.jsp</result> </action> </package> </struts> |
UserOperAction.java |
||||
package com.ibm.action;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class UserOperAction extends ActionSupport{ private String uname;
private int age;
private Date birthday;
public String getUname() { return uname; }
public void setUname(String uname) { this.uname = uname; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
@Override public String execute() throws Exception { System.out.println("轉換後的日期:"+birthday); return "success"; }
}
|
常用類型轉換器(第二種轉換方式)
DataConvert.ava |
||
package com.ibm.convert;
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;
public class DataConvert extends StrutsTypeConverter{
/** * 頁面到action的轉換 */ @Override public Object convertFromString(Map arg0, String[] arg1, Class arg2) { // TODO Auto-generated method stub DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Date dt = null; //判斷頁面輸入框中用戶是否輸入了內容 if(arg1[0]!=null){ //用戶輸入的內容是否要轉換成日期類型 if(arg2==Date.class){ try { dt=df.parse(arg1[0]); } catch (ParseException e) { e.printStackTrace(); } return dt; } } return null; }
/** * 把action中的數據內容轉換成String類型後輸出到頁面 */ @Override public String convertToString(Map arg0, Object arg1) { DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String str=""; if(arg1!=null){ str=df.format(arg1); } return str; } }
|
用戶輸入信息的校驗
UserOperAction.java(手動校驗) |
package com.ibm.action;
import java.util.Date;
import org.apache.struts2.interceptor.validation.SkipValidation;
import com.opensymphony.xwork2.ActionSupport;
public class UserOperAction extends ActionSupport{ private String uname;
private Integer age;
private Date birthday;
public String getUname() { return uname; }
public void setUname(String uname) { this.uname = uname; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday){ this.birthday = birthday; }
//系統缺省不予驗證的方法(跳過驗證) //@SkipValidation public String execute() throws Exception { System.out.println("轉換後的日期:"+birthday); return "success"; }
//此方法用來校驗用戶輸入的信息,手動校驗 // @Override // public void validate() { //// super.validate(); // if((uname)!=null&&uname.length()>4){ // addFieldError("msg","輸出的內容超出了制定的範圍,請重新輸入"); // } // // } } |
配置文件中校驗
UserOperAction-conversion.properties(配置文件中校驗) |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"> <!-- dtd文件必須加上,否則報語法錯誤 --> <validators> <field name="uname"> <field-validator type ="requiredstring"> <param name="trim">true</param> <message>用戶名不合法</message> </field-validator> </field>
<field name="age"> <field-validator type="required"> <message>You must enter a value for age.</message> </field-validator> <field-validator type="int"> <param name="min">13</param> <param name="max">19</param> <message>age between ${min} and ${max} current age is ${age}</message> </field-validator> </field>
</validators>
|