Struts框架图解

Struts核心
- 操作(Actions)
- 拦截器(Interceptors)
- 值栈(Value Stack)/OGNL
- 结果(Result)/结果类型
- 视图技术

导入依赖
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.5.26</version> </dependency>
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-json-plugin</artifactId> <version>2.5.20</version> </dependency>
|
Maven resources下新建配置struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <constant name="struts.devMode" value="true"/> <package name="helloworld" extends="struts-default" namespace="/"> </package> </struts>
|

配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <display-name>Archetype Created Web Application</display-name> <filter> <filter-name>action2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>action2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
|
主要添加内容:
<filter> <filter-name>action2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter>
<filter-mapping> <filter-name>action2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|

创建Action类 默认方法名execute()(类似Servlet)
package com.xianxian;
public class Action {
public String execute(){ System.out.println("第一个action:"+this); return "success"; } }
|
新建视图层jsp
<%-- Created by IntelliJ IDEA. User: 羡羡 Date: 2021/7/19 Time: 9:34 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>视图层</h1> </body> </html>
|
配置struts.xml 跳转jsp(result)
<action name="hello" class="com.xianxian.Action" method="execute"> <result name="success">/HelloStruts.jsp</result> </action>
|

修改Action方法名

修改Action方法名配置
修改配置的method class=action类的路径(不是绝对路径 copy References)

Action得到表单数据
定义表单name对应变量 设置变量对应的set方法

Action类返回值
默认success 通过返回的结果进行对应的网页跳转

按返回值执行跳转
(result里面写对应的跳转地址) name=返回的结果

namespace
命名空间 ,相等于servlet的链接注解 进行模块跳转(如下:跳login 变成 /admin/login)
<package name="helloworld" extends="struts-default" namespace="/admin"> <action name="login" class="com.action.Action"> <result name="success">/logsug.jsp</result> <result name="error">/logeror.jsp</result> </action> </package>
|
Action继承ActionSupport
(返回值则是内置 大写)

重新execute()方法
@Override public String execute() throws Exception { System.out.println("其他的地址!"); return ERROR; }
|
全局跳转
两个Action有跳转的地方相同 如下图
<global-results> <result name="error">/NoLogin.jsp</result> </global-results>
|

如上相同地址则可使用global 示例如下

action不做控制器 做跳转
<action name="tjiao" > <result>/WEB-INF/hide.jsp</result> </action>
|
Action通配符
一个Action执行多件事情
添加运行通配符
<global-allowed-methods>regex:.*</global-allowed-methods>
|
package com.xianxian; import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport { public String add(){ System.out.println("用户增加"); return SUCCESS; } public String dele(){ System.out.println("用户删除"); return SUCCESS; } public String update(){ System.out.println("用户修改"); return SUCCESS; } public String search(){ System.out.println("用户查询"); return SUCCESS; } }
|
通配符配置
<action name="user*" class="com.xianxian.UserAction" method="{1}"> <result>/WEB-INF/hide.jsp</result> </action>
|
多个通配符配置
与单个通配符类似(多个Action类)
<action name="*_*" class="com.xianxian.{1}Action" method="{2}"> <result>/WEB-INF/hide.jsp</result> </action>
|
默认容器内转发
<action name="tjiao" > <result >/WEB-INF/hide.jsp</result> </action>
|
浏览器重定向
(type=“redirect”)(red ruai ke che)
<action name="tjiao" > <result type="redirect">/WEB-INF/hide.jsp</result> </action>
|
一个Action跳转到其他类Action
name:返回的值 hello跳转得Action name
UserAction跳 Action 图例
<result name="gohello" type="chain">hello</result>
|


全局异常处理
<global-exception-mappings> <exception-mapping exception="java.lang.Exception" result="err" /> </global-exception-mappings>
<global-results> <result name="error">/NoLogin.jsp</result> <result name="err">/error.jsp</result> </global-results>
|

