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版本:

Struts2 基本配置的更多相关文章

  1. Struts2 XML配置详解

    struts官网下载地址:http://struts.apache.org/   1.    深入Struts2的配置文件 本部分主要介绍struts.xml的常用配置. 1.1.    包配置: S ...

  2. struts2 action配置时 method 省略不写 默认执行方法是父类ActionSuppot中的execute()方法

    struts2 action配置时 method 省略不写 默认执行方法是父类ActionSuppot中的execute()方法

  3. struts2环境配置

    struts2环境配置 struts2框架,大多数框架都在使用.由于工作需要,开始做Java项目.先学个struts2. 一.下载struts2 有好多版本,我下载的是struts-2.2.1.1. ...

  4. 在Struts2中配置Action

    在Struts2中配置Action <package>: 1.定义Action使用<package>标签下的<action>标签完成,一个<package&g ...

  5. Struts2的配置

    Struts2的配置 Struts2可以通过Convention插件管理Action和结果映射,也可以通过使用XML文件进行管理,这两种方式各有好处:使用Convention插件管理减少了XML文件的 ...

  6. Struts2的配置和一个简单的例子

    Struts2的配置和一个简单的例子 笔记仓库:https://github.com/nnngu/LearningNotes 简介 这篇文章主要讲如何在 IntelliJ IDEA 中使用 Strut ...

  7. 1-1 struts2 基本配置 struts.xml配置文件详解

    详见http://www.cnblogs.com/dooor/p/5323716.html 一. struts2工作原理(网友总结,千遍一律) 1 客户端初始化一个指向Servlet容器(例如Tomc ...

  8. spring+hibernate+struts2零配置整合

    说句实话,很久都没使用SSH开发项目了,但是出于各种原因,再次记录一下整合方式,纯注解零配置. 一.前期准备工作 gradle配置文件: group 'com.bdqn.lyrk.ssh.study' ...

  9. struts2基本配置详解2

    接上篇struts2基本配置详解,还有一些配置没有讲到,下面将继续. struts.xml <package name="com.amos.web.action" names ...

随机推荐

  1. Cocos引擎开发者指南(1-5)

    Cocos引擎开发者指南 英文原版:http://www.cocos2d-x.org/docs/programmers-guide/1/ 中午翻译:http://www.cocos.com/doc/t ...

  2. x86指令集同频性能提升

    x86近5000条指令,迄今为止最复杂的指令集.这里不研究CISC & RISC,也不考虑process制程变化,主要是看最近几代IA架构对于同频率下性能的提升. x86指令集nasm文档 h ...

  3. PHP 字符串的隐式转换规则以及针对包含字母的字符串的递增/递减操作

    之前一直对 PHP 中关于字符串的算数运算隐式类型转换规则和递增/递减操作符针对字符串的操作比较模糊,今天总结一下. 一.隐式转换 二进制算术运算符的隐式类型转换规则(http://php.net/m ...

  4. 阿里云服务器Linux CentOS安装配置(六)resin多端口配置、安装、部署

    阿里云服务器Linux CentOS安装配置(六)resin多端口配置.安装.部署 1.下载resin包 http://125.39.66.162/files/2183000003E08525/cau ...

  5. [uva12170]Easy Climb

    还是挺难的一个题,看了书上的解析以后还是不会写,后来翻了代码仓库,发现lrj又用了一些玄学的优化技巧. #include <algorithm> #include <iostream ...

  6. PGPool 配置错误定位 s_do_auth: expecting R got E

    自从按照教程 http://www.pgpool.net/docs/latest/pgpool-zh_cn.html#hba配置好PGPool以后,每次启动 pgpool -c -n -D 都报 s_ ...

  7. 使用PowerShell解三道测试开发笔试题

    在网上看到了三道测试开发的笔试题,答案是用Python解的.这段时间正好在学PowerShell,练习一下:) 1. 验证邮箱格式 2. 获取URL的后缀名 3. 获取前一天时间或前一秒 我的解法是: ...

  8. 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)

    synchronized: 在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的.原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不 ...

  9. SpringMVC常用配置-处理程序异常以及404错误

  10. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...