Struts2 基本配置

Struts2是一个优秀的MVC框架,也是我比较喜欢用的框架。它个各种配置基本都可以集中在一个xml文档中完成。现在让我们看看如何简单几步实现常用功能。

一、搭建Struts2的开发环境

1)首先是利用Maven导入依赖,其实真正使用的只有一个struts2-core包

<dependencies>
    <dependency>
        <groupId>org.apache.struts</groupId>
        <artifactId>struts2-core</artifactId>
        <version>2.3.24</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>            
pom.xml

2)新建各种package(其实建包这类的事情都是个人习惯,你也可以等用到再建)

3)配置web.xml

顺带提一句,如果你没有通过Maven来引入依赖而是通过Struts官网下载的完整开发包,可以直接找到事例配置文件。直接导入进你的项目就可以了,省时又省力,安全又方便。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Struts2 Demo</display-name>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
web.xml

4)增加资源文件struts.xml(这个文件的默认路径就是在classes下面)

直接在官方开发包里找一个放进项目中就可以了。

以上4步就可以完成struts2的开发环境搭建,真的很简单。

二、功能实现与代码示例

1)首先是建立测试使用的jsp页面。

首页:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ 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" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Basic Struts 2 Application - Welcome</title>
</head>
<body>
    <h1>Welcome To Struts 2!</h1>
    <p>
        <a href="register.jsp">Please register</a> for our network station.
    </p>
    <p>
        Here is <a href="login.jsp">login link</a>.
    </p>
</body>
</html>
index.jsp

跳转成功和跳转失败页面(每次开发我都习惯配置这样一对页面):

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ 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" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <h1>success!</h1>
    <p>Log in to the <a href="manager/management">Management</a></p>
    <s:property value="#session.user" />
    <s:debug></s:debug>
</body>
</html>
success.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ 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" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    <h1>error!</h1>
    <s:property value="#request.message" />
    <s:debug></s:debug>
</body>
</html>
error.jsp

注册页面:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ 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" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>register</title>
</head>
<body>
    <h1>register</h1>
    <s:form action="register">
        <s:textfield name="userVo.userName" label="User Name" />
        <s:password name="userVo.userPassword" label="User Password" />
        <s:password name="userVo.userPasswordConfirm" label="Confirm" />
        <s:submit />
    </s:form>
</body>
</html>
register.jsp

登录页面:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ 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" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>login</title>
</head>
<body>
    <h1>login</h1>
    <s:form action="login">
        <s:textfield name="user.userName" label="User Name" />
        <s:password name="user.userPassword" label="User Password" />
        <s:submit />
    </s:form>
</body>
</html>
login.jsp

后台管理页面:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ 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" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>management</title>
</head>
<body>
    <h1>Management</h1>
    <a href="manager/management-add">add</a>
    <br />
    <a href="manager/management-remove">remove</a>
    <br />
    <a href="manager/management-modify">modify</a>
    <br />
    <s:property value="#request.operate" />
</body>
</html>
management.jsp

2)配置struts.xml

由于我已经事先在IDE中完成了整个项目,所以这里就直接提供完整配置。实际开发中往往都是一条一条增加的,特别是拦截器和监听器的配置其实是在整个action都完成以后才添加的功能,具体的测试步骤就不一一赘述了。

<?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>
    <!-- struts2 支持"!"的动态方法调用,但并不建议 -->
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />
    <!-- 配置一个监听器 -->
    <bean type="com.opensymphony.xwork2.ActionEventListener" class="action.listener.ServiceListener" />
    
    <package name="default" namespace="/" extends="struts-default">
        <!-- 自定义拦截器需要同时继承默认拦截器栈 -->
        <interceptors>
            <interceptor name="timer" class="action.interceptor.Timer" />
            <interceptor-stack name="myStack">
                <interceptor-ref name="defaultStack" />
                <interceptor-ref name="timer" />
            </interceptor-stack>
        </interceptors>
        <!-- 在package下配置的拦截器可以对所有action生效 -->
        <default-interceptor-ref name="myStack" />
        <!-- 若用户请求不存在,跳转掉首页。减少报错的几率 -->
        <default-action-ref name="index" />
        <!-- 配置统一的跳转页面,一般针对异常处理 -->
        <global-results>
            <result name="error">/error.jsp</result>
        </global-results>
        <action name="index">
            <result>/index.jsp</result>
        </action>
        <action name="register" class="action.RegisterAction" method="execute">
            <result name="success">/login.jsp</result>
            <result name="input">/register.jsp</result>
        </action>
        <action name="login" class="action.LoginAction" method="login">
            <result name="success">/success.jsp</result>
        </action>
        <!-- 省略了方法调用和结果集返回字符串,默认就是execute()方法和success结果集 -->
        <action name="management" class="action.ManagementAction">
            <result>/management.jsp</result>
        </action>
    </package>
    <!-- 配置包继承 -->
    <package name="manager" namespace="/manager" extends="default">
        <action name="management" class="action.ManagementAction">
            <result>/management.jsp</result>
        </action>
        <!-- 使用通配符的动态方法调用是struts2推荐的方法 -->
        <action name="management-*" class="action.ManagementAction" method="{1}">
            <result name="success">/management.jsp</result>
        </action>
    </package>
</struts>
struts.xml

3)编写功能代码

(1)model和modelVo

package model;

public class User {
    private int id;
    private String userName;
    private String userPassword;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "User [userName=" + userName + ", userPassword=" + userPassword + "]";
    }

}
User.java
package model.vo;

public class UserVo {
    private String userName;
    private String userPassword;
    private String userPasswordConfirm;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    public String getUserPasswordConfirm() {
        return userPasswordConfirm;
    }

