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>
|