Struts四大作用域
表单获取
可以用对象接收 需要有get set方法
定义表单实体类
package com.entity;
public class User { public String name; public String pass; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", pass='" + pass + '\'' + '}'; } }
|
表单 name 实体类.属性 (User us=new User() 在Action类new)
<html> <body> <h2>Hello World!</h2> <form action="login" method="post"> <input type="text" name="us.name"/> <input type="text" name="us.pass"/> <input type="submit" value="提交"/> </form> </body> </html>
|
Action类(需要new实体类 get set方法)
User us=new User(); public User getUs() { return us; } public void setUs(User us) { this.us = us; }
|
获取原生四大作用域
HttpServletRequest request=ServletActionContext.getRequest();
HttpSession session=request.getSession();
ServletContext se=ServletActionContext.getServletContext();
HttpServletResponse response=ServletActionContext.getResponse();
|
Struts框架获取四大作用域
方法1、
ActionContext ac=ActionContext.getContext(); ac.put("na","struts -- request"); ac.getSession().put("sa","struts -- session"); ac.getApplication().put("se","struts -- application");
|
方法2、
实现三个接口
implements RequestAware, SessionAware, ApplicationAware
|
新建三个map
Map<String,Object> request; Map<String,Object> session; Map<String,Object> app;
|
重写方法 (this.新建map的变量名)
@Override public void setRequest(Map<String, Object> map) { this.request = map; } @Override public void setApplication(Map<String, Object> map) { this.app=map; } @Override public void setSession(Map<String, Object> map) { this.session=map; }
|
使用:
public String execute(){ request.put("na","struts -- request"); session.put("sa","struts -- session"); app.put("se","struts -- application"); return "success"; }
|

Action返回JSON
导入依赖
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-json-plugin</artifactId> <version>2.5.20</version> </dependency>
|
配置 json struts.xml (package 继承 json-default )
<action name="ajaxjson" class="com.xianxian.ReturnJsonAction"> <result type="json"> <param name="excludeNullProperties">true</param> <param name="root">result</param> </result> </action>
|

定义通用返回类
package com.entity;
public class JsonResult { int code; Object data; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public JsonResult() { } public JsonResult(int code, Object data) { this.code = code; this.data = data; } }
|
返回jsonAction
package com.xianxian; import com.entity.JsonResult; import com.opensymphony.xwork2.ActionSupport; import java.util.ArrayList; import java.util.List;
public class ReturnJsonAction extends ActionSupport {
JsonResult result; public JsonResult getResult() { return result; } public void setResult(JsonResult result) { this.result = result; } @Override public String execute() throws Exception { List lis=new ArrayList(); lis.add("C++"); lis.add("Java"); lis.add("C#"); lis.add("Python"); result =new JsonResult(200,lis); return SUCCESS; } }
|
返回成功 result=new JsonResult(200,lis);

返回失败 result=new JsonResult(200,“返回失败!”);

配置struts.xml 添加过滤空配置


Action文件上传
界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="myFile"/> <input type="submit" value="提交"/> </form> </body> </html>
|
struts.xml配置
<action name="upload" class="com.xianxian.FileAction"> <result name="success">/filsu.jsp</result> </action>
|
文件上传Action
package com.xianxian;
import com.opensymphony.xwork2.ActionSupport; import org.apache.commons.io.FileUtils; import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.io.File;
public class FileAction extends ActionSupport { private File myFile; private String myFileContentType; private String myFileFileName; private String destPath;
public File getMyFile() { return myFile; }
public void setMyFile(File myFile) { this.myFile = myFile; }
public String getMyFileContentType() { return myFileContentType; }
public void setMyFileContentType(String myFileContentType) { this.myFileContentType = myFileContentType; }
public String getMyFileFileName() { return myFileFileName; }
public void setMyFileFileName(String myFileFileName) { this.myFileFileName = myFileFileName; }
public String getDestPath() { return destPath; }
public void setDestPath(String destPath) { this.destPath = destPath; }
@Override public String execute() throws Exception { destPath= ServletActionContext.getServletContext().getRealPath("/images"); System.out.println("Src File name: " + myFile); System.out.println("Dst File name: " + myFileFileName); File destFile = new File(destPath, myFileFileName); FileUtils.copyFile(myFile, destFile);
return SUCCESS; } }
|
限制文件的大小
<constant name="struts.multipart.maxSize" value="1000000"></constant>
|

Error:(83, 61) java: 无法访问javax.servlet.ServletContext 找不到javax.servle

<dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> </dependency>
|
Action拦截器
拦截器(AOP编程)
- 在调用action之前提供预处理逻辑。
- 在调用action后提供后处理逻辑。
- 捕获异常,以便可以执行备用处理。
Struts2框架拦截器
Struts 2框架提供了一个良好的开箱即用的拦截器列表,这些拦截器预先配置好并可以使用。 下面列出了几个重要的拦截器:
| 序号 | 拦截器和说明 |
|---|
| 1 | alias允许参数在请求之间使用不同的别名。 |
| 2 | checkbox通过为未检查的复选框添加参数值false,以辅助管理复选框。 |
| 3 | conversionError将字符串转换为参数类型的错误信息放置到action的错误字段中。 |
| 4 | createSession自动创建HTTP会话(如果尚不存在)。 |
| 5 | debugging为开发人员提供一些不同的调试屏幕。 |
| 6 | execAndWait当action在后台执行时,将用户发送到中间的等待页面。 |
| 7 | exception映射从action到结果抛出的异常,允许通过重定向自动处理异常。 |
| 8 | fileUpload便于文件上传。 |
| 9 | i18n 在用户会话期间跟踪选定的区域。 |
| 10 | logger通过输出正在执行的action的名称提供简单的日志记录。 |
| 11 | params设置action上的请求参数。 |
| 12 | prepare这通常用于执行预处理工作,例如设置数据库连接。 |
| 13 | profile允许记录action的简单分析信息。 |
| 14 | scope在会话或应用程序范围内存储和检索action的状态。 |
| 15 | ServletConfig提供可访问各种基于servlet信息的action。 |
| 16 | timer以action执行时间的形式提供简单的分析信息。 |
| 17 | token检查action的有效性,以防止重复提交表单。 |
| 18 | validation提供action的验证支持。 |
默认拦截器
Params(没有设置Action则得不到表单的数据)
<interceptor-ref name="params"></interceptor-ref>
|
timer (显示表单提交需要多久 输出表单的提交时间 需要配置log4j.xml)
<interceptor-ref name="timer"></interceptor-ref>
|
log4j.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> </Console> </Appenders> <Loggers> <Logger name="com.opensymphony.xwork2" level="info"/> <Logger name="org.apache.struts2" level="info"/> <Logger name="org.demo.rest" level="debug"/> <Root level="warn"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration>
|
自定义拦截器
定义拦截器类(继承AbstractInterceptor 重新intercept方法)
package com.Interceptor;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import java.util.Map;
public class LoginInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation actionInvocation) throws Exception { ActionContext ac=ActionContext.getContext(); Map session=ac.getSession(); Object obj=session.get("logname");
if(obj==null){ return "nologin"; }else{ String ok=actionInvocation.invoke(); return ok; } } }
|
invoke()
代码在invoke之前则是拦截之前的操作 在invoke之后 则是拦截Action后的操作
配置拦截器
注册拦截器 (name 拦截的name class为拦截器类)
<interceptors> <interceptor name="logininterceptor" class="com.Interceptor.LoginInterceptor"></interceptor> <interceptor name="Testlj" class="com.Interceptor.TestInterceptor"></interceptor> <interceptor name="authlj" class="com.Interceptor.AuthInterceptor"></interceptor> </interceptors>
|
使用拦截器 (name需要与注册拦截器的name相同)
<interceptor-ref name="logininterceptor"></interceptor-ref>
|
自定义拦截器时需要使用默认拦截器栈(否则会出现参数无法得到)
<interceptor-ref name="defaultStack"></interceptor-ref>
|
拦截器栈
当多个拦截器使用到同一地方时可以使用拦截器栈
拦截器栈配置
interceptor-stack:拦截器栈 name提供给使用拦截器的name
interceptor-ref: name自定义
<interceptors> <interceptor-stack name="zalj"> <interceptor-ref name="logininterceptor"></interceptor-ref> <interceptor-ref name="authlj"></interceptor-ref> </interceptor-stack> </interceptors>
|
使用拦截器栈 (name为拦截器栈的name值)
<interceptor-ref name="zalj"></interceptor-ref>
|
Token使用
token 防止表单进行重复提交
界面顶部添加标签
<%@ taglib prefix="s" uri="/struts-tags" %>
|
界面 (form表单内必须加上<s:token /> )
<%@ taglib prefix="s" uri="/struts-tags" %> <%-- Created by IntelliJ IDEA. User: 羡羡 Date: 2021/7/25 Time: 14:04 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form method="post" action="fromsub"> <input type="text" name="name"/> <input type="password" name="pass"> <s:token /> <button type="submit">提交</button> </form> </body> </html>
|
Action(FormSubAction 接收表单提交的信息)
package com.xianxian;
import com.opensymphony.xwork2.ActionSupport;
public class FormSubAction extends ActionSupport {
String name; String pass;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPass() { return pass; }
public void setPass(String pass) { this.pass = pass; }
@Override public String execute() throws Exception { System.out.println("name:"+name+" "+"pass:"+pass); return SUCCESS; } }
|
struts.xml 配置
<action name="fromsub" class="com.xianxian.FormSubAction"> //token拦截器 <interceptor-ref name="token"></interceptor-ref> //默认拦截器 <interceptor-ref name="defaultStack"></interceptor-ref> //提交后跳转位置 <result name="success">/index.jsp</result> //重复提交后跳转的位置 <result name="invalid.token">/resub.jsp</result> </action>
|
拦截器案例
首页 登入页 超链接 (未登入是跳到未登入界面 ,登入后才可以访问超链接)
界面
首页 (a 访问的链接是AdminAction里面的add方法)
<%-- Created by IntelliJ IDEA. User: 羡羡 Date: 2021/7/24 Time: 10:39 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>首页</h1> <a href="adminadd">访问管理员add方法</a> </body> </html>
|
登入
<%-- Created by IntelliJ IDEA. User: 羡羡 Date: 2021/7/24 Time: 10:39 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登入页</h1> <form action="logac" method="post"> <input type="text" name="name"/> <input type="text" name="pass"/> <input type="submit" value="login"/> </form> </body> </html>
|
未登入跳转界面
<%-- Created by IntelliJ IDEA. User: 羡羡 Date: 2021/7/19 Time: 10:05 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登入失败 请确认账号密码!</h1> </body> </html>
|
定义表单Action (得到表单的数据)
package com.xianxian;
import com.entity.User; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.ServletActionContext; import org.apache.struts2.interceptor.ApplicationAware; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware;
import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.Map;
public class LogAction extends ActionSupport{
String name; String pass;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPass() { return pass; }
public void setPass(String pass) { this.pass = pass; }
@Override public String execute() throws Exception { System.out.println("正在登录!"+name+" "+pass); ActionContext ac=ActionContext.getContext(); Map session=ac.getSession(); session.put("logname",name); return SUCCESS; } }
|
AdminAction 增删改查方法(首页a标签的链接是AdminAction的add方法)
package com.xianxian;
import com.opensymphony.xwork2.ActionSupport;
public class AdminAction extends ActionSupport { public String add(){ System.out.println("管理员增加"); return SUCCESS; }
public String dele(){ System.out.println("管理员删除"); return SUCCESS; }
public String update(){ System.out.println("管理员修改"); return SUCCESS; }
public String search(){ System.out.println("管理员查询"); return SUCCESS; } }
|
自定义登入拦截器LoginInterceptor
package com.Interceptor;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import java.util.Map;
public class LoginInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation actionInvocation) throws Exception { ActionContext ac=ActionContext.getContext(); Map session=ac.getSession(); Object obj=session.get("logname"); if(obj==null){ return "nologin"; }else{ String ok=actionInvocation.invoke(); return ok; } } }
|
配置struts.xml(配置拦截器)
需要配运行通配符(20)
自定义拦截器配置 需要添加默认拦截器(name=“defaultStack”)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <constant name="struts.devMode" value="true"/> <package name="helloworld" extends="struts-default" namespace="/">
<interceptors> <interceptor name="loglj" class="com.Interceptor.LoginInterceptor"></interceptor> </interceptors>
<global-allowed-methods>regex:.*</global-allowed-methods>
<action name="logac" class="com.xianxian.LogAction"> <result>/index.jsp</result> </action>
<action name="admin*" class="com.xianxian.AdminAction" method="{1}"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="loglj"></interceptor-ref> <result>/index.jsp</result> <result name="nologin">/NoLogin.jsp</result> </action>
</package> </struts>
|