一. result的配置
result通过属性name对应到ActionSupport子类方法中return的字符串上。 假定该字符串为"page",那result就把"page"映射到page.jsp前端去。
前端测试代码
请求部分:
<!-- 参数name要对应到 ActionSupport 处理类中的name属性上——需要有getter&setter方法 -->
<a href="hello?name=Struts2" target="_blank">默认转发_dispatcher</a><br/>
<!-- “!” 动态调用 hello 处理类 HelloAction的 baby(),c(),ra()方法。url可以带参数 -->
<a href="hello!baby?name=Struts2" target="_blank">重定向_redirect</a><br/>
<a href="hello!c?name=Struts2" target="_blank">链式处理_chain</a><br/>
<a href="hello!ra?name=Struts2" target="_blank">重定向到Action_redirectAction</a><br/>
<!-- target="_blank"表示新开一个浏览器窗口 -->
<a href="hello" target="_blank">全局result配置</a><br/>
响应部分(success.jsp 或者 baby.jsp):
Name:${name }<br/>
Name2:${name2 }
这里EL表达式中的变量name和name2对应Action处理类中的同名属性(属性要有getter和setter方法)。
响应部分(error.jsp):
错误信息:${error }
来看看struts.xml的配置
<!-- 允许动态方法调用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<package name="manage" extends="struts-default">
<!-- 全局性地将Action处理类中各方法的return "error"一并映射到error.jsp -->
<!-- 方法中public static final String ERROR = "error";(Action接口中定义) -->
<global-results>
<!-- hello的<action>中有<result name="error">的就走那里的映射,没有就走<global-results>中的<result name="error">映射。 -->
<result name="error">error.jsp</result>
</global-results>
<!-- 将url "/hello" 映射到 Action处理类 HelloAction extends ActionSupport -->
<action name="hello" class="com.bee.action.HelloAction">
<!-- 省略type即默认为type="dispatcher" -->
<result name="success">success.jsp</result>
<!-- baby在ActionSupport的子类中(实际上就是一个javabean)——HelloAction,
相应的方法中返回同名字符串即可映射到此处定义的baby.jsp:
public String baby() throws Exception{
retrun "baby";
}
-->
<result name="baby" type="redirect">baby.jsp</result>
<!-- 链式处理chain把请求重定向到url “/hello2”继续处理(可带请求参数)。url “hello”和“/hello2”的Action处理类可以共享数据(通过http get的参数)。hello2的Action处理类可以没有参数对应的属性——靠hello的Action处理类的同名属性。 -->
<result name="c" type="chain">hello2</result>
<!-- 把请求重定向到Action处理类,而不是一个url。 重定向前后Action处理类不能共享http get参数。-->
<result name="ra" type="redirectAction">hello2</result>
</action>
<action name="hello2" class="com.bee.action.HelloAction2">
<!--
public class HelloAction2 extends ActionSupport{
private String name2;
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
@Override
public String execute() throws Exception {
this.name2="你好啊";
return SUCCESS;
// Action接口中:public static final String SUCCESS = "success";
}
}
-->
<result name="success" type="dispatcher">success.jsp</result>
</action>
</package>
这里type的类型:
- 默认是dispatcher内部转发(http get参数可以在不同页面间传递)
- redirect重定向(http get参数不可以在不同页面间传递)
- chain 链式 (http get参数可以在不同页面间传递)
- redirectAction 重定向到action (http get参数不可以在不同页面间传递)
type的其他类型:
- freemarker 模版引擎
- httpheader 返回一个已配置好的HTTP头消息相应
- stream 将原始数据作为流返回浏览器
- velocity 呈现velocity模版
- xslt 该xml可以通过xsl模版进行转换
- plaintext 返回普通文本内容
二. struts2拦截器
struts2的拦截器是在访问某个Action或Action的某个方法,属性之前或之后插入的操作。拦截器是AOP的一种实现。
先看看struts.xml中的配置
<package name="manage" extends="struts-default">
......
</package>
其中extends="struts-default"对应
struts-2.3.16.3\src\core\src\main\resources\struts-default.xml
其中的 <interceptors>标签部分预定义了各种拦截器
而该标签的子节点<interceptor-stack>定义了拦截器栈
拦截器interceptors预定义了若干拦截器,而拦截器栈interceptor-stack将预定义的拦截器按功能分组形成一个处理集合。
- 配置拦截器
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="manage" extends="struts-default">
<interceptors>
<interceptor name="myInterceptor" class="com.bee.interceptor.MyInterceptor"></interceptor>
</interceptors>
<action name="hello" class="com.bee.action.HelloAction">
<result name="success">success.jsp</result>
<interceptor-ref name="myInterceptor"></interceptor-ref> 栈顶
<!-- 如果不定义defaultStack,那么其他拦截器将不被执行。 -->
<interceptor-ref name="defaultStack"></interceptor-ref> 栈底
</action>
</package>
</struts>
- 拦截器的定义
package com.bee.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void destroy() {
System.out.println("MyInterceptor销毁");
}
@Override
public void init() {
System.out.println("MyInterceptor初始化");
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("在Action执行之前");
String result = invocation.invoke();
System.out.println("result:" + result);
System.out.println("在Action执行之后");
return result;
}
}
- 实例——登录验证
- 定义实体类
package com.bee.model;
public class User {
private String userName;
private String password;
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;
}
}
- 定义service类用于模拟数据库查询
package com.bee.service;
import com.bee.model.User;
public class UserService {
public boolean login(User user) {
if ("bee".equals(user.getUserName()) && "123456".equals(user.getPassword())) {
return true;
} else {
return false;
}
}
}
- 定义登录验证类
package com.bee.action;
import java.util.Map;
import com.bee.model.User;
import com.bee.service.UserService;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private UserService userService = new UserService();
private User user;
private String error;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
@Override
public String execute() throws Exception {
if (userService.login(user)) {
ActionContext actionContext = ActionContext.getContext();
Map<String, Object> session = actionContext.getSession();
session.put("currentUser", user);
return SUCCESS;
} else {
this.error = "用户名或密码错误";
return ERROR;
}
}
}
- 定义登录拦截器
package com.bee.interceptor;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LoginInterceptor implements Interceptor {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void destroy() {
System.out.println("LoginInterceptor销毁");
}
@Override
public void init() {
System.out.println("LoginInterceptor初始化");
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("在Action执行之前");
ActionContext actionContext = invocation.getInvocationContext();
Map<String, Object> session = actionContext.getSession();
Object currentUser = session.get("currentUser");
String result = null;
if (currentUser != null) {
result = invocation.invoke();
} else {
HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext()
.get(ServletActionContext.HTTP_REQUEST);
request.setAttribute("error", "请先登录!");
result = "error";
}
System.out.println("result:" + result);
System.out.println("在Action执行之后");
return result;
}
}
- 定义被拦截的目标Action
要访问的页面(URL)需要登录验证,验证通过才能访问。要借助session。
package com.bee.action;
import com.opensymphony.xwork2.ActionSupport;
public class GrilAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String execute() throws Exception {
System.out.println("一个长腿白皙MM");
return SUCCESS;
}
}
- 配置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="user" extends="struts-default">
<interceptors>
<interceptor name="loginInterceptor"
class="com.bee.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="loginStack">
<interceptor-ref name="loginInterceptor"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref> <!-- 系统默认拦截器栈 -->
</interceptor-stack>
</interceptors>
<!-- 自定义默认的拦截器栈——覆盖系统默认拦截器栈 -->
<default-interceptor-ref name="loginStack"></default-interceptor-ref>
<global-results>
<result name="error">error.jsp</result>
</global-results>
<action name="login" class="com.bee.action.LoginAction">
<result name="success">success.jsp</result>
<!-- 定义恢复系统默认拦截器栈——取消登录拦截 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<action name="seemm" class="com.bee.action.GrilAction">
<result name="success">success.jsp</result>
</action>
</package>
</struts>
- 前端jsp
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="login" method="post">
用户名:<input type="text" name="user.userName"/>
密码:<input type="password" name="user.password"/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
success.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>当前用户:${currentUser.userName }
</body>
</html>
error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
错误信息:${error } <a href="login.jsp">登录</a>
</body>
</html>
3. struts.xml的标签配置顺序
如果标签配置顺序不满足约定会出现如下错误:
元素类型为 "package" 的内容必须匹配 "(result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)"
那么正确的标签配置顺序是什么呢?
result-types
interceptors
default-interceptor-ref
default-action-ref
default-class-ref
global-results
global-exception-mappings
action 注意<action>标签要求包含<result>标签。