Struts2学习笔记
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。其全新的Struts 2的体系结构与Struts 1的体系结构差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。虽然从Struts 1到Struts 2有着太大的变化,但是相对于WebWork,Struts 2的变化很小。
创建一个动态Web工程,版本使用2.5
并将struts2所需的核心包加入lib中
|
修改web.xml(所有的页面请求在此地截获,统一由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> |
编写HelloWorldAction.java
|
内容如下
package com.kingsoft.action;
import com.opensymphony.xwork2.Action;
public class HelloWorldAction implements Action{
@Override public String execute() throws Exception { System.out.println("执行了Action的默认方法"); return SUCCESS; //SUCCESS=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="helloWorld" extends="struts-default"> <action name="hello" class="com.kingsoft.action.HelloWorldAction"> <result name="success">helloworld.jsp</result> </action> </package>
</struts>
在页面请求/hello时会执行HelloWorldAction.java,如果返回值为SUCCESS则跳转到helloworld.jsp页面 |
运行原理
|
Struts2自动获取getter/setter设置的数据
SetNameAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.Action;
public class SetNameAction implements Action{
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String execute() throws Exception { System.out.println("execute方法被执行"); return SUCCESS; }
} |
修改struts.xml
<package name="helloWorld" extends="struts-default"> <action name="hello" class="com.kingsoft.action.HelloWorldAction"> <result name="success">helloworld.jsp</result> </action> <action name="test01" class="com.kingsoft.action.SetNameAction"> <result name="success">test01.jsp</result> </action> </package> |
test01.jsp
<body> <h1> ${name}你好 </h1> </body> |
使用浏览器
地址栏中输入http://localhost:8080/struts2-01/test01?name=张三
使用Debug模式得出结论: 当在地址栏中输入后,SetNameAction获取到name的值张三,setName中的name有值,当跳转到test01.jsp时,页面有${name}这时会触发getName方法得到值并返回页面显示 |
以上方式采用get方式提交
我们也可以采用post方式提交
<body> <form action="test01" method="post"> 用户名:<input type="text" name="name"><br> <input type="submit" value="提交"> </form> </body> |
在开发中一般Action都是继承ActionSupport
SetNameSupportAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class SetNameSupportAction extends ActionSupport{
private static final long serialVersionUID = -9158813220652853654L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String execute() throws Exception { System.out.println("execute方法被执行"); 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="helloWorld" extends="struts-default"> <action name="hello" class="com.kingsoft.action.HelloWorldAction"> <result name="success">helloworld.jsp</result> </action> <action name="test01" class="com.kingsoft.action.SetNameAction"> <result name="success">test01.jsp</result> </action> <action name="test02" class="com.kingsoft.action.SetNameSupportAction"> <result name="success">test01.jsp</result> </action> </package>
</struts> |
test01.jsp不变
<body> <h1> ${name}你好 </h1> </body> |
Action设置数据
第一种方式:属性驱动 A:基本数据类型属性
首先创建一个UserService.java用于处理登录业务
package com.kingsoft.service;
import com.kingsoft.entity.User;
public class UserService {
public Boolean login(User user) { Boolean flag = Boolean.FALSE; if ("wang".equals(user.getUserName()) && "123".equals(user.getPassword())) { flag = Boolean.TRUE; } return flag; } } |
编写UserAction.java
package com.kingsoft.action; import com.kingsoft.entity.User; import com.kingsoft.service.UserService; import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{
private static final long serialVersionUID = 1L; private String userName; private String password; private UserService userService = new UserService();
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; }
@Override public String execute() throws Exception { System.out.println("执行了UserAction的execute"); User user = new User(); user.setUserName(userName); //页面传值后自动装配 user.setPassword(password); if(userService.login(user)) { return SUCCESS; }else { return ERROR; } } } |
修改struts.xml
<package name="helloWorld" extends="struts-default"> <action name="login" class="com.kingsoft.action.UserAction"> <result name="success">success.jsp</result> <result name="error">error.jsp</result> </action> </package> |
创建login.jsp登录页面
<body> <form action="login" method="post"> 用户名:<input type="text" name="userName"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="登录"> </form> </body> |
创建success.jsp
<h1> 欢迎${userName}登录 </h1> |
创建error.jsp
<h1> ${userName}不是合法用户 </h1> |
第一种方式:属性驱动 B:JavaBean类型属性
首先创建一个UserService.java用于处理登录业务
package com.kingsoft.service;
import com.kingsoft.entity.User;
public class UserService {
public Boolean login(User user) { Boolean flag = Boolean.FALSE; if ("wang".equals(user.getUserName()) && "123".equals(user.getPassword())) { flag = Boolean.TRUE; } return flag; } } |
编写UserAction.java
package com.kingsoft.action;
import com.kingsoft.entity.User; import com.kingsoft.service.UserService; import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{
private static final long serialVersionUID = 1L; private UserService userService = new UserService(); private User user;
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
@Override public String execute() throws Exception { System.out.println("执行了UserAction的execute"); if(userService.login(user)) { return SUCCESS; }else { return ERROR; } } } |
编写struts.xml
<package name="helloWorld" extends="struts-default"> <action name="login" class="com.kingsoft.action.UserAction"> <result name="success">success.jsp</result> <result name="error">error.jsp</result> </action> </package> |
创建login.jsp
<body> <form action="login" method="post"> 用户名:<input type="text" name="user.userName"><br> //user.userName自动绑定数据 密码:<input type="password" name="user.password"><br> <input type="submit" value="登录"> </form> </body> |
创建success.jsp
<h1> 欢迎${userName}登录 </h1> |
创建error.jsp
<h1> ${userName}不是合法用户 </h1> |
第二种方式:模型驱动(在一个Action中只能适配一种数据类型)
编写UserModelAction.java
package com.kingsoft.action;
import com.kingsoft.entity.User; import com.kingsoft.service.UserService; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; //这个实现ModelDriven的Action只能接收User类型的数据 public class UserModelAction extends ActionSupport implements ModelDriven<User>{
private static final long serialVersionUID = 8683820191542343750L; private UserService userService = new UserService(); private User user = new User();
@Override public User getModel() { return user; }
@Override public String execute() throws Exception { if (userService.login(user)) { return SUCCESS; }else { return ERROR; } }
} |
编写struts.xml
<package name="helloWorld" extends="struts-default"> <action name="loginModel" class="com.kingsoft.action.UserModelAction"> <result name="success">success.jsp</result> <result name="error">error.jsp</result> </action> </package> |
编写登录页面loginModel.jsp
<form action="loginModel" method="post"> 用户名:<input type="text" name="userName"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="登录"> </form> |
其他的不用修改
Struts2处理数目不定的字符串
创建hobby.jsp
<body> <form action="hobby" method="post"> 爱好: <input type="checkbox" name="hobby" value="唱歌">唱歌 <input type="checkbox" name="hobby" value="跳舞">跳舞 <input type="checkbox" name="hobby" value="睡觉">睡觉 <input type="checkbox" name="hobby" value="玩CF">玩CF <input type="submit" value="提交" /> </form>
</body> |
创建HobbyAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class HobbyAction extends ActionSupport{
private static final long serialVersionUID = 4516916341891363874L;
private String[] hobby;
public String[] getHobby() { return hobby; }
public void setHobby(String[] hobby) { this.hobby = hobby; }
@Override public String execute() throws Exception { if(hobby!=null) { for(String ho : hobby) { System.out.println(ho); } } return SUCCESS; }
} |
编写struts.xml
<package name="helloWorld" extends="struts-default"> <action name="hobby" class="com.kingsoft.action.HobbyAction"> <result name="success">result.jsp</result> </action> </package> |
Struts2处理不定数目的javaBean对象
创建实体Student.java
package com.kingsoft.entity;
public class Student {
private String name; private String sex; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", sex=" + sex + ", age=" + age + "]"; } } |
编写StudentAction.java
package com.kingsoft.action;
import java.util.List;
import com.kingsoft.entity.Student; import com.opensymphony.xwork2.ActionSupport;
public class StudentAction extends ActionSupport{
private static final long serialVersionUID = -8469771940895541706L; private List<Student> students;
public List<Student> getStudents() { return students; }
public void setStudents(List<Student> students) { this.students = students; }
@Override public String execute() throws Exception { for(Student student : students) { System.out.println(student); } return SUCCESS; } } |
配置struts.xml
<package name="helloWorld" extends="struts-default"> <action name="student" class="com.kingsoft.action.StudentAction"> <result name="success">result.jsp</result> </action> </package> |
编写页面addstudents.jsp
<body> <form action="student" method="post"> <table> <tr> <th>姓名</th> <th>性别</th> <th>年龄</th> </tr> <tr> <td><input type="text" name="students[0].name"/></td> <td><input type="text" name="students[0].sex"/></td> <td><input type="text" name="students[0].age"/></td> </tr> <tr> <td><input type="text" name="students[1].name"/></td> <td><input type="text" name="students[1].sex"/></td> <td><input type="text" name="students[1].age"/></td> </tr> <tr> <td colspan="3"> <input type="submit" value="提交"/> </td> </tr> </table> </form> </body> |
此处需要注意的是页面中students必须和Action中List<Student> students一致才能取到值
配置文件struts.xml讲解
Package中的参数
name:本身并没有什么意义,它只是标识package的一种方式,用于分包管理
<package name="stock" extends="struts-default"> <action name="inStock" class="com.kingsoft.action.InStockAction"> <result name="success">result.jsp</result> </action> <action name="outStock" class="com.kingsoft.action.OutStockAction"> <result name="success">result.jsp</result> </action> </package> <package name="operation" extends="struts-default"> <action name="windFarmRun" class="com.kingsoft.action.WindFarmRunAction"> <result name="success">result.jsp</result> </action> <action name="tubineFarmRun" class="com.kingsoft.action.TubineFarmRumAction"> <result name="success">result.jsp</result> </action> </package> |
namespace:命名空间,但在地址栏访问时必须加前缀/test01/stuUpdate才能访问
${pageContext.request.contextPath}获取绝对路径,因为命名空间指向了/test01以后,在访问绝对路径下的result.jsp就会访问不到,所以需要加入绝对路径。
<package name="hobby" namespace="/test01" extends="struts-default"> <action name="hobbyList" class="com.kingsoft.action.HobbyAction"> <result name="success">${pageContext.request.contextPath}/result.jsp</result> </action> </package> <package name="student" namespace="/test02" extends="struts-default"> <action name="stuUpdate" class="com.kingsoft.action.StudentAction"> <result name="success">${pageContext.request.contextPath}/result.jsp</result> </action> </package> |
Action中的参数
name:提供给外部调用的名称
class:标识类的存放位置
<action name="hobbyList" class="com.kingsoft.action.HobbyAction"> <result name="success">${pageContext.request.contextPath}/result.jsp</result> </action> |
method:让请求执行Action中特定的方法
修改HobbyAction.java类
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class HobbyAction extends ActionSupport{
private static final long serialVersionUID = 4516916341891363874L;
@Override public String execute() throws Exception { System.out.println("执行了HobbyAction的默认方法"); return SUCCESS; }
public String show()throws Exception{ System.out.println("指定执行了Show方法"); return SUCCESS; }
} |
修改struts.xml
<package name="hobby" namespace="/test01" extends="struts-default"> <action name="hobbyList" class="com.kingsoft.action.HobbyAction" method="show"> <result name="success">${pageContext.request.contextPath}/result.jsp</result> </action> </package> |
当请求调用/test01/hobbyList时会触发指定的方法show
分模块管理配置(是将多个配置文件在struts.xml中进行统一管理)
创建StudentAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class StudentAction extends ActionSupport{
private static final long serialVersionUID = -4141514990102568879L;
@Override public String execute() throws Exception { System.out.println("执行了StudentAction的默认方法"); return SUCCESS; } } |
创建TeacherAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class TeacherAction extends ActionSupport{
private static final long serialVersionUID = 5323960877931126937L;
@Override public String execute() throws Exception { System.out.println("执行了TeacherAction的默认方法"); return SUCCESS; } }
|
在src根目录下创建student.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="student" namespace="/student" extends="struts-default"> <action name="stuList" class="com.kingsoft.action.StudentAction"> <result name="success"> ${pageContext.request.contextPath}/result.jsp </result> </action> </package> </struts> |
在src根目录下创建teacher.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="teacher" namespace="/teacher" extends="struts-default"> <action name="teacList" class="com.kingsoft.action.TeacherAction"> <result name="success">${pageContext.request.contextPath}/result.jsp</result> </action> </package> </struts> |
创建struts.xml,将student.xml和teacher.xml集成到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> <include file="student.xml"></include> <include file="teacher.xml"></include> </struts> |
在浏览器中输入
http://localhost:8080/struts2-01/student/stuList
http://localhost:8080/struts2-01/teacher/teacList
分别测试
===============================================================================
使用通配符调用方法
创建GradeAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class GradeAction extends ActionSupport{
private static final long serialVersionUID = -5961665991535524959L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String list()throws Exception{ System.out.println("班级查找"); name="班级查找"; return SUCCESS; }
public String add()throws Exception{ System.out.println("班级添加"); name="班级添加"; return SUCCESS; }
public String update()throws Exception{ System.out.println("班级修改"); name="班级修改"; return SUCCESS; }
public String delete()throws Exception{ System.out.println("班级删除"); name="班级删除"; return SUCCESS; } } |
创建StudentAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class StudentAction extends ActionSupport{
private static final long serialVersionUID = -8469771940895541706L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String list()throws Exception{ System.out.println("学生查找"); name="学生查找"; return SUCCESS; }
public String add()throws Exception{ System.out.println("学生添加"); name="学生添加"; return SUCCESS; }
public String update()throws Exception{ System.out.println("学生修改"); name="学生修改"; return SUCCESS; }
public String delete()throws Exception{ System.out.println("学生删除"); name="学生删除"; 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="student" extends="struts-default"> <action name="student_*" class="com.kingsoft.action.StudentAction" method="{1}"> <result name="success">result.jsp</result> </action> </package> <package name="grade" extends="struts-default"> <action name="grade_*" class="com.kingsoft.action.GradeAction" method="{1}"> <result name="success">result.jsp</result> </action> </package> </struts>
说明:当页面请求为student_add时,在struts.xml配置文件中student_会把*解析出来,赋值给method中,从而可以调用Action中的指定方法名add |
创建index.jsp
<body> <h1>通配符</h1> <a href="student_list" target="_blank">学生信息查询</a> <a href="student_add" target="_blank">学生信息添加</a> <a href="student_update" target="_blank">学生信息修改</a> <a href="student_delete" target="_blank">学生信息删除</a> <br /> <br /> <a href="grade_list" target="_blank">班级信息查询</a> <a href="grade_add" target="_blank">班级信息添加</a> <a href="grade_update" target="_blank">班级信息修改</a> <a href="grade_delete" target="_blank">班级信息删除</a> <br />
</body> |
动态方法调用(大概了解)
继续使用之前测试的StudentAction.java和GradeAction.java
修改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> <!-- 开启动态方法调用 --> <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<package name="student" extends="struts-default"> <action name="student" class="com.kingsoft.action.StudentAction"> <result name="success">result.jsp</result> </action> </package> <package name="grade" extends="struts-default"> <action name="grade" class="com.kingsoft.action.GradeAction"> <result name="success">result.jsp</result> </action> </package> </struts> |
修改index.jsp
<body> <h1>动态方法调用</h1> <a href="student!list" target="_blank">学生信息查询</a> <a href="student!add" target="_blank">学生信息添加</a> <a href="student!update" target="_blank">学生信息修改</a> <a href="student!delete" target="_blank">学生信息删除</a> <br /> <br /> <a href="grade!list" target="_blank">班级信息查询</a> <a href="grade!add" target="_blank">班级信息添加</a> <a href="grade!update" target="_blank">班级信息修改</a> <a href="grade!delete" target="_blank">班级信息删除</a> <br /> </body> |
Struts会根据请求的student!list进行拆分,动态的调用!后面的方法名
Action的生命周期
测试一下
创建HelloAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport{
private static final long serialVersionUID = -3052754509240462646L;
@Override public String execute() throws Exception { return SUCCESS; }
public HelloAction() { System.out.println("HelloAction被创建一次"); } } |
修改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="test" extends="struts-default"> <action name="hello" class="com.kingsoft.action.HelloAction"> <result name="success">result.jsp</result> </action> </package> </struts> |
在浏览器的地址栏中输入http://localhost:8080/struts2-01/hello
当每次重新加载页面发出请求时,Action都会重新实例化一次HelloAction
|
result配置
- type默认是dispatcher内部转发
- type为redirect重定向
- type为chain链条
- type为redirectAction重定向到action
以上4个为常用类型,一定要掌握
首先测试1:dispatcher内部转发, 2:redirect重定向
创建TestStrutsAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class TestStrutsAction extends ActionSupport{
private static final long serialVersionUID = 4577159549507722143L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String redirectMethod()throws Exception{ System.out.println("执行重定向方法"); return SUCCESS; }
public String dispatchMethod()throws Exception{ System.out.println("执行内部转发方法"); 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="test01" extends="struts-default"> <action name="dispatcher" class="com.kingsoft.action.TestStrutsAction" method="dispatchMethod"> <result name="success" type="dispatcher">success.jsp</result> </action> <action name="redirect" class="com.kingsoft.action.TestStrutsAction" method="redirectMethod"> <result name="success" type="redirect">success.jsp</result> </action> </package> </struts> |
创建index.jsp页面
<body> <a href="dispatcher?name=Struts2" target="_blank">内部转发</a> <a href="redirect?name=Struts2" target="_blank">重定向</a> </body> |
创建success.jsp页面
<body> <h1> 你好 :${name} </h1> </body> |
在地址栏输入http://localhost:8080/struts2-01/index.jsp
当点击内部转发时,跳转的页面能取到值
当点击重定向时,跳转的页面无值
首先测试2:chain链条
创建HelloAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport{
private static final long serialVersionUID = 4577159549507722143L;
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; } } |
修改TestStrutsAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class TestStrutsAction extends ActionSupport{
private static final long serialVersionUID = 4577159549507722143L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String redirectMethod()throws Exception{ System.out.println("执行重定向方法"); return SUCCESS; }
public String dispatchMethod()throws Exception{ System.out.println("执行内部转发方法"); return SUCCESS; }
public String chain()throws Exception{ return "chain"; } } |
修改struts.xml
<struts>
<package name="test01" extends="struts-default"> <action name="dispatcher" class="com.kingsoft.action.TestStrutsAction" method="dispatchMethod"> <result name="success" type="dispatcher">success.jsp</result> </action> <action name="redirect" class="com.kingsoft.action.TestStrutsAction" method="redirectMethod"> <result name="success" type="redirect">success.jsp</result> </action> <action name="chain" class="com.kingsoft.action.TestStrutsAction" method="chain"> <result name="chain" type="chain">hello</result> </action> <action name="hello" class="com.kingsoft.action.HelloAction"> <result name="success" type="dispatcher">success.jsp</result> </action> </package> </struts> 运行说明: 当请求/chain时调用TestStrutsAction中的chain方法,如果返回值为chain则调用hello,而hello可调用HelloAction中的execute方法,如果返回为success则内部转发到success.jsp页面,在跳转过程中name和name2的值都可用。 |
修改index.jsp页面
<body> <a href="dispatcher?name=Struts2" target="_blank">默认转发_dispatcher</a> <a href="redirect?name=Struts2" target="_blank">重定向_redirect</a> <a href="chain?name=Struts2" target="_blank">链条_chain</a> </body> |
首先测试3:redirectAction重定向到Action
修改TestStrutsAction.java
package com.kingsoft.action; import com.opensymphony.xwork2.ActionSupport; public class TestStrutsAction extends ActionSupport{ private static final long serialVersionUID = 4577159549507722143L; private String name;
public String getName() { return name; } public void setName(String name) { this.name = name; } public String redirectMethod()throws Exception{ System.out.println("执行重定向方法"); return SUCCESS; } public String dispatchMethod()throws Exception{ System.out.println("执行内部转发方法"); return SUCCESS; } public String chain()throws Exception{ return "chain"; }
public String redirectAction()throws Exception{ return "redirectAction"; } } |
修改struts.xml
<package name="test01" extends="struts-default"> <action name="dispatcher" class="com.kingsoft.action.TestStrutsAction" method="dispatchMethod"> <result name="success" type="dispatcher">success.jsp</result> </action> <action name="redirect" class="com.kingsoft.action.TestStrutsAction" method="redirectMethod"> <result name="success" type="redirect">success.jsp</result> </action> <action name="chain" class="com.kingsoft.action.TestStrutsAction" method="chain"> <result name="chain" type="chain">hello</result> </action> <action name="redirectAction" class="com.kingsoft.action.TestStrutsAction" method="redirectAction"> <result name="redirectAction" type="redirectAction">hello</result> </action>
<action name="hello" class="com.kingsoft.action.HelloAction"> <result name="success" type="dispatcher">success.jsp</result> </action> </package> 运行说明: 当请求/redirectAction时会调用TestStrutsAction中的redirectAction方法,返回值为redirectAction时会调用hello,hello则调用HelloAction,当HelloAction返回success时转发到success.jsp,需要注意的是type=redirectAction时的值是不能传递到success.jsp中的。 |
编写index.jsp
<body> <a href="dispatcher?name=Struts2" target="_blank">默认转发_dispatcher</a><br> <a href="redirect?name=Struts2" target="_blank">重定向_redirect</a><br> <a href="chain?name=Struts2" target="_blank">链条_chain</a><br> <a href="redirectAction?name=Struts2" target="_blank"> 重定向到Action_redirectAction </a><br> </body> |
result的全局配置
编写ErrorAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class ErrorAction extends ActionSupport{
private static final long serialVersionUID = 4385046150975999632L;
private String name; private String error;
public String getError() { return error; }
public void setError(String error) { this.error = error; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String execute() throws Exception { if(name==null || "".equals(name)) { this.error = "name为空值"; return ERROR; }else { return SUCCESS; } } } |
编写struts.xml
<package name="test01" extends="struts-default"> <!-- 全局错误配置 --> <global-results> <result name="error">error.jsp</result> </global-results> <action name="testErr" class="com.kingsoft.action.ErrorAction"> <result name="success">success.jsp</result> </action> </package> |
编写error.jsp
<body> <h3 style="color: red;"> 错误信息提示:<br> ${error} </h3> </body> |
编写index.jsp
<body> <a href="testErr" target="_blank">全局错误页面测试</a><br> </body> |
Struts2的拦截器
1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.
2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
|
测试自定义拦截器
创建TestStrutsAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class TestStrutsAction extends ActionSupport{
private static final long serialVersionUID = 4577159549507722143L; private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String execute() throws Exception { System.out.println("执行Action"); return SUCCESS; }
} |
创建自定义的拦截器MyInterceptor.java
package com.kingsoft.intercept;
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor{
private static final long serialVersionUID = -179341758452344000L;
@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("Action执行之后"); return result; } } |
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="interceptor" extends="struts-default"> <interceptors> <interceptor name="myInterceptor" class="com.kingsoft.intercept.MyInterceptor"> </interceptor> </interceptors>
<action name="test" class="com.kingsoft.action.TestStrutsAction"> <result name="success">success.jsp</result> <!-- 引用拦截器是有一定的顺序的 1.外层可以引用自定义的拦截器 2.内存引用默认的拦截器 如果只引用自定义的拦截器,则默认的拦截器将失效 --> <interceptor-ref name="myInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package> </struts> |
在浏览器地址栏输入http://localhost:8080/struts2-01/test?name=zhangsan
|
测试拦截器来实现用户登录和访客登录
包和类的分布情况 |
创建User.java
package com.kingsoft.entity;
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; }
} |
创建UserService.java
package com.kingsoft.service;
import com.kingsoft.entity.User;
public class UserService {
public Boolean login(User user) { Boolean flag = Boolean.FALSE; if("wang".equals(user.getUserName()) && "123".equals(user.getPassword())) { flag = Boolean.TRUE; } return flag; } } |
创建LoginAction.java
package com.kingsoft.action;
import java.util.Map;
import com.kingsoft.entity.User; import com.kingsoft.service.UserService; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
private static final long serialVersionUID = 8497468271246178208L; private User user; private String error; private UserService userService = new UserService();
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; } } } |
创建访客LookAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class LookAction extends ActionSupport{
private static final long serialVersionUID = 1L;
@Override public String execute() throws Exception { System.out.println("look"); return SUCCESS; } } |
创建自定义拦截器LoginInterceptor.java
package com.kingsoft.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 = 7326386639551398115L;
@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; } } |
配置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="login" extends="struts-default"> <!-- 拦截器 --> <interceptors> <interceptor name="loginInterceptor" class="com.kingsoft.interceptor.LoginInterceptor"/>
<!-- 定义自己的拦截器栈 --> <interceptor-stack name="myStack"> <interceptor-ref name="loginInterceptor"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors>
<!-- 设置默认的拦截器栈 --> <default-interceptor-ref name="myStack"/>
<!-- 全局错误页面 --> <global-results> <result name="error">error.jsp</result> </global-results>
<!-- 用户登录 --> <action name="user" class="com.kingsoft.action.LoginAction"> <result name="success">success.jsp</result> <!-- 用户登录action不需要myStack拦截器栈, 所以必须指定Struts默认的拦截器defaultStack, 如果不设置defaultStack拦截器,Struts就会设置 我们自定义的拦截器栈myStack --> <interceptor-ref name="defaultStack" /> </action>
<!-- 临时访客登录 --> <action name="guest" class="com.kingsoft.action.LookAction"> <result name="success">success.jsp</result> <!-- 此时访客就使用上了默认的拦截器栈myStack --> </action> </package>
</struts> |
编写login.jsp
<body> <form action="user" method="post"> 用户名:<input type="text" name="user.userName"><br> 密码:<input type="password" name="user.password"><br> <input type="submit" value="登录"> </form> </body> |
编写error.jsp
<body> <h3> 错误信息:${error} </h3> <a href="login.jsp">登录</a> </body> |
编写success.jsp
<body> 当前用户: ${currentUser.userName} </body> |
浏览器地址栏:http://localhost:8080/struts2-02/guest
说明访客操作已经被拦截 |
值栈与OGNL
创建动态web工程
web.xml配置文件加入struts过滤
<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> |
在src根目录下创建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="hello" extends="struts-default"> <action name="hello" class="com.kingsoft.action.HelloAction"> <result name="success">success.jsp</result> </action> </package>
</struts> |
在对应的包中创建HelloAction.java
package com.kingsoft.action;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.ValueStack;
public class HelloAction extends ActionSupport{ private static final long serialVersionUID = -3052754509240462646L;
@Override public String execute() throws Exception { ActionContext actionContext = ActionContext.getContext(); //值栈 ValueStack stack = actionContext.getValueStack(); stack.set("name", "张三(valueStack)"); stack.set("age", 11); //session Map<String, Object> session = actionContext.getSession(); session.put("name", "李四(session)"); session.put("age", 23); //application Map<String, Object> application = actionContext.getApplication(); application.put("name", "赵六(applicaton)"); application.put("age", 15); return SUCCESS; } } |
编写success.jsp
<%@ 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>Insert title here</title> </head> <body> <% request.setAttribute("name", "王五(request)"); request.setAttribute("age", 13); %> 值栈数据: <s:property value="name"/> <s:property value="age"/><br> 请求参数:接收页面中传递的参数 <s:property value="#parameters.name"/> <s:property value="#parameters.age"/><br> request: <s:property value="#request.name"/> <s:property value="#request.age"/><br> session: <s:property value="#session.name"/> <s:property value="#session.age"/><br> application: <s:property value="#application.name"/> <s:property value="#application.age"/><br>
</body> </html> |
测试,在浏览器地址栏中输入http://localhost:8080/struts2-03/hello?name=king&age=18
接收参数时需要使用#并加上对应的范围 |
测试OGNL访问对象类型,List类型,Map类型
创建Student.java
package com.kingsoft.entity;
public class Student { private String name; private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; }
public Student(String name, int age) { super(); this.name = name; this.age = age; }
public Student() { super(); }
} |
在原有的HelloAction.java中修改
public class HelloAction extends ActionSupport{ private static final long serialVersionUID = -3052754509240462646L; private Student student; private List<Student> students; private Map<String, Student> studentMap;
public Map<String, Student> getStudentMap() { return studentMap; }
public void setStudentMap(Map<String, Student> studentMap) { this.studentMap = studentMap; }
public List<Student> getStudents() { return students; }
public void setStudents(List<Student> students) { this.students = students; }
public Student getStudent() { return student; }
public void setStudent(Student student) { this.student = student; }
@Override public String execute() throws Exception { ActionContext actionContext = ActionContext.getContext(); //值栈 ValueStack stack = actionContext.getValueStack(); stack.set("name", "张三(valueStack)"); stack.set("age", 11); //session Map<String, Object> session = actionContext.getSession(); session.put("name", "李四(session)"); session.put("age", 23); //application Map<String, Object> application = actionContext.getApplication(); application.put("name", "赵六(applicaton)"); application.put("age", 15); //Student对象 student = new Student("三胖子", 23); //List对象 students = new ArrayList<Student>(); students.add(new Student("AA",11)); students.add(new Student("BB",12)); students.add(new Student("CC",13)); //Map对象 studentMap = new HashMap<String, Student>(); studentMap.put("good", new Student("学霸",23)); studentMap.put("bad", new Student("学渣",24));
return SUCCESS; } } |
修改原有的success.jsp页面
<body> <% request.setAttribute("name", "王五(request)"); request.setAttribute("age", 13); %> 值栈数据: <s:property value="name"/> <s:property value="age"/><br> 请求参数: <s:property value="#parameters.name"/> <s:property value="#parameters.age"/><br> request: <s:property value="#request.name"/> <s:property value="#request.age"/><br> session: <s:property value="#session.name"/> <s:property value="#session.age"/><br> application: <s:property value="#application.name"/> <s:property value="#application.age"/><br> OGNL访问Student对象: <s:property value="student.name"/> <s:property value="student.age"/><br> OGNL访问List对象: <s:property value="students[0].name"/> <s:property value="students[0].age"/><br> OGNL访问Map对象: <s:property value="studentMap['good'].name"/> <s:property value="studentMap['good'].age"/> </body> |
OGNL访问静态属性和静态方法
创建MyStatic.java,其中定义了静态的属性和方法
package com.kingsoft.commond;
public class MyStatic {
public static final String content = "我是静态属性";
public static String showUrl() { System.out.println("我是静态方法"); return "我是静态方法"; } } |
需要注意的是如果在页面中访问静态方法时必须在struts.xml中添加配置
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
<package name="hello" extends="struts-default"> <action name="hello" class="com.kingsoft.action.HelloAction"> <result name="success">success.jsp</result> </action> </package> |
创建test_static.jsp
<%@ 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>Insert title here</title> </head> <body>
<s:property value="@[email protected]"/><br> <s:property value="@[email protected]()"/> </body> </html> |
Struts2标签
搭建测试环境
创建动态Web工程,导入对应的jar包,设置web.xml配置文件,创建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="hello" namespace="/" extends="struts-default">
</package> </struts> |
在src下创建com.kingsoft.entity,并创建Student.java
package com.kingsoft.entity;
public class Student {
private int id; private String name; private int age;
public Student() { super(); }
public Student(int id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; }
public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
在src下com.kingsoft.comparator下创建MyComparator.java
package com.kingsoft.comparator;
import java.util.Comparator;
import com.kingsoft.entity.Student;
public class MyComparator implements Comparator<Student>{
public int compare(Student s1, Student s2) { if(s1.getAge()>s2.getAge()){ return 1; }else if(s1.getAge()<s2.getAge()){ return -1; } return 0; } } |
数据标签
Property标签:输出OGNL表达式的值
<% request.setAttribute("name", "<font color=red>张三</font>"); %> <s:property value="#request.name"/><br> <s:property value="#request.name2" default="某人"/><br> <s:property value="#request.name" default="某人" escapeHtml="false"/>
说明:escapeHtml执行HTML,把<font color=red>张三</font>转化为html显示 |
Date标签
<body> <% request.setAttribute("date", new Date());
%> ${date}<br> 当前日期:<s:date name="#request.date" format="yyyy-MM-dd HH:mm:ss"/> </body> |
Set标签
<s:set var="i" value="1"></s:set> <s:property value="#i" /><br>
<s:set var="a" value="'action范围的值'" scope="action"></s:set> <s:property value="#a" /><br>
<s:set var="p" value="'page范围的值'" scope="page"></s:set> <s:property value="#attr.p" /><br>
<s:set var="r" value="'request范围的值'" scope="request"></s:set> <s:property value="#request.r" /><br />
<s:set var="s" value="'session范围的值'" scope="session"></s:set> <s:property value="#session.s" /><br />
<s:set var="app" value="'application范围的值'" scope="application"></s:set> <s:property value="#application.app" /><br /> |
Bean标签
<body> <s:bean name="com.kingsoft.entity.Student" var="student"> 引入Student类的路径,创建实例student <s:param name="name" value="'张三'"></s:param> <s:param name="age" value="10"></s:param> </s:bean> <s:property value="#student.name"/><br> <s:property value="#student.age"/> </body> |
Debug标签,可以查看值栈中的参数
<body> <s:debug></s:debug> </body> |
Include标签
创建head.html
<body> 头部 </body> |
创建include.jsp
<body> <s:include value="head.html"></s:include> </body> |
url标签
<body> <s:url action="hello" namespace="/foreground" id="h"> <s:param name="name" value="'struts2'"/> </s:url> <s:a href="%{h}">超链接1</s:a>
<s:a action="hello" namespace="/foreground"> 比较常用 <s:param name="name" value="'struts2'"/> 超链接2 </s:a> </body> |
控制标签
Ifelse标签
<body> <% int age=11; request.setAttribute("age", age); %> <s:if test="#request.age<20"> 年龄小于20 </s:if> <s:elseif test="#request.age==20"> 年龄等于20 </s:elseif> <s:else> 年龄大于20 </s:else> </body> |
Iterator标签
<body> <% List<Student> students = new ArrayList<Student>(); students.add(new Student(1,"张三",10)); students.add(new Student(2,"李四",13)); students.add(new Student(3,"王五",15)); request.setAttribute("students", students); %> <table> <tr> <th>序号</th> <th>编号</th> <th>姓名</th> <th>年龄</th> </tr> <s:iterator value="#request.students" status="status"> <tr> <td><s:property value="#status.index+1"/></td> <td><s:property value="id"/></td> <td><s:property value="name"/></td> <td><s:property value="age"/></td> </tr> </s:iterator> </table> </body> |
append标签,把所有的内容追加在一起显示
<body> <% List<Student> students1 = new ArrayList<Student>(); List<Student> students2 = new ArrayList<Student>(); students1.add(new Student(1, "张三", 10)); students1.add(new Student(3, "李四", 20)); students2.add(new Student(5, "王五", 30)); students2.add(new Student(7, "赵六", 40)); request.setAttribute("students1", students1); request.setAttribute("students2", students2); %> <s:append var="students"> <s:param value="#request.students1"/> <s:param value="#request.students2"/> </s:append> <table> <tr> <th>序号</th> <th>编号</th> <th>姓名</th> <th>年龄</th> </tr> <s:iterator value="students" status="status"> <tr> <td><s:property value="#status.index+1"/></td> <td><s:property value="id"/></td> <td><s:property value="name"/></td> <td><s:property value="age"/></td> </tr> </s:iterator> </table> </body> |
generator分割标签
<body> <s:generator separator="," val="'张三,李四,王五,赵六'" var="names"/> <s:iterator value="#names"> <s:property/> </s:iterator> </body> 根据,进行分割 |
merge标签,与append标签没有太多的区别
<body> <% List<Student> students1 = new ArrayList<Student>(); List<Student> students2 = new ArrayList<Student>(); students1.add(new Student(1, "张三", 10)); students1.add(new Student(3, "李四", 20)); students2.add(new Student(5, "王五", 30)); students2.add(new Student(7, "赵六", 40)); request.setAttribute("students1", students1); request.setAttribute("students2", students2); %> <s:merge var="students"> <s:param value="#request.students1" /> <s:param value="#request.students2" /> </s:merge> <table> <tr> <th>序号</th> <th>编号</th> <th>姓名</th> <th>年龄</th> </tr> <s:iterator value="students" status="status"> <tr> <td><s:property value="#status.index+1" /></td> <td><s:property value="id" /></td> <td><s:property value="name" /></td> <td><s:property value="age" /></td> </tr> </s:iterator> </table> </body> |
sort标签
<body> <% List<Student> students = new ArrayList<Student>(); students.add(new Student(1, "张三", 20)); students.add(new Student(3, "李四", 10)); students.add(new Student(5, "王五", 40)); students.add(new Student(7, "赵六", 30)); request.setAttribute("students", students); %> <!-- 使用自定义的比较器,按照年龄进行比较 --> <s:bean id="myComparator" name="com.kingsoft.comparator.MyComparator"></s:bean>
<table> <tr> <th>序号</th> <th>编号</th> <th>姓名</th> <th>年龄</th> </tr> <s:sort comparator="#myComparator" source="#request.students" > <s:iterator status="status"> <tr> <td><s:property value="#status.index+1"/></td> <td><s:property value="id"/></td> <td><s:property value="name"/></td> <td><s:property value="age"/></td> </tr> </s:iterator> </s:sort> </table> |
subset标签:截取指定的位置
<body> <% List<Student> students = new ArrayList<Student>(); students.add(new Student(1, "张三", 20)); students.add(new Student(2, "李四", 10)); students.add(new Student(3, "王五", 40)); students.add(new Student(4, "赵六", 30)); request.setAttribute("students", students); %> <table> <tr> <th>序号</th> <th>编号</th> <th>姓名</th> <th>年龄</th> </tr> <!-- count为截取的条数 --> <!-- start为截取的开始位置,下标从0开始 --> <s:subset source="#request.students" count="2" start="2"> <s:iterator status="status"> <tr> <td><s:property value="#status.index+1" /></td> <td><s:property value="id" /></td> <td><s:property value="name" /></td> <td><s:property value="age" /></td> </tr> </s:iterator> </s:subset> </table> </body> |
界面标签
form标签
<body> <s:form action="hello" method="post" namespace="/foreground">
</s:form> </body> |
text标签
<body> 用户名:<s:textfield name="userName"></s:textfield><br> 密码:<s:password name="password"></s:password><br> 备注:<s:textarea name="remark"></s:textarea><br> </body> |
radio标签
<body> 性别: <s:radio list="#{0:'男',1:'女'}" name="sex" value="0"></s:radio> </body> |
checkboxlist标签
<body> 爱好:<s:checkboxlist list="#{0: '游泳', 1:'唱歌 ',2:'跳舞'}" name="hobby" value="1">
</s:checkboxlist> </body> |
select标签
<body> 爱好: <s:select list="#{0: '游泳', 1:'唱歌 ',2:'跳舞'}" name="hobby" value="1" multiple="false"> </s:select> </body> |
Struts2国际化
创建动态Web工程,导入Struts2的相关jar包,修改web.xml配置文件用于拦截请求交给struts处理,创建strtus.xml配置文件
strtus.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> <!-- 引入struts国际化资源 --> <constant name="struts.custom.i18n.resources" value="i18n"/> </struts> |
以后要使用的资源文件必须以i18n_开头
创建默认的资源文件i18n.properties
userName=用户名 password=密码 login=登录 welcomeInfo=欢迎{0} |
创建中文资源文件i18_zh_CN.properties
userName=用户名 password=密码 login=登录 welcomeInfo=欢迎{0} |
创建英文资源文件i18_en_US.properties
userName=UserName password=Password login=Login welcomeInfo=welcome {0} |
此时struts会根据浏览器设置的语言来自动选择使用哪一种资源文件
创建login.jsp
<body> <table> <tr> <td> <s:text name="userName"></s:text> </td> <td> <input type="text" name="userName"> </td> </tr> <tr> <td> <s:text name="password"></s:text> </td> <td> <input type="password" name="password"> </td> </tr> <tr> <td> <input type="submit" value="<s:text name='login'></s:text>"/> </td> </tr> </table> </body> |
创建welcome.jsp
<body> <s:text name="welcomeInfo"> <s:param>Bryant</s:param> 给资源文件传入指定位置的参数 </s:text> </body> |
测试效果
|
Struts2自带的验证框架
创建动态Web工程,导入对应的jar包,修改web.xml文件对所有请求进行拦截并交由struts处理
创建User.java
package com.kingsoft.entity;
public class User {
private String userName; private String name; private int age; private String email; private String homePage;
getter and setter …..
@Override public String toString() { return "User [userName=" + userName + ", name=" + name + ", age=" + age + ", email=" + email + ", homePage=" + homePage + "]"; }
}
|
创建RegisterAction.java
package com.kingsoft.action;
import com.kingsoft.entity.User; import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction extends ActionSupport{
private static final long serialVersionUID = -5983023180767947486L;
private User user;
public User getUser() { return user; }
public void setUser(User user) { this.user = user; }
@Override public String execute() throws Exception { System.out.println("传入用户:"+user); return SUCCESS; }
}
|
在src根目录创建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="manager" extends="struts-default"> <action name="registerAction" class="com.kingsoft.action.RegisterAction"> <result name="input">/register.jsp</result> <result name="success">/success.jsp</result> </action> </package>
</struts> |
创建register.jsp
<%@ 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>Insert title here</title> </head> <body> <s:actionerror/> 用户注册 <s:form action="/registerAction" method="post"> <s:textfield name="user.userName" label="用户名"></s:textfield> <s:textfield name="user.name" label="真实姓名"></s:textfield> <s:textfield name="user.age" label="年龄"></s:textfield> <s:textfield name="user.email" label="邮件"></s:textfield> <s:textfield name="user.homePage" label="主页"></s:textfield> <s:submit value="注册"></s:submit> </s:form> </body> </html> |
创建success.jsp用于显示注册成功
测试如果要使用struts2自带的验证需要在RegisterAction.java同包下创建
RegisterAction-validation.xml验证配置文件,注意这个命名是有要求的xxxxAction-validation.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators> <field name="user.userName"> <field-validator type="requiredstring"> <message>请输入用户名</message> </field-validator> <field-validator type="stringlength"> <param name="minLength">6</param> <param name="maxLength">10</param> <message>用户名必须在${minLength}和${maxLength}之间</message> </field-validator> </field> <field name="user.name"> <field-validator type="requiredstring"> <message>请输入姓名</message> </field-validator> </field> <field name="user.age"> <field-validator type="int"> <param name="min">18</param> <message>年龄必须满18周岁</message> </field-validator> </field> <field name="user.email"> <field-validator type="requiredstring"> <message>请输入邮件</message> </field-validator> <field-validator type="email"> <message>邮件格式不对</message> </field-validator> </field> <field name="user.homePage"> <field-validator type="requiredstring"> <message>请输入主页</message> </field-validator> <field-validator type="url"> <message>主页格式不对</message> </field-validator> </field>
<validator type="expression"> <param name="expression"><![CDATA[!user.name.equals(user.userName)]]></param> <message>用户名和真实姓名不能相同</message> </validator> </validators> |
验证效果如下
|
自定义的验证
在上一个工程的基础上添加自定义的验证,用于验证注册姓名时是否有脏字
创建SensitiveWordValidators.java用于验证敏感词汇
package com.kingsoft.validators;
import com.opensymphony.xwork2.validator.ValidationException; import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;
public class SensitiveWordValidators extends FieldValidatorSupport{
@Override public void validate(Object object) throws ValidationException { String fieldName = this.getFieldName(); String value = this.getFieldValue(fieldName, object).toString(); if(!Check(value)) { this.addFieldError(fieldName, object); } }
private boolean Check(String value) { String[] sensitiveWords = {"操","你妈","逼"}; for(int i=0;i<sensitiveWords.length;i++) { if(value.indexOf(sensitiveWords[i])>-1) { return false; } } return true; } } |
在src根目录下创建validators.xml
|
validators.xml内容如下
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator Config 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-config-1.0.dtd"> <validators> <validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/> <validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/> <validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/> <validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/> <validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/> <validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/> <validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/> <validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/> <validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/> <validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/> <validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/> <validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/> <validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/> <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
<!-- 自定义的验证脏字 --> <validator name="sensitive" class="com.kingsoft.validators.SensitiveWordValidators"/>
</validators> |
创建ValidationAction.java
package com.kingsoft.action;
import com.opensymphony.xwork2.ActionSupport;
public class ValidationAction extends ActionSupport{
private static final long serialVersionUID = 5224941761028296584L;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String execute() throws Exception { System.out.println("姓名:"+name); return SUCCESS; } } |
创建ValidationAction-validation.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators> <field name="name"> <field-validator type="requiredstring"> <message>请输入姓名</message> </field-validator>
<field-validator type="sensitive"> 与validators.xml中配置的名称必须一致 <message>有脏字不能注册</message> </field-validator> </field>
</validators> |
配置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="manager" extends="struts-default"> <action name="registerAction" class="com.kingsoft.action.RegisterAction"> <result name="input">/register.jsp</result> <result name="success">/success.jsp</result> </action> <action name="validationAction" class="com.kingsoft.action.ValidationAction"> <result name="input">/validation.jsp</result> <result name="success">/success.jsp</result> </action> </package>
</struts> |
创建validation.jsp页面
<%@ 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>Insert title here</title> </head> <body> <s:form action="/validationAction" method="post"> <s:textfield name="name" label="姓名"></s:textfield> <s:submit value="提交"></s:submit> </s:form> </body> </html> |
测试效果
|
Struts2文件上传
创建fileupload.jsp
<%@ 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>Insert title here</title> </head> <body> <s:fielderror></s:fielderror> <form action="upload" method="post" enctype="multipart/form-data"> 文件:<input type="file" name="doc"> <input type="submit" value="提交"> </form> </body> </html> |
创建FileUploadAction.java
package com.kingsoft.action;
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction extends ActionSupport{
private static final long serialVersionUID = 4597655201405318590L;
private File doc; //文件
private String docFileName; //文件名
private String docContentType; //文件类型
public File getDoc() { return doc; }
public void setDoc(File doc) { this.doc = doc; }
public String getDocFileName() { return docFileName; }
public void setDocFileName(String docFileName) { this.docFileName = docFileName; }
public String getDocContentType() { return docContentType; }
public void setDocContentType(String docContentType) { this.docContentType = docContentType; }
@Override public String execute() throws Exception { System.out.println("文件名:"+docFileName); System.out.println("文件类型:"+docContentType); String path = "C:/"+docFileName; File saveFile = new File(path); FileUtils.copyFile(doc, saveFile);
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="manager" extends="struts-default"> <action name="upload" class="com.kingsoft.action.FileUploadAction"> <result name="success">success.jsp</result> <!-- 如果上传失败会返回到表单 input表示表单 --> <result name="input">fileupload.jsp</result> <!-- 对上传文件加格式和大小限制 --> <interceptor-ref name="fileUpload"> <param name="allowedTypes"> image/bmp,image/x-png,image/gif,image/jpg,image/jpeg </param> <param name="maximumSize">81101</param> </interceptor-ref>
<!-- 重新加载一次默认的拦截器 --> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package>
</struts> |
测试上传文件时只能上传指定格式的文件,以及指定大小的文件。
上传大文件
因为Struts2默认的上传限制的大小为2M,所以需要修改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>
<!-- 限制上传文件的大小不能超过20M --> <constant name="struts.multipart.maxSize" value="20000000"></constant>
<package name="manager" extends="struts-default"> <action name="upload" class="com.kingsoft.action.FileUploadAction"> <result name="success">success.jsp</result> <!-- 如果上传失败会返回到表单,input表示表单 --> <result name="input">fileupload.jsp</result> </action> </package>
</struts> |
多文件上传
创建filesupload.jsp
<%@ 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>Insert title here</title> </head> <body> <s:fielderror></s:fielderror> <form action="uploads" method="post" enctype="multipart/form-data"> 文件1:<input type="file" name="doc"><br> 文件2:<input type="file" name="doc"><br> 文件3:<input type="file" name="doc"><br> <input type="submit" value="提交"> </form> </body> </html> |
创建FilesUploadAction.java
package com.kingsoft.action;
import java.io.File;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ActionSupport;
public class FilesUploadAction extends ActionSupport{
private static final long serialVersionUID = -5906826302041869705L;
private File[] doc; //文件 private String[] docFileName; //文件名 private String[] docContentType; //文件类型 public File[] getDoc() { return doc; } public void setDoc(File[] doc) { this.doc = doc; } public String[] getDocFileName() { return docFileName; } public void setDocFileName(String[] docFileName) { this.docFileName = docFileName; } public String[] getDocContentType() { return docContentType; } public void setDocContentType(String[] docContentType) { this.docContentType = docContentType; } @Override public String execute() throws Exception { for(int i=0;i<doc.length;i++) { System.out.println("文件名:"+docFileName[i]); System.out.println("文件类型:"+docContentType[i]); String path = "C:/"+docFileName[i]; File saveFile = new File(path); FileUtils.copyFile(doc[i], saveFile); } 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>
<!-- 限制上传文件的大小不能超过20M --> <constant name="struts.multipart.maxSize" value="20000000"></constant>
<package name="manager" extends="struts-default"> <action name="upload" class="com.kingsoft.action.FileUploadAction"> <result name="success">success.jsp</result> <!-- 如果上传失败会返回到表单 input表示表单 --> <result name="input">fileupload.jsp</result> <!-- 对上传文件加格式和大小限制 --> <!-- <interceptor-ref name="fileUpload"> <param name="allowedTypes"> image/bmp,image/x-png,image/gif,image/jpg,image/jpeg </param> <param name="maximumSize">81101</param> </interceptor-ref> -->
<!-- 重新加载一次默认的拦截器 --> <!-- <interceptor-ref name="defaultStack"></interceptor-ref> --> </action> <action name="uploads" class="com.kingsoft.action.FilesUploadAction"> <result name="success">success.jsp</result> <result name="input">filesupload.jsp</result> </action> </package>
</struts> |
文件下载
创建FileDownloadAction.java
package com.kingsoft.action;
import java.io.File; import java.io.FileInputStream; import java.io.InputStream;
import com.opensymphony.xwork2.ActionSupport;
public class FileDownloadAction extends ActionSupport{
private static final long serialVersionUID = -1907938881127694932L;
private String fileName; //文件名
public String getFileName()throws Exception{ fileName = new String(fileName.getBytes(), "ISO8859-1"); //解决下载乱码问题 return fileName; }
public void setFileName(String fileName) { this.fileName = fileName; }
/** * * <b>Description</b><br> * (Struts2规定必须使用此文件名并返回InputStream类型) * <br> * -------------------------------------------------<br> * <b>北派二大爷 2019年12月9日 下午10:54:53</b> */ public InputStream getInputStream()throws Exception{ File file = new File("C:/美女1号.jpg"); //源文件 this.fileName = "本地美女1号.jpg"; //下载后的文件名 return new FileInputStream(file); }
} |
修改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="manager" extends="struts-default"> <action name="download" class="com.kingsoft.action.FileDownloadAction"> <result type="stream"> <param name="contentDisposition"> attachment;filename=${fileName} </param> </result> </action> </package> </struts> |
创建filedownload.jsp
<body> <a href="download">文件下载</a> </body> |
测试,单击链接即可将服务器端的图片下载到本地
Struts2防止重复提交
创建Student.java实体类
package com.kingsoft.entity;
public class Student {
private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; }
} |
创建StudentAction.java
package com.kingsoft.action;
import com.kingsoft.entity.Student; import com.opensymphony.xwork2.ActionSupport;
public class StudentAction extends ActionSupport{
private static final long serialVersionUID = -8469771940895541706L;
private Student student;
public Student getStudent() { return student; }
public void setStudent(Student student) { this.student = student; }
public String add() throws Exception { System.out.println("开始添加学生"+student); Thread.sleep(5000); //模拟网络缓慢的延迟 System.out.println("学生"+student.getName()+"添加完成"); 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="manager" extends="struts-default"> <action name="student" class="com.kingsoft.action.StudentAction" method="add"> <result name="success">/success.jsp</result> <!-- 无视重复提交 --> <interceptor-ref name="tokenSession"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action> </package>
</struts> |
编写student.jsp
<%@ 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>Insert title here</title> </head> <body> <form action="student" method="post"> <s:token></s:token> 姓名:<input type="text" name="student.name"><br> 年龄:<input type="text" name="student.age"><br> <input type="submit" value="提交"> </form> </body> </html> |
测试时重复提交的表单将被忽略不计