    public void setUserPasswordConfirm(String userPasswordConfirm) {
        this.userPasswordConfirm = userPasswordConfirm;
    }

}
UserVo.java

(2)service

配置了两个用户可以正常登陆,其中admin是管理员可以登陆后台

package service;

import model.*;

/*
 * 模拟后台数据库操作,orm框架都可以通过这个端口扩展
 */
public class GeneralService {
    public boolean save(User user) {
        return true;
    }

    public boolean login(User user) {
        if (user.getUserName().equals("admin") && user.getUserPassword().equals("admin")) {
            return true;
        }
        if (user.getUserName().equals("Learnhow") && user.getUserPassword().equals("Learnhow")) {
            return true;
        }
        return false;
    }

    public boolean isAdmin(User user) {
        if (user.getUserName().equals("admin") && user.getUserPassword().equals("admin")) {
            return true;
        }
        return false;
    }
}
GeneralService.java

(3)action、interceptor和listener

package action;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import model.User;
import service.GeneralService;
/*
 * 用户登录
 */
public class LoginAction extends ActionSupport {
    private static final long serialVersionUID = 1L;
    private GeneralService generalService = new GeneralService();
    private User user;

    public String login() throws Exception {
        if (generalService.login(user)) {
            //获得session对象,也可以通过SessionAware继承。还可以获得request和application对象。
            Map<String, Object> session = (Map) ActionContext.getContext().get("session");
            session.put("user", user);
            return SUCCESS;
        }
        Map<String, Object> request = (Map) ActionContext.getContext().get("request");
        request.put("message", "The user name or password mistake, please login again");
        return ERROR;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

}
LoginAction.java
package action;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import model.User;
import service.GeneralService;

/*
 * 管理员登录
 */
public class ManagementAction extends ActionSupport {
    // GeneralService对象没有新建,而是通过监听器注入的
    private GeneralService generalService;
    private Map<String, Object> request = (Map) ActionContext.getContext().get("request");

    @Override
    public String execute() throws Exception {
        Map<String, Object> session = (Map) ActionContext.getContext().get("session");
        User user = (User) session.get("user");
        if (user.getUserName().equals("admin") && user.getUserPassword().equals("admin")) {
            return SUCCESS;
        }
        return ERROR;
    }

    // 动态的add()方法调用
    public String add() throws Exception {
        request.put("operate", "add");
        return SUCCESS;
    }

    public String remove() throws Exception {
        request.put("operate", "remove");
        return SUCCESS;
    }

    public String modify() throws Exception {
        request.put("operate", "modify");
        return SUCCESS;
    }

    public GeneralService getGeneralService() {
        return generalService;
    }

    public void setGeneralService(GeneralService generalService) {
        this.generalService = generalService;
    }

}
ManagementAction.java
package action;

import com.opensymphony.xwork2.ActionSupport;

import model.User;
import model.vo.UserVo;
import service.GeneralService;
/*
 * 用户注册
 */
public class RegisterAction extends ActionSupport {
    private static final long serialVersionUID = 1L;
    private GeneralService generalService = new GeneralService();
    private User user;
    //添加了setter和getter方法的变量会跟随请求被存入值栈
    private UserVo userVo;

    @Override
    public String execute() throws Exception {
        user = new User();
        user.setUserName(userVo.getUserName());
        user.setUserPassword(userVo.getUserPassword());
        generalService.save(user);
        return SUCCESS;
    }
    
    //struts2的验证方法,可以针对表单做动态验证。调用验证方法的返回字符串是input
    @Override
    public void validate() {
        if (userVo.getUserName().length() == 0) {
            addFieldError("userVo.userName", "user name is required.");
        }
        if (userVo.getUserPassword().length() == 0) {
            addFieldError("userVo.userPassword", "user password is required.");
        }
        if (!userVo.getUserPassword().equals(userVo.getUserPasswordConfirm())) {
            addFieldError("userVo.userPasswordConfirm", "passwords don't match");
        }
    }

    public UserVo getUserVo() {
        return userVo;
    }

    public void setUserVo(UserVo userVo) {
        this.userVo = userVo;
    }
}
RegisterAction.java
package action.interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/*
 * 给action添加一个运行时间的拦截器
 */
public class Timer extends AbstractInterceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        long startTime = System.currentTimeMillis();
        String result = invocation.invoke();
        long endTime = System.currentTimeMillis();
        System.out.println("Time:" + (endTime - startTime));
        return result;
    }

}
Timer.java
package action.listener;

import com.opensymphony.xwork2.ActionEventListener;
import com.opensymphony.xwork2.util.ValueStack;

import action.*;
import model.*;
import service.GeneralService;
/*
 * 实现的ActionEventListener的监听器,可以针对action和异常处理
 * 根据官方文档的描述,监听器的作用是在action实例化的过程中或有异常发生的时候增加逻辑处理,这一点不同于拦截器。也就是说监听器是可以对action做出区分的。
 */
public class ServiceListener implements ActionEventListener {

    public Object prepare(Object action, ValueStack stack) {
        if (action instanceof ManagementAction) {
            //通过struts2框架为特定action注入对象
            ((ManagementAction) action).setGeneralService(new GeneralService());
        }
        return action;
    }

    public String handleException(Throwable t, ValueStack stack) {
        return null;
    }

}
ServiceListener.java

Struts2基本配置大概就是这样,其实也没有什么难度,关键是好用。不过现在好像依然使用Struts2新开发的项目越来越少了,更多项目使用SpringMVC代替,但是如果是我自己写项目Struts依然是首选,因为我比较“土”!

最后依照惯例附上整个项目的部署目录和IDE版本:

原文地址:https://www.cnblogs.com/learnhow/p/5112794.html