Struts2 基本操作
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Struts2 基本操作相关的知识,希望对你有一定的参考价值。
1. 概述
1) struts2应用在JavaEE中的web层中
2) Struts2框架在struts1和webwork基础之上发展的全新框架
3) 解决问题:将传统Web的servlet类思想转换成单个action类的方法,单个serlvet 等于 一个action类的方法
4) web层常见框架:Struts2、SpringMVC
2. 框架搭建/准备
2.1 jar包 [ 历史版本下载 ]
- struts2.3.34-all.zip
- struts2.5.13-all.zip
2.2 创建Action类
- 继承ActionSupport,重写execute,在return时能使用常量值(success,input,error,login,none)
- 不继承ActionSupport,则不能使用常量值,需要存在默认执行方法execute
2.3 配置相关文件
2.4 流程执行图
3. Struts2配置
3.1 web.xml:配置struts2过滤器(该过滤器会自动加载struts2.xml,并同时加载struts2内部xml文件[struts-default.xml、struts-plugin.xml])
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
3.2 struts2.xml:核心文件[struts.xml](与Hibernate.hbm.xml)[名称(struts.xml)与位置(src)是固定的]、引入约束、package标签、action标签
与servlet相比较:
每次访问servlet时,底层都会自动运行service方法去选择性执行doGet/doPost方法
每次访问action时,都会自动执行execute方法
- package标签:类似与代码包,区别不同action。
· name属性:与功能无关系,仅起到识别作用,不能重复命名
· extends属性:属性值固定为struts-default ,表示设置该属性,则在package下配置的class都具备action功能
· namespace属性:该属性值与action标签中的name属性值构成访问路径 例如:http://127.0.0.1:8080/项目名/namespace/action标签的name属性
- action标签:指定配置的Class(Action类)的访问路径 (配置默认Action:<default-action-ref>标签)
· name属性:该属性值与package标签中的namespace属性值构成访问路径,且name不能重复
· class属性:配置Class(action类)的全路径
· method属性:指定action中多个方法执行,不指定则执行默认方法(execute方法)
- result标签:根据action中方法的返回值,自动配置不同的路径(路径可以是页面,也可以是另外action)
· name属性(匹配Action类中的返回值):默认为SUCCESS 例如 <result name="" type="" >/success.jsp</result>
· type属性:设置跳转的方式[转发或重定向],默认值为dispatcher
- 常量配置:
· 方式一(常用):在struts.xml进行配置 <constant name="常量名" value="常量值"></constant>
· 方式二(不常用):在src下创建struts.properties,并在文件内进行常量键值对的填写
· 方式三(不常用):在web.xml进行参数配置
· 最常用的常量:
struts.action.extension = "html":设置action的后缀
struts.i18n.encoding = "UTF-8":自动解决通过post提交的表单数据的乱码问题,仅针对post方式
表单提交数据到action里面,在action可以获取表单提交数据
表单提交数据有中文,有乱码问题,解决:过滤器(post提交直接设置编码[setcharacterEncoding]、get提交做编码转换)
- 分模块开发:独立模块存在独立的xml文件,然后在核心配置文件中引入(跟Hibernate中cfg.xml内引入hbm.xml类似)
· 作用:避免配置文件的错乱,且在独立的xml文件进行修改时不影响核心xml配置文件。
在<struts>标签内使用<include file="xml文件路径"></include> xml文件路径:PackageName1/PackageName2/.../xml文件名
- 结果页面配置
· 全局结果页面配置:相当于资源共享,在package标签内设置,当action返回值与global-results标签的result一致时,返回该值。
作用域仅在package内
<!-- 全局结果页面配置 -->
<global-results>
<result name="SUCCESS">/index2.jsp</result>
</global-results>
· 局部结果页面配置:就是在action里面的result,当同一个package内存在全局与局部的result,且name相同时,result返回的值以action内的result为准
· result标签 type属性:配置以什么方式跳转到result结果去(有dispatcher(转发)、redirect(重定向))
dispatcher(转发)、redirect(重定向):跳转到页面路径时使用
chain(转发到action;一般不用)、redirectAction(重定向到action):跳转到action路径时使用
× 在action中获取表单提交数据:通过struts2封装类获取表单提交数据(底层为request操作)
4. Action类创建
1.Action的三种编写模式
1) 方式一:创建普通类,该类不继承类,不实现接口
2) 方式二:创建类并实现接口Action
3) 方式三:创建类并继承ActionSuppport类(常用)
1 import com.opensymphony.xwork2.Action; 2 import com.opensymphony.xwork2.ActionSupport; 3 4 /* 5 * 创建Action类,并继承ActionSupport类 6 */ 7 @SuppressWarnings("serial") 8 class TestOne extends ActionSupport { 9 10 @Override 11 public String execute() throws Exception { 12 return ""; 13 } 14 } 15 16 //--------------------------------------------- 17 18 /* 19 * 创建Action类实现Action接口 20 */ 21 class TestTwo implements Action { 22 23 @Override 24 public String execute() throws Exception { 25 return ""; 26 } 27 28 } 29 30 /* 31 * 创建Action类,不继承类,不实现接口 32 */ 33 class TestThree { 34 public String execute() { 35 return ""; 36 } 37 }
2.访问Action类中方法:有三种实现方式
1) 方式一:在struts.xml中,action标签内使用method属性,指向Action类的方法名
e.g. <action name="Action名称" class="类全限定路径" method="指向action类中的方法名">
2) 方式二:使用通配符方式实现
e.g. <action name="Action名称_*" class="类全限定路径" method="{1}"> ,{1}为 * 号的位置序号
单独访问时的url:127.0.0.1:8080/WebName(项目名)/namespace(命名空间)/ActionName_Method(Action名_方法名)
将url中处于通配符 * 位置的值 赋值给{1} 并进行下一步操作
3) 方式三:动态访问实现:感叹号方式
5. Struts2 - 提供获取提交的表单数据:通过Struts2封装类进行操作(三种方式)
1) 使用ActionContext类获取:使用getContext获取ActionContext对象
- 调用ActionContext对象的方法进行表单数据的获取
方法声明 | 功能描述 |
void put(String key,object value) | 将key-value键值对放入ActionContext中模拟ServletAPI中的HttpServletRequest |
Object get(String key) | 通过参数key来查找当前ActionContext中的值 |
Map<String,Object> getApplication() | 返回一个Application级别的对象 |
static ActionContext getContext() | 获取当前线程的ActionContext对象 |
Map<String,Object> getPerpameters()[主要使用] | 返回一个包含所有HttpServletRequest参数信息的Map对象 |
Map<String,Object> getSession() | 返回一个Map类型的HttpSession级别的对象 |
void setApplication(Map<String,Object> application) | 设置Application上下文 |
void setSession(Map<String,Object> session) | 设置一个Map类型的Session值 |
import java.util.Arrays; import java.util.Map; import java.util.Set; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Form1Action extends ActionSupport { @Override public String execute() throws Exception { // 使用ActionContext获取上下文对象进行数据获取 ActionContext ac = ActionContext.getContext(); // String str = (String) ac.get("username"); // System.out.println(str);//null Map<String, Object> map = ac.getParameters(); Set<String> set = map.keySet(); for (String string : set) { // 数组形式:因为输入项可能存在复选框,复选框存在多个值 Object[] obj = (Object[]) map.get(string); System.out.println(string + ":" + Arrays.toString(obj)); } map.get("username"); return NONE; } }
2) 使用ServletActionContext类获取:使用ServletActionContext访问ServletAPI
- static HttpServletRequest getRequest():获取Web应用的HttpServletRequest对象
- static HttpServletResponse getResponse():获取Web应用的HttpServletResponse对象
- static ServletContext getServletContext():获取Web应用的HttpServletContext对象
- static PageContext getPageContext():获取Web应用的PageContext对象
import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Form2Action extends ActionSupport { @Override public String execute() throws Exception { // 使用ServletActionContext访问ServletAPI获取内置对象 HttpServletRequest hr = ServletActionContext.getRequest(); String username = hr.getParameter("username"); String password = hr.getParameter("password"); System.out.println("ServletActionContext:" + username + " : " + password); return NONE; } }
3) 使用接口的注入方式获取(不常用):Action类实现接口直接使用对应的ServletAPI
- ServletRequestAware:直接访问Web应用的HttpServletRequest对象
- ServletResponseAware:直接访问Web应用的HttpServletResponse对象
- SessionAware:直接访问Web应用的HttpSession对象
- ServlerContextAware:直接访问Web应用的SerlvetContext对象
import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Form3Action extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; @Override public String execute() throws Exception { // 实现接口直接访问SerlvetAPI String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("ServletActionContext:" + username + " : " + password); return NONE; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }
import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Form4Action extends ActionSupport { @Override public String execute() throws Exception { // 操作域对象 // 1.Request域 HttpServletRequest request = ServletActionContext.getRequest(); request.setAttribute("request", "requestValue"); // 2.Session域 HttpSession session = ServletActionContext.getRequest().getSession(); session.setAttribute("session", "sessionValue"); // 3.ServletContext(Application)域 ServletContext context1 = ServletActionContext.getRequest().getSession().getServletContext(); ServletContext context2 = ServletActionContext.getServletContext(); context1.setAttribute("context1", "context1Value"); context2.setAttribute("context2", "context2Value"); return NONE; } }
6. struts2 - 提供封装提交的表单数据
1) 常规封装
@Override public String execute() throws Exception { HttpServletRequest hsr = ServletActionContext.getRequest(); String username = hsr.getParameter("username"); String password = hsr.getParameter("password"); User user = new User(); user.setUsername(username); user.setPassword(password); System.out.println(user); return NONE; }
2) 属性封装:不需要实现ActionContext等接口就能自动获取表单对应数据,但不会保存到对象中。
- Action类内定义与表单中name的名称相同的成员变量
- 生成变量的set/get方法
× 底层执行类似于BeanUtils的功能,将表单数据赋值给Action类中对应的属性,但依旧有缺陷,获取的数据仅存在于Action类的变量中,依然需要手动new一个对应对象。
import com.opensymphony.xwork2.ActionSupport; /** * 自动获取表单提交的数据,但不会保持到对象中 */ @SuppressWarnings("serial") public class Form5Action extends ActionSupport { // 1.创建变量 private String username; private String password; // set/get方法 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(username + ":" + password); return NONE; } }
3) 模型驱动封装:能直接将表单获取的数据保存到实体类对象中。
× 前提条件:表单输入项name的属性值 与 实体类的变量名称一样
- 实现ModelDriven接口,重写getModel()方法并将对象返回
- 在action里面创建对象
import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; /** * 使用模型驱动封装数据 - ModelDriven */ @SuppressWarnings("serial") // 1.实现接口 public class Form6Action extends ActionSupport implements ModelDriven<User> { // 2.创建对象 // 前提条件:表单输入项name的属性值 与 实体类的变量名称一样才能自动封装到对象内 User user = new User(); @Override public User getModel() { // 3.返回创建的实例对象 return user; } @Override public String execute() throws Exception { System.out.println(user); return NONE; } }
× 使用属性封装和模型封装注意问题
1 . 在一个Action类中,获取表单数据不能同时使用属性封装和模型驱动封装,仅可以使用其中一种。
2 . 如果同时使用两个封装,则优先执行模型驱动封装
4) 表达式封装
- 在Action类内声明实体类 eg:User user;
- 在Action类内生成实体类的set/get方法 eg:setUser()/getUser()
- 在表单输入项的name属性值内写表达式进行传递
import com.opensymphony.xwork2.ActionSupport; /** * 使用表达式封装 */ @SuppressWarnings("serial") public class Form7Action extends ActionSupport { // 1.声明变量 private User user; // 2.set/get方法 public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Override public String execute() throws Exception { System.out.println(user); return NONE; } }
× 表达式封装和模型驱动比较
相同点:功能目的都是将表单数据封装到实例对象中
不同点:
- 模型封装只能封装同一类型的实例对象,局限性大。implements ModelDriven<T>:只能封装数据到T类型对象中
- 表达式封装能封装不同类型的实例对象。
操作数据封装到集合中
封装到list集合
import java.util.List; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Form8Action extends ActionSupport { // 1.声明变量 private List<User> list; // 2.set/get方法 public List<User> getList() { return list; } public void setList(List<User> list) { this.list = list; } public String execute() throws Exception { for (User user : list) { System.out.println(user); } return NONE; } }
username:<input name="list[0].username" type="text" value=""> <br /> password:<input name="list[0].password" type="text" value=""> <br /> username:<input name="list[1].username" type="text" value=""> <br /> password:<input name="list[1].password" type="text" value=""> <br /> <input type="submit" value="发送">
封装到map集合
import java.util.Map; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class Form9Action extends ActionSupport { // 1.声明变量 private Map<String, User> maps; // 2.set/get方法 public Map<String, User> getMap() { return maps; } public void setMap(Map<String, User> maps) { this.maps = maps; } public String execute() throws Exception { System.out.println(maps); System.out.println(maps.size()); maps.entrySet(); for (Map.Entry<String, User> user : maps.entrySet()) { System.out.println(user); } return NONE; } }
username:<input name="map[‘a‘].username" type="text" value=""> <br /> password:<input name="map[‘a‘].password" type="text" value=""> <br /> username:<input name="map[‘b‘].username" type="text" value=""> <br /> password:<input name="map[‘b‘].password" type="text" value=""> <br /> <input type="submit" value="发送">
以上是关于Struts2 基本操作的主要内容,如果未能解决你的问题,请参考以下文章
VSCode自定义代码片段15——git命令操作一个完整流程