项目的初始配置见:idea快速搭建struts2框架:https://blog.csdn.net/m0_70083523/article/details/127899288
额外的其他jar包,可能会用到:
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.12version>
dependency>
<dependency>
<groupId>javax.servlet.jsp.jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>jsp-apiartifactId>
<version>2.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>2.5version>
<scope>providedscope>
dependency>
public class HelloAction implements Action {
@Getter
@Setter
private String name;
@Getter
@Setter
private String message;
public String execute() throws Exception {
System.out.println("hello struts2~~~struts构建完成");
System.out.println("接收到的name是===="+name);
message="----message----"; //相当于request.SetAttribute();
return "OK";
}
}
【读取请求参数的时候使用Set方法,在浏览器页面读取值得时候使用get方法,必须要给属性进行get/set方法】
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<html>
<head>
<title>Hellotitle>
head>
<body>
<h2>struts2h2>
<br/>
<form action="hello" method="post">
<input name="name">
<input type="submit" value="提交">
form>
<span>后端读取值:${requestScope.message}span>
body>
html>
创建实体类User:set/get方法使用了注解
@Getter
@Setter
@ToString
public class User {
private Integer id; //id
private String userName; //用户名称
}
public class HelloAction implements Action {
@Getter
@Setter
private User user;
public String execute() throws Exception {
System.out.println("hello struts2~~~struts构建完成");
System.out.println("user==="+user);
return "OK"; //返回的结果
}
}
传值:属性名.实体类属性
如:user.id
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<html>
<body>
<h2>struts2h2>
<br/>
<form action="hello" method="post">
id:<input name="user.id"><br/>
userName:<input name="user.userName"><br/>
<input type="submit" value="提交">
form>
body>
html>
<constant name="struts.action.extension" value="do,html"/>
<constant name="struts.i18n.encoding" value="utf-8"/>
<constant name="struts.ui.theme" value="simple"/>
<package name="default" namespace="/" extends="struts-default">
package是包。Struts2的package与java中的package类似,可以把同一个业务模块的action和result集中到一个包中,方便管理。不同的是Struts2的包可以继承,比如商品有增删改查操作,订单也有增删该查操作,我们可以将商品和订单的action分别放两个package中方便管理。
name属性
是包的名字,一个struts.xml中可以有很多个package,通过name属性进行区分。namespace
是命名空间,/代表的是根目录。namespace的作用类似于SpringMVC中在Controller类上加@RequestMapping注解。相当于此包中所有的action前都加一个父路径。如:extends属性
是继承,通常都会继承struts-default
。在struts-default中定义了大星的struts特性,如拦截器和参数处理的功能,如果不继承struts-default,会遇到参数无法绑定或找不到action类。
<package name="default" namespace="/user" extends="struts-default">
<action name="hello" class="com.wxy.action.HelloAction">
<result name="success">/index.jspresult>
action>
package>
<action name="login" class="com.wxy.action.LoginAction">
<result name="success">index.jspresult>
<result name="error">error.jspresult>
<result name= "input">login.jspresult>
action>
action标签用来处理请求和响应结果。
- name属性是请求的名字,此处不需要加.action。同一个package下的action不能重名。
- class属性指定处理该请求的类,是类的全路径。默认的处理请求时会去类中找名为execute的方法。如果不指定class,将默认ActionSupport为处理请求的类。
- result标签用来处理请求结果,name属性是Action类中返回的字符串。标签的值是要跳转的页面地址。name如果不写的话,默认是success。
示例:
实体类:
@Data
public class User {
private String userName;
private String password;
}
UserAction类:
public class UserAction extends ActionSupport {
@Getter
@Setter
private User user;
public String execute() throws Exception {
System.out.println("用户名:" + user.getUserName());
System.out.println("密码:" + user.getPassword());
if ("admin".equals(user.getUserName()) && "1234567".equals(user.getPassword())) {
// 将user对象保存在session中
Map<String, Object> session = null;
session = ActionContext.getContext().getSession();
session.put("user_session", user);
return "success";
} else {
return "error";
}
}
}
login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录title>
head>
<body>
<form action="hello" method="post">
用户名:<input type="text" name="user.userName" /><br />
密 码:<input type="password" name="user.password" /><br />
<input type="submit" />
form>
body>
html>
success.jsp:
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<html>
<head>
<title>登录成功title>
head>
<body>
<h2>欢迎您,${sessionScope.get("user_session").userName}h2>
body>
html>
error.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h2>用户名或密码不匹配。</h2>
</body>
</html>
struts.xml:
<package name="userAction" namespace="/" extends="struts-default">
<action name="login" class="com.wxy.action.UserAction" method="execute">
<result name="success">/success.jspresult>
<result name="error">/fail.jspresult>
action>
package>
访问路径:localhost:8080/login
【Struts的业务核心是Action类】前面我们已经使用过了此类实现Action接口
- 一个Action业务里可以实现Action接口,也可以
继承ActionSupport类
。在ActionSupport中提供了一些实现好的业务方法。在以后的编程中,建议全部继承ActionSupport类。- Action中的方法必须
返回一个String类型的字符串
,这个字符串与struts.xml中result标签的name属性相对应,struts.xml会根据返回的字符串查找对应的页面。
下面讲述继承ActionSupport类
的使用:
可以存在多个方法且可自定义,但是都得返回String类型:
创建ActionTest类:
public class TestAction extends ActionSupport {
@Setter
@Getter
private User user;
//登录的方法
public String login() {
System.out.println("登录方法 ");
return SUCCESS;
}
//注册的方法
public String register() {
System.out.println("注册方法 ");
return SUCCESS;
}
}
struts.xml的配置:
DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="default" namespace="/user" extends="struts-default">
<action name="login" class="com.wxy.action.TestAction" method="login">
<result name="success">/index.jspresult>
action>
<action name="register" class="com.wxy.action.TestAction" method="register">
<result name="success">/index.jspresult>
action>
package>
struts>
action标签method属性:调用具体是类中的哪个方法(method=“方法名”)
- method="login"表示要调用类中的login()方法处理请求。如果找不到login()方法,默认会去找execute()方法,在找不到,报错。
如果一个类中有多个业务方法,又不想给每个业务方法都配置一个action标签,可以使用动态方法调用,语法是:请求名!方法名.action
Struts2中可以开启调用动态方法,设置的常量为:
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<package name="default" namespace="/user" extends="struts-default">
<global-allowed-methods>login,registglobal-allowed-methods>
<action name="user" class="com.wxy.action.TestAction">
<result name="success">/index.jspresult>
action>
package>
登录访问路径:localhost:8080/user/user!login
注册访问路径:localhost:8080/user/user!register
另—种减少action数量的方法是使用通配符:
<package name="default" namespace="/user" extends="struts-default">
<global-a1lowed-methods>login,registglobal-a1lowed-methods>
<action name="*User" class="com.wxy.action.TestAction" method="{1}">
<result name="success">/index.jspresult>
<result name="error">{1}.jspresult>
action>
package>
name属性值为
*User
就是匹配以User结束的请求,method="{1}"中的{1}匹配的就是User中的*
- 登录访问路径:localhost:8080/user/loginUser
- 注册访问路径:localhost:8080/user/registerUser
如果在struts.xml中找不到匹配的action,将会报错。可以设置一个默认的action,当所有请求都不匹配时,将匹配默认action。
<default-action-ref name="default"/>
<action name="default">
<result>/error.jspresult>
action>
- < default-action-ref>对当前的package有效。
- action标签的class省略调用的ActionSupport类,result的name省略将默认为success。
- 注意default-actiop-ref必须在
所有的action标签上面
。也就是说default-action-ref出现在action标签之前。不然不符合DTD验证。
【常用结果有三种类型: dispatcher、redirect、redirectAction、chain】
result的默认类型就是dispatcher。以下两个标签是等价的:
<result name="success" type="dispatcher ">index.jspresult>
<result name="success">index.jspresult>
- dispatcher的结果等同于Servlet中的请求转发,即:request.getRequestDispatcher(“success.jsp”).forward(request, response);
- 请求转发的意思是当前请求中的参数、属性在下一个页面或请求中仍然可以使用。
redirect是重定向,重定向之后,当前请求中的参数和属性在下一个页面或请求中将不能使用。
<result name="success" type="redirect" >index.jspresult>
相当于Servlet中的:response.sendRedirect(“success.jsp”); 地址栏改变
redirectAction与redirect类似,不过redirectAction是重定向到某一个action
主要redirectAction的action后缀是action
<action name="reg" class="com.wxy.action.UserAction" method="regist">
<result name="success" type="redirectAction">login.actionresult>
action>
如果要调用不同package下的action,需要在result中传参数:
<package name="default" namespace="/" extends="struts-default">
<action name="login" class="com.wxy.action.UserAction" method="login">
<result name="success" type="redirectAction">
<param name="namespace">/userparam>
<param name="actionName">hello.actionparam>
<param name="username">123par am>
result>
<result name="error">login.jspresult>
action>
此时访问路径:localhost:8080/test就会跳转到localhost:8080/user/hello.do
redirectAction不能共享request中的数据,如果想共享数据,可以将type设置为chain。
注意chain的action后面没有后缀
<action name="test" class="com.wxy.action.UserAction" method="regist">
<result name="success" type="chain">helloresult>
action>
动态结果是根据某个属性不同的值返回到不同页面。
@Data
private String username;
@Data
private string page;
I
public String login() {
//参数和业务略
System.out.println("我是登录");
if ("admin".equals(username)) { //管理员去管理页
page = "admin_page";
}else { //其他人去用户页
page = "user_page";
}
return SUCCESS;
}
<action name="page" class="com.wxy.action.ResultTest" method="goPage">
<result name="success">${page}.jspresult>
action>
访问路径:
- localhost:8080/page?page=admin_page 返回管理员管理页面
- localhost:8080/page?page=user_page 返回用户使用页面
- 可以用来设置访问权限
一个action中的result只能在当前action中有效。如果多数的action中都用到同一个结果,可以将此结果定义为全局结果。比如index代表用户没有登录,需要跳转到登录页面,那么可以设置成全局结果:
<global-results>
<result name="success">index.jspresult>
global-results>
如果action中定义了与全局结果同名的result,将优先action标签中的。
注意global-results在action之前,default-action-ref之后。
? 代表出现0次或1次
星号 代表0次或多次
- result-types?
- interceptors?
- default-interceptor-ref?
- default-action-ref?
- default-class-ref?
- global-results?
- global-exception-mappings?
- action*