struts2作为一个老牌的mvc框架,他在很多项目中都有运用,今天我们来一起简单回顾和学习下他。
一:简单的helloworld
创建一个maven工程test_struts2.
pom文件:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- struts2 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.4.1</version>
</dependency>
</dependencies>
web.xml我们加上struts2的过滤器
<!-- Struts2配置 -->
<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>
写一个HelloAction
public class HelloAction extends ActionSupport{
public String execute(){
System.out.println("HelloAction execute()...");
return "success";
}
}
写一个struts.xml文件放在resources目录下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="basePackage" extends="struts-default" namespace="/">
<action name="hello" class="com.julyday.action.HelloAction">
<result name="success">/jsp/hello/hello.jsp</result>
</action>
</package>
</struts>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!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=ISO-8859-1">
<title>hello.jsp</title>
</head>
<body>
this is julyday hello.jsp.
</body>
</html>
struts节点下最常用的三个标签:
package:包,struts用package来组织action。
package标签下的标签:
action:处理的action,方法及返回
constant:struts的常用配置信息。
常用配置的默认值可以查看struts-core.jar目录下的org.apache.struts2下的default.properties文件
include:包含其他子包。
ok,部署下项目就可以访问了。http://localhost:8080/test_struts2/hello.action
接着我们把其他标签也写了一下:
分别测试下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="basePackage" extends="struts-default" namespace="/">
<!-- 返回类型,struts2为我们提供了丰富的返回类型 -->
<!-- <result-types></result-types>-->
<!-- 拦截器 -->
<interceptors>
<interceptor name="myInterceptor" class="com.julyday.interceptor.MyInterceptor"/>
<interceptor-stack name="myStack" >
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="myInterceptor"/>
</interceptor-stack>
</interceptors>
<!-- 默认的拦截器栈,建议不要修改 -->
<default-interceptor-ref name="defaultStack"/>
<!-- 默认的action处理类 -->
<default-action-ref name="default-action"></default-action-ref>
<!-- 系统默认的class为ActionSupport,与default-action-ref同时出现时,执行class -->
<default-class-ref class="com.julyday.action.DefaultClassRefAction"/>
<!-- 全局返回结果 -->
<global-results>
<result name="index">/index.jsp</result>
<result name="arithmetic">/jsp/arithmetic.jsp</result>
</global-results>
<!-- 异常处理页面 -->
<global-exception-mappings>
<exception-mapping result="arithmetic" exception="java.lang.ArithmeticException"/>
</global-exception-mappings>
<!-- actions -->
<action name="default-action">
<result name="success">/jsp/hello/hello.jsp</result>
</action>
<action name="hello" class="com.julyday.action.HelloAction">
<result name="success">/jsp/hello/hello.jsp</result>
<interceptor-ref name="myStack"/>
</action>
</package>
</struts>
public class DefaultClassRefAction extends ActionSupport{
public String execute(){
System.out.println("DefaultClassRefAction execute()...");
return "index";
}
}
public class MyInterceptor extends AbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Action action = (Action) invocation.getAction();
long start = System.currentTimeMillis();
String result = invocation.invoke();
long end = System.currentTimeMillis();
System.out.println("MyInterceptor 拦截"+action.getClass().getName()+",执行该action时间是"+(end-start));
return result;
}
}
public class HelloAction extends ActionSupport{
public String execute(){
System.out.println("HelloAction execute()...");
int i = 1/0;
return "success";
}
}
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!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=ISO-8859-1">
<title>arithmetic.jsp</title>
</head>
<body>
this is an arithmetic exception page.
</body>
</html>
http://localhost:8080/test_struts2/hello.action
结果:到了异常页面this is an arithmetic exception page.
去掉除法再执行一次,拦截器也启作用了。
http://localhost:8080/test_struts2/xxx.action
结果:julyday Hello World!
显然实际项目里面没这么简单,至少我们还需要和前台交互,交互的话就需要servlet API了。
显然实际项目里面没这么简单,至少我们还需要和前台交互,交互的话就需要servlet API了。
public class LoginAction extends ActionSupport implements ServletRequestAware{
private String name;
private String password;
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
private HttpServletRequest request;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String execute() {
//获取页面参数值的四种方式:
ActionContext ctx = ActionContext.getContext();
HttpServletRequest req1 = ServletActionContext.getRequest();
System.out.println("ServletActionContext 方式:"+req1.getParameter("name"));
HttpServletRequest req2 = (HttpServletRequest) ctx.get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);
System.out.println("ActionContext 方式:" + req2.getParameter("name"));
System.out.println("set 方式:"+name);
System.out.println("ServletRequestAware 方式:"+request.getParameter("name"));
//向Application中添加属性
Integer count = (Integer)ctx.getApplication().get("count");
if(count == null){
count = 1;
}else{
count++;
}
ctx.getApplication().put("count", count);
//向Session中添加属性
ctx.getSession().put("session", name);
//向Cookie中添加属性
Cookie c = new Cookie("user",password);
c.setMaxAge(3600);
HttpServletResponse response = ServletActionContext.getResponse();
response.addCookie(c);
//向request中添加属性
ctx.put("message", "登录成功");
return SUCCESS;
}
}
我们将之前的struts.xml文件重命名为hello.xml。
新增main.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="userPackage" extends="struts-default" namespace="/user">
<action name="index">
<result>/jsp/user/index.jsp</result>
</action>
<span style="white-space:pre"> </span><action name="login" method="login" class="com.julyday.action.LoginAction">
<span style="white-space:pre"> </span><result>/jsp/user/success.jsp</result>
<span style="white-space:pre"> </span></action>
</package>
</struts>
新的struts.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<include file="hello.xml"/>
<include file="main.xml"/>
</struts>
<%@ 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>index.jsp</title>
</head>
<body>
<form action="login" method="post">
<div style="margin-left: 300px;margin-top: 200px">
姓名:<input name="name" type="text"/><br></br>
密码:<input name="password" type="password"/><br></br>
<input type="submit" value="登录"/>
</div>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>success.jsp</title>
</head>
<body>
欢迎您:${name}<br><br/>
网站访问次数:${applicationScope.count}<br><br/>
session中的值:${sessionScope.session}<br><br/>
cookie中的值:${cookie.user.value }<br><br/>
request中的值:${requestScope.message}
</body>
</html>
http://localhost:8080/test_struts2/user/index.action,这样我们就可以访问servletAPI了。
当我们的action越来越多时,我们写的xml文件就越大,有没有办法去简化呢?struts为我们提供了另外2中action调用的写法。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="userPackage" extends="struts-default" namespace="/user">
<action name="index">
<result>/jsp/user/index.jsp</result>
</action>
<!--
<action name="login" method="login" class="com.julyday.action.LoginAction">
<result>/jsp/user/success.jsp</result>
</action>
<action name="regist" method="regist" class="com.julyday.action.LoginAction">
<result name="regist">/jsp/user/regist.jsp</result>
</action>
-->
<!-- 动态方法调用方式,官方不推荐使用,存在安全问题 -->
<!--
<action name="login" class="com.julyday.action.LoginAction">
<result name="success">/jsp/user/success.jsp</result>
<result name="regist">/jsp/user/regist.jsp</result>
</action>
-->
<!-- 通配符方式 -->
<action name="*" method="{1}" class="com.julyday.action.LoginAction">
<result name="success">/jsp/user/success.jsp</result>
<result name="regist">/jsp/user/regist.jsp</result>
</action>
</package>
</struts>
<%@ 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>index.jsp</title>
<script type="text/javascript">
function regist(){
var targetForm = document.forms[0];
//targetForm.action = "login!regist";
targetForm.action = "regist";
}
</script>
</head>
<body>
<form action="login" method="post">
<div style="margin-left: 300px;margin-top: 200px">
姓名:<input name="name" type="text"/><br></br>
密码:<input name="password" type="password"/><br></br>
<input type="submit" value="登录"/><input type="submit" value="注册" οnclick="regist()" style="margin-left: 50px"/>
</div>
</form>
</body>
</html>
http://localhost:8080/test_struts2/user/index.action,这样我们再多的action我们也能根据通配符方式去写,当然我们也可以如下:
<action name="*_*" method="{1}" class="com.julyday.action.{2}Action">
<result name="success">/jsp/user/success.jsp</result>
<result name="{1}">/jsp/user/{1}.jsp</result>
</action>
<%@ 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>index.jsp</title>
<script type="text/javascript">
function regist(){
var targetForm = document.forms[0];
//targetForm.action = "login!regist";
targetForm.action = "regist_Login";
}
</script>
</head>
<body>
<form action="login_Login" method="post">
<div style="margin-left: 300px;margin-top: 200px">
姓名:<input name="name" type="text"/><br></br>
密码:<input name="password" type="password"/><br></br>
<input type="submit" value="登录"/><input type="submit" value="注册" οnclick="regist()" style="margin-left: 50px"/>
</div>
</form>
</body>
</html>
写到这,很多朋友估计和我一样,看到后缀action,都烦死了,下面,我们去掉后缀。
struts.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 让struts2关闭动态方法调用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<!-- 所有匹配*.action,*.do的请求都由struts2处理 -->
<!--<constant name="struts.action.extension" value="do,action" />-->
<!-- 所有匹配的请求都由struts2处理 -->
<!-- 除了/ 和 /index.jsp -->
<constant name="struts.action.extension" value="" />
<constant name="struts.action.excludePattern" value="/,/index.jsp"/>
<include file="hello.xml"/>
<include file="main.xml"/>
</struts>
这里稍微说下:动态调用的方式需要<constant name="struts.enable.DynamicMethodInvocation" value="true" />,但是官方都说存在安全问题了,我们最后不用了,建议加上这个并改成false。struts.action.extension可以可以根据自己想喜好来设置,这里特别注意的是如果不加后缀的话,struts是会自动过滤所有的请求,包括你在web.xml设置的welcome-file-list,所以记得去掉这些。
不过一般常用配置我们一般放在一个文件里面:
struts.properties:
#让struts2关闭动态方法调用
struts.enable.DynamicMethodInvocation=false
#所有匹配*.action,*.do的请求都由struts2处理
#struts.action.extension=do,action
#所有匹配的请求都由struts2处理
#除了/ 和 /index.jsp
struts.action.extension=
struts.action.excludePattern=/,/index.jsp
#是否启用开发模式
struts.devMode=false
#struts配置文件改动后,是否重新加载
struts.configuration.xml.reload=true
#设置浏览器是否缓存静态内容
struts.serve.static.browserCache=false
#请求参数的编码方式
struts.i18n.encoding=utf-8
#每次HTTP请求系统都重新加载资源文件,有助于开发
struts.i18n.reload=true
# 文件上传最大值10m
struts.multipart.maxSize=104857600
#让struts2支持动态方法调用
struts.enable.DynamicMethodInvocation=true
#Action名称中是否还是用斜线
struts.enable.SlashesInActionNames=false
#允许标签中使用表达式语法
struts.tag.altSyntax=true
#对于WebLogic,Orion,OC4J此属性应该设置成true
struts.dispatcher.parametersWorkaround=false
到目前我们跳转的都是jsp页面,但是struts为我们提供了多种结果类型:
在result标签我们可以制定type,默认的是dispatcher,就是使用jsp作为视图结果类型。
其他常用的有:
redirect:跳转其他的URL。
freemarket/volocity:使用FreeMarket/volocity模版作为视图结果类型。
redirectAction:跳转到其他的action。
stream:返回一个InputStream(一般用于文件下载)
plainText:显示某个页面的原始代码。
比较简单就不做例子了。
二:注解
pom.xml新增:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.3.4.1</version>
</dependency>
@Namespace("/admin")
@ParentPackage("struts-default")
@ExceptionMappings({
@ExceptionMapping(exception="java.lang.ArithmeticException", result = "error"),
@ExceptionMapping(exception="java.io.IOException", result = "ioerror")
})
@Results({@Result(name = "error", location = "/jsp/admin/error.jsp"),
@Result(name = "ioerror", location = "/jsp/admin/ioerror.jsp")})
public class AdminAction extends ActionSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Action(value = "index", results = {
@Result(name = "success", location = "/jsp/admin/index.jsp")})
public String index(){
return SUCCESS;
}
@Action(value = "login", results = {
@Result(name = "success", location = "/jsp/admin/success.jsp"),
@Result(name = "input", location = "/jsp/admin/input.jsp")})
public String login() throws IOException {
System.out.println("AdminAction login()");
//int i = 1/0;
// int j = 10;
// if( j == 10){
// throw new IOException();
// }
//如果cookie中有返回input,其他返回success
HttpServletRequest request = ServletActionContext.getRequest();
Cookie[] coolies = request.getCookies();
for(Cookie c : coolies){
if("admin".equals(c.getName())){
return INPUT;
}
}
Cookie c = new Cookie("admin",name);
c.setMaxAge(100);
HttpServletResponse response = ServletActionContext.getResponse();
response.addCookie(c);
return SUCCESS;
}
}
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>regist.jsp</title>
</head>
<body>
<form action="login" method="post">
<div style="margin-left: 300px;margin-top: 200px">
姓名:<input name="name" type="text"/><br></br>
密码:<input name="password" type="password"/><br></br>
<input type="submit" value="登录"/>
</div>
</form>
</body>
</html>
<%@ 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>index.jsp</title>
</head>
<body>
Hello ${cookie.admin.value }! 您已经登录.
</body>
</html>
<%@ 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>index.jsp</title>
</head>
<body>
Hello ${cookie.admin.value }! this is julyday admin index.jsp.
</body>
</html>
最重要的是告诉web.xml你要使用注解
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<display-name>test_struts2</display-name>
<!-- Struts2配置 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>com.julyday.action</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
ok,运行测试下。
最后放上全部的代码:代码下载