Struts2-初学小结

前言:

我们学J2EE一定要学习框架。那框架设计从web层开始,首先要读取浏览器的请求,然后根据请求去处理业务逻辑,查询数据库,最终将数据渲染到前台展示页面。
       流程知道了我们再来认识Struts2,一款优秀的web层框架。前身是webwork2,而并非是Struts1的升级版,是webwork2结合了Struts1的特性后变成了Struts2(基于过滤器)。

正文开始

上图是Struts的运行流程,来看其具体实现
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0"><display-name>struts2</display-name><filter><filter-name>stras</filter-name><filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class></filter><filter-mapping><filter-name>stras</filter-name><url-pattern>/</url-pattern>*</filter-mapping><!--浏览器发送请求后先到这里根据filter-mapping的url匹配过滤器然后到filter中去实例化filter-class中声明的类然后就会去找struts.xml以调用其中声明的action
</web-app>-->
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><!--自定义字符集,默认UTF-8(常用)  i18n做国际化,其实是将需要改变的文字定义为对应的properties,切换语言就是切换propertiesi18n是国际化Internationalization的从首字母到为字母共18位,因此叫i18n--><constant name="struts.i18n.encoding" value="UTF-8"></constant><!--可以有3中方式去写:1.写在struts.xml  2.写在单独的Properties中   3.写在web.xml  --><package name="struts" extends="struts-default" namespace="/"><action name="hello" class="com.demo.action.HelloAction" method="execute"><result name="ok">/index.jsp</result></action><!--通配符实现(推荐使用)  Struts2.5之后     一个通配符实现很多对user的操作  --><action name="user_*" class="com.demo.user.UserAction" method="{1}"><result name="ok">/index.jsp</result><allowed-methods>add,update</allowed-methods></action><!--动态配置实现(太灵活,不建议使用)  --><action name="regisiter" class="com.demo.user.UserAction"><result name="ok">/index.jsp</result></action><!--使用之前要在<struts>中开启动态访问    :   eg:<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>  --><!--在form中的action中指明:eg:<form action="regisiter!esecute.action" method="post">  --></package><!--协同开发,每个人写的独立的xml include即可,互不相干  --><include file="com/demo/pay/struts-pay.xml"></include><!--package中可以放多个action,name:package的唯一标识 extends:继承另一个struts内置的配置文件namespace:命名空间:与action的name构成一个访问路径,此时路径为:端口号/项目名/hello(.action)--><!--action:就是用于描述Action类的name:action的唯一标识,也是action的访问路径class:将路径指向目标类method:将路径指向目标类的某一方法,默认是execute()result:Action类中方法的返回值,根据返回值确认跳转页面,默认是以转发方式跳转。result-type:设置跳转方式-->
</struts>
Action:
public class HelloAction extends ActionSupport {/* *    实现Action有三种方式:*    1.exetends ActionSupport (最常用)*    2.implements Action*    3.啥都不要,只要在struts.xml声明该类即可*/private static final long serialVersionUID = -3014500372004529338L;public String execute() {return "ok";}
}
Action 访问ServletAPI以实现操作request,response,session,cookie等

Struts访问ServletAPI需要依赖servlet-api.jar

获取域对象有三种方式:

  1. 让Action类实现Aware感知接口
public class ApiAction extends ActionSupport implements ServletRequestAware,ServletResponseAware,SessionAware  {protected HttpServletRequest request;protected HttpServletResponse response;protected Map<String, Object> session;private static final long serialVersionUID = 823593947937711197L;public String execute() {String name = request.getParameter("name");session.put("names", name);try {PrintWriter out = response.getWriter();out.print(name);} catch (IOException e) {e.printStackTrace();}Object names = session.get("names");System.out.println("names - >"+names);return Action.NONE;}public void setServletRequest(HttpServletRequest request) {this.request=request;}public void setServletResponse(HttpServletResponse response) {this.response=response;}public void setSession(Map<String, Object> session) {this.session=session;}
}

这个Action就可以被别的Action继承,充当BaseAction;那么它return null,对应的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><package name="api" extends="struts-default" namespace="/"><action name="api" class="com.qwx.api.ApiAction" /></package>
</struts>

但这种方式存在的问题是:与ServletAPI严重耦合


  1. 通过ServletActionContext工具类(常用)

       通过ServletActionContext类中的静态方法,得到Servlet相关api:getRequest(),getResponse(),getServletContext();

public class ApiAction2 extends ActionSupport {private static final long serialVersionUID = 886566026266620426L;public String execute() {HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();HttpSession session = request.getSession();String name = request.getParameter("name");System.out.println(name);session.setAttribute("names", name);try {PrintWriter out = response.getWriter();out.print("name"+name);} catch (IOException e) {e.printStackTrace();}Object names = session.getAttribute("names");System.out.println(names);return Action.NONE;}
}

该方式操作简单,且可以直接使用,但仍与ServeletAPI耦合。


  1. 通过ActionContext工具类(不常用)
           ActionContext表示的是Action的上下文对象,封装每一次请求的相关信息。
public class ApiAction3 extends ActionSupport {private static final long serialVersionUID = 9156791014500216035L;public String execute() {ActionContext context = ActionContext.getContext();//强制获取session(依据源码)Map<String, Object> session=(Map<String, Object>)context.get(ActionContext.SESSION);HttpServletRequest request=(HttpServletRequest)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");HttpServletResponse response=(HttpServletResponse)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");String name = request.getParameter("name");session.put("names", name);try {response.getWriter().println(name);System.out.println(name);} catch (IOException e) {e.printStackTrace();}Object names = session.get("names");System.out.println(names);return Action.NONE;}//仿照源码进行封装protected HttpServletRequest getRequestCustomer(ActionContext context) {HttpServletRequest request=(HttpServletRequest)context.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");return request;}
}

是第二种的父类,不如第二种封装的方便,不能直接使用。


Action 接收参数的三种方式:
  1. 在action中直接声明属性,并提供setter方法
public class ParaAction extends ActionSupport {/**   *   将属性直接写在Action中,并提供set方法,就能直接获取参数值。*/private String sname;private Integer sid;public void setSid(Integer sid) {this.sid = sid;}public void setSname(String sname) {this.sname = sname;}private static final long serialVersionUID = -5765537308872529477L;public String execute() {System.out.println("sname ->"+sname);System.out.println("sid ->"+sid);return Action.NONE;}
}

局限性:如果多个参数,这样就不合适了


  1. 封装成一个单独的JavaBean,Action中提供bean的对象,传参指定对象名称
public class ParaAction2 extends ActionSupport {private static final long serialVersionUID = -4036312971628051141L;/**   * 通过javaBean传参,这里的对象属性一定要提供get/set方法* 通过url访问时一定要指明对象属性名。(这样就可以接收多个对象的属性)*/private User user;public void setUser(User user) {this.user = user;}public User getUser() {return user;}public String execute() {System.out.println(user);return Action.NONE;}
}

推荐使用该方法


  1. 使用ModelDriver接口,重写其抽象方法
public class ParaAction3 extends ActionSupport implements ModelDriven<User> {private static final long serialVersionUID = -3457739698457049296L;private User u=new User();public String execute() {System.out.println(u);return Action.NONE;}//重写ModelDriven方法,无需get/set方法.public User getModel() {return u;}
}

局限性:只能接受一个实体的属性,不常用到
       三种方法可结合使用.


Action 获取数组集合等类型参数:
  1. 接收数组:(创建数组,提供get/set即可)
public class ParaAction4 extends ActionSupport {private static final long serialVersionUID = 8636699282313437455L;//请求路径:http://localhost:8080/struts2/pa4.action?hobby=1&hobby=2&hobby=3//同名自动封装为数组//数组情况:爱好:1.篮球  2.足球   3.排球private String[]  hobby;//get/set不能少public String[] getHobby() {return hobby;}public void setHobby(String[] hobby) {this.hobby = hobby;}public String execute() {System.out.println(Arrays.asList(hobby));return Action.NONE;}}
  1. 接收集合:(简单集合与数组相似,复杂类型使用下标)
public class ParaAction5 extends ActionSupport { private static final long serialVersionUID = -7855066679657306785L;//请求路径:http://localhost:8080/struts2/pa5.action?list=1&list=2&list=3//简单集合情况:(与数组相似)List<String> list;public List<String> getList() {return list;}public void setList(List<String> list) {this.list = list;}/**   表单请求格式*   <form action="pa5.action" method="post"><input type="text" name="users[0].sname" value="张三" ><input type="text" name="users[0].sid" value="1" ><input type="text" name="users[0].age" value="13" ><input type="text" name="users[1].sname" value="李四" ><input type="text" name="users[1].sid" value="2" ><input type="text" name="users[1].age" value="12" ><input type="submit" value="提交" ></form>*///复杂集合情况:List<User> users;public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}public String execute() {System.out.println(users);//结果:[User [sname=张三, sid=1, age=13], User [sname=李四, sid=2, age=12]]return Action.NONE;}}
  1. 接收Map参数:
public class ParaAction6 extends ActionSupport {private static final long serialVersionUID = -8037899230280395513L;/**   表单请求格式*   <form action="pa6.action" method="post"><input type="text" name="map['a'].sname" value="张三" ><input type="text" name="map['a'].sid" value="1" ><input type="text" name="map['a'].age" value="13" ><input type="text" name="map['b'].sname" value="李四" ><input type="text" name="map['b'].sid" value="2" ><input type="text" name="map['b'].age" value="12" ><input type="submit" value="提交" ></form>*///map集合情况:Map<String,User> map;public Map<String, User> getMap() {return map;}public void setMap(Map<String, User> map) {this.map = map;}public String execute() {System.out.println(map);return Action.NONE;}}

#### Struts2拦截器:

  1. 拦截器Interceptor(作用于Action):
           Struts拦截器是在访问某个Action或在某个Action的方法之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种体现.(AOP简单理解:在不修改源码的基础上,对已有的方法进行动态增强.)
  2. WebWork中文文档解释:
           拦截器是动态拦截Action调用的对象,它提供了一种可以使开发者可以定义在一个action的执行前后执行代码的机制.也可以在一个action执行前阻止其执行,同时也提供了一种可提取action中可重用部分的方式.
  3. 拦截器栈(Interceptor Stack)
           就是将拦截器按一定的顺序连成一条链.在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用,栈结构为先进后出.
Struts2的拦截器和过滤器的区别

拦截器是基于Java的反射机制,而过滤器时基于函数回调.
       过滤器需要在web.xml中配置,是servlet规范中的一部分,任何web工程都能使用.
       拦截器是Struts2框架自己的,只有使用了Struts2的工程才可使用。
       过滤器在url-partten中配置/*后,可以对所有要访问的资源进行拦截,进而可以阻止所有资源的访问。
       拦截器是在只有进入了Struts2核心内部后才会起作用,如果访问的是静态资源,都不会进行拦截,同时拦截器是AOP编程思想的具体体现形式。
       处理的深度不同:Filter只在Servlelt前后起作用,而拦截器深入到Action方法前后,异常抛出前后,因此拦截器更加适合使用。

Struts2内置框架:

Struts2内置许多拦截器,提供了许多Struts2的核心功能和可选的高级特性。

这些内置的拦截器都在struts2-core-2.5.x.jar下的struts.default.xml中配置的。内置拦截器虽然都被定义了,但并不是所有的拦截器都能起作用,只有被添加到默认拦截器栈里的拦截器才起作用。
       常见拦截器:

  1. params拦截器
    此拦截器将请求的参数设置到相应的Action的属性中去,并自动进行类型转换。
  2. ServletConfig拦截器:
    感知接口封装
  3. fileUpload拦截器:
    用于文件上传,及封装校验
  4. token:
    使用token来作为核对当前请求的有效表示,解决重复提交问题
  5. validation:
    使用action-validation.xml文件中定义的内容校验提交的数据
  6. exception:
    程序抛出异常时,拦截器对异常进行处理,建议放在第一位,让它能捕获所有异常
自定义一个登录拦截器

步骤:

  1. 定义拦截器类
    implements Interceptor接口
    extends AbstractInterceptor类
    但实现了Interceptor接口,destory()和init()都用不到,因此推荐使用继承AbstractInterceptor类。
  2. 重写public String intercept(ActionInvocation invocation) throws Exception 方法
  3. 在struts.xml中注册该拦截器,
    拦截器只有注册后才可使用,注册时要描述该拦截器与Action的关系
    在需要拦截的Action所在的package中通过<interceptor元素定义拦截器
    在具体的<action标签中通过<interceptor-ref元素来使用拦截器
  4. 如果给Action指定了拦截器,则系统提供的拦截器栈将失去作用。
    为继续使用默认拦截器,需要手动声明,如标签:<interceptor-ref name=“defaultStack”》<interceptor-ref》
    如果定义的Action中没有用到Struts2中的功能则不需要考虑该问题。
  5. 该拦截器会对该action中的所有方法进行拦截,这样会产生一些不必要的拦截过程而影响系统性能,因此,将无需拦截的方法进行不拦截的配置。
    在<interceptor-ref》标签下面加入:<param name=“excludeMethods”》login</param》,若有多个方法用逗号隔开。
<?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>
<package name="inter" extends="struts-default" namespace="/"><interceptors><interceptor name="liginInterc" class="com.qwx.interceptor.LoginInterceptor"></interceptor></interceptors><!--全局拦截,只要这个package的action的任何一个方法返回LOGIN,都可被拦截到login.jsp  --><global-results><result name="login">/login.jsp</result></global-results><action name="inter_*" class="com.qwx.interceptor.LoginAction" method="{1}"><result name="success" type="redirectAction">index</result><result name="login">/login.jsp</result><allowed-methods>login</allowed-methods></action><action name="index" class="com.qwx.interceptor.IndexAction" method="index"><interceptor-ref name="liginInterc"></interceptor-ref><result name="index">/index2.jsp</result><!-- <result name="login">/login.jsp</result> --><!--配置了全局拦截,就不要了  --></action></package>
</struts>
/*** 登录拦截器*/
public class LoginInterceptor extends AbstractInterceptor {public String intercept(ActionInvocation invocation) throws Exception {Map<String, Object> session = invocation.getInvocationContext().getSession();Object object = session.get("name");if(object!=null) {//放行,类似于过滤器的chain.doFilter()return invocation.invoke();}return Action.LOGIN;}}
自定义拦截器的优化

当一个package中有100个action,,其中98个都要用到我们定义的拦截器,那么我们岂不是要在每个action中都写上<interceptor-ref》?这样就太low了,以下方法可解决:

<?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><package name="inter" extends="struts-default" namespace="/"><interceptors><interceptor name="liginInterc" class="com.qwx.interceptor.LoginInterceptor"></interceptor><!--将自己定义的拦截器扩展到默认的拦截器栈  --><interceptor-stack name="myStrack"><!--Struts2默认的拦截器栈,位于struts2-core-2.5.x.jar下的struts.default.xml  --><interceptor-ref name="defaultStack"></interceptor-ref><interceptor-ref name="liginInterc"></interceptor-ref></interceptor-stack></interceptors><!--将默认拦截器栈指向我们自己扩展的栈  --><!--但这样对所有的action都生效,因此要为不需要被拦截的action去除拦截  --><default-interceptor-ref name="myStrack"></default-interceptor-ref><!--全局拦截,只要这个package的action的任何一个方法返回LOGIN,都可被拦截到login.jsp  --><global-results><result name="login">/login.jsp</result></global-results><action name="inter_*" class="com.qwx.interceptor.LoginAction" method="{1}"><interceptor-ref name="defaultStack"></interceptor-ref><!--只用系统默认栈而不用自己扩展的用不到且影响性能的拦截器  --><result name="success" type="redirectAction">index</result><result name="login">/login.jsp</result><allowed-methods>login</allowed-methods></action><action name="index" class="com.qwx.interceptor.IndexAction" method="index"><!--添加到了拦截器栈。不必每次声明  --><result name="index">/index2.jsp</result></action><action name="user" class="com.qwx.interceptor.UserAction" method="userInfo"><result name="userInfo">/user</result></action></package>
</struts>
方法级别拦截器

MethodFilterInterceptor,更加灵活的方法基本拦截器,可指定需拦截的和无需拦截的方法。
       在<interceptor 标签内:<param name=“excludeMethods”》方法名</param》,多个方法逗号隔开。
       方法级别和普通的区别:

  1. AbstractInterceptor是Interceptor的子类。

  2. MethodFilterInterceptor是AbstractInterceptor的子类,要想拦截器实现对方法的过滤,就要继承MethodFilterInterceptor类,默认情况下,拦截器会拦截Action中的所有方法,不包括getter/setter.
    这时就可以使用方法过滤器来拦截指定的方法,这是种更加细化的拦截器配置方式,细化到可拦截具体的方法。

    1. 使用includeMethods指明拦截器所有要拦截的方法
    2. 使用excludeMethods指明拦截器不再拦截的方法

    这里includeMethods和excludeMethods是MethodFilterInterceptor中定义的成员变量。
    且只要includeMethods进来的方法就一定会被拦截,而不管是否已经将其excludeMethods在外了,也就是说includeMethods的优先级要高于excludeMethods。

<?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><package name="inter" extends="struts-default" namespace="/"><interceptors><interceptor name="liginInterc" class="com.qwx.methodInterceptor.MethodIntercepeor"><param name="includeMethods">login</param></interceptor><!--将自己定义的拦截器扩展到默认的拦截器栈  --><interceptor-stack name="myStrack"><!--Struts2默认的拦截器栈,位于struts2-core-2.5.x.jar下的struts.default.xml  --><interceptor-ref name="defaultStack"></interceptor-ref><interceptor-ref name="liginInterc"></interceptor-ref></interceptor-stack></interceptors><!--将默认拦截器栈指向我们自己扩展的栈  --><!--但这样对所有的action都生效,因此要为不需要被拦截的action去除拦截  --><default-interceptor-ref name="myStrack"></default-interceptor-ref><!--全局拦截,只要这个package的action的任何一个方法返回LOGIN,都可被拦截到login.jsp  --><global-results><result name="login">/login.jsp</result></global-results><action name="inter_*" class="com.qwx.interceptor.LoginAction" method="{1}"><result name="success" type="redirectAction">index</result><result name="login">/login.jsp</result><allowed-methods>login,login2</allowed-methods></action><action name="index" class="com.qwx.interceptor.IndexAction" method="index"><!--添加到了拦截器栈。不必每次声明  --><result name="index">/index2.jsp</result></action><action name="user" class="com.qwx.interceptor.UserAction" method="userInfo"><result name="userInfo">/user</result></action></package>
</struts>
OGNL和值栈
  1. OGNL是Object Graphic Navigation Language(对象导航语言的缩写)
    所谓对象图,即以任意一个对象为根,通过OGNL可以访问与这个对象关联的其它对象,${user.addr.name}这种写法就叫对象视图导航。
    通过其简单一致的表达式语法,可以存取对象的任一属性,调用对象的方法,遍历整个对象的结构图,实现对象类型转换等功能,它使用相同的表达式去存取其对象的属性。
  2. Struts2框架使用OGNL作为默认的表达式语言,(与JSTL相似)
    OGNL比EL表达式强大很多倍
    xwork提供OGNL表达式
    ognl-3.0.5.jar
  3. OGNL提供五大类功能
    支持对象方法调用
    支持静态方法的调用和值访问
    访问OGNL上下文
    支持赋值操作和表达式
    操作集合对象

struts2引入了OGNL表达式,在jsp页面中获取值栈中的值。

值栈:

  1. 什么是值栈?
    相当于Struts2框架的数据中转站,在值栈中存取值。
    我们使用ValueStack最大的作用是接收action相关的数据即web相关的对象携带到页面上
    ValueStack是Struts2提供的一个接口,实现类-OgnValueStack栈值对象
  2. 值栈的内部结构:
    1>root(CompoundRoot继承自List集合) -Struts把动作和相关对象压入ObjectStack,先进后出。
    2>context(OgnContext 实际为Map类型) -Struts把各种各样的映射关系(一些map类型的对象)压入Context栈中。
  3. 值栈的生命周期:
    Action是多例的,有一起请求,创建Action实例,创建一个ActionContext上下文对象,还会创建一个ValueStrack对象。
    ValueStrack的值是保存在request域中的,一个request对应一个valueStrack对象,每一个Action实例都有一个ValueStack对象。
    Struts框架把ValueStack对象保存在名为strutsValueStack的请求属性中,在request中,值栈对象是request的一个属性,所以可根据request获取值栈对象:ValueStack vs=(ValueStack )request.getAttribute(“struts.ValueStack”);
    也可以通过ValueStack vs=ActionContext.getContext.getValueStack(推荐使用)获取。

Struts2标签库

作为一款优秀的MVC框架,把重点放在了业务逻辑控制器和视图页面部分
       控制器部分主要有Action来提供,视图则是由大量的标签提供而代替之前在jsp写java代码
       如何定义呢?
       Struts2的标签库定义在struts-tags.tld文件中,可以在struts-core-2.5xx.jar中的META-INF目录下找到。
       要使用struts2的标签库,需要在jsp使用taglib指令导入struts2标签库,代码:

<%@taglib prefix="x" uri="/struts-tags" %>

要注意的是:上述代码中taglib指令的uri属性用于指定引入标签库描述文件的URI,在jsp文件中,所有的Struts2标签库使用s前缀。
       Struts2的标签大致分为两类:

  1. 普通标签:在页面生成时控制执行的流程
  2. UI标签:以丰富可复用的HTML文件来显示数据
值栈的内部结构


使用<s:debug>(新版本Struts2要在struts.xml中加入)

<constant name="struts.devMode" value="true"></constant>

即可在jsp中看值栈表。

使用root实现数据传递:

一般将单个对象放入root中值就在栈顶

  1. 添加数据

    1. 无属性名添加
      1>值栈对象.getRoot().add(0,“内容”);
      2>值栈对象.push(“内容”);
    2. 有属性名添加
      1>值栈对象.set(“key”,“value”);
      2>action中提供属性的getter方法实现
  2. JSP中获取值栈中root的数据

    1. 无属性名获取:<s:propety value="[0].top"
    2. 有属性名获取:<s:propety value=“key”

使用context实现数据传递

把数据放入context中

  1. 值栈对象.getContext.put(String key,Object value);
  2. ActionContext对象.put(String key,Object value);
    一般集合的数据我们都建议放在context中

取值采用:<s:property value="#age">
       #注意点:取数据时,不加#表示从Root中查找,找不到再到Context中。

public class Tags extends ActionSupport {private String name="sss";public String getName() {return name;}public void setName(String name) {this.name = name;}public String tag() {//获取值栈,从请求中获取ValueStack vs = ActionContext.getContext().getValueStack();System.out.println(vs);CompoundRoot root = vs.getRoot();//root.add(0,"内容");//就是压栈的过程root.push("内容");vs.set("key1", "内容1");Map<String, Object> context = vs.getContext();context.put("key2", "内容2");ActionContext.getContext().put("key3", "内容3");return "succ";}
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() +request.getContextPath()+"/";
%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head><base href="<%=basePath %>"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>new jsp</title>
</head>
<body><s:debug></s:debug><!--操作root  --><s:property value="name" />   <!--属性getter()取值  --><s:property value="[0].top" /><!--无属性取值  --><s:property value="key1" />   <!--有属性取值  --><br><!--操作context  --><s:property value="#key2" /><s:property value="#key3" />
</body>
</html>

各种标签

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() +request.getContextPath()+"/";
%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head><base href="<%=basePath %>"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>new jsp</title>
</head>
<body><h1>数据标签</h1><%request.setAttribute("pro", "这是内容"); %><!--request存放在值栈中的context中。键为request  --><!--取不到值显示默认内容  --><s:property value="#request.pro" default="显示默认内容"  /><%request.setAttribute("pro2", "<b>这是内容2</b>"); %><!--使html标签生效  --><s:property value="#request.pro2" escapeHtml="false" /><h1>a标签</h1><!--超链接路径,实际开发中是由后台配置的 --><a href="https://www.baidu.com">跳转百度</a><!--什么都不写默认本页路径  --><!--属性:1.href    2.action   3.namespace   4.method 可跳转到指定的方法 --><s:a>Struts2写法</s:a><!--不带参数写法  --><s:a namespace="/" action="tag">不带参数</s:a><!--带参数写法  --><s:a namespace="/" action="tag"><!--数字参数可直接解析,字符默认取OGNL表达式  --><s:param name="name" value="#request.pro2"></s:param><!--若要带默认字符,在value中写:%{zx}  -->带参数</s:a><h1>url标签</h1><!--带参数的访问路径  --><a href="<s:url action="sts" namespace="/user"><s:param name="param" value="123456"></s:param></s:url>">使用了URL的超链接</a><h1>控制标签</h1><%request.setAttribute("na", 100);ArrayList<String> list=new ArrayList<String>();list.add("刘备");list.add("张飞");list.add("关羽");request.setAttribute("list", list);%><s:if test="#request.na > 90">优秀</s:if><s:elseif test="#request.na>60">良好</s:elseif><s:else>差劲</s:else><h2>迭代</h2><s:iterator value="#request.list" var="str"><s:property value="#str"/></s:iterator><h2>for</h2>
<!--for(int i=-;i<9;i++) -->
<s:iterator begin="0" end="9" var="num"><s:property value="#num" />
</s:iterator>
</body>
</html>

Struts2原理

Struts2原理:

Action的方法访问

result实现并响应

Struts2文件上传

  1. 条件

    1. 使用post方式
    2. 使用二进制编码:multipart/form-data
    3. <input type=“file” name=“xxx”/
      Struts2底层仍采用apache的commons-fileupload组件
  2. 文件上传编写action的注意事项
    1. Struts2提供的文件上传命名规则:上传的字段名(form中的name)+FileName
    2. Struts2提供MIME类型命名规则:上传的字段名+ContentType
    3. 没有使用驱动模型时form表单提供的属性和Struts2提供的属性要生成set()/get()
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() +request.getContextPath()+"/";
%>
<!DOCTYPE html>
<html>
<head><base href="<%=basePath %>"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>new jsp</title>
</head>
<body><h1>Upload JSP</h1><form action="<%=basePath %>/upload.action" method="post" enctype="multipart/form-data"><input type="text" name="uname" value="zs" ><input type="file" name="logo" ><input type="submit" value="上传" ></form>
</body>
</html>
public class File extends ActionSupport{private static final long serialVersionUID = 4113091966014859681L;private String uname;private File logo;//文件名映射规则:表单name+FileNameprivate String logoFileName;//MIME类型规则:表单name+ContentTypeprivate String logoContentType;getter()/setter()......public String execute() throws Exception {//获取项目部署到磁盘的绝对路径String realPath = ServletActionContext.getServletContext().getRealPath("/");File file = new File(realPath,logoFileName);FileUtils.copyFile(logo,file);return Action.NONE;}}

文件下载

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort() +request.getContextPath()+"/";
%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head><base href="<%=basePath %>"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>new jsp</title>
</head>
<body><h1>download JSP</h1><s:a namespace="/" action="download">文件下载1<s:param name="fileName" value="%{'file1.jpg'}"></s:param></s:a><s:a namespace="/" action="download">文件下载2<s:param name="fileName" value="%{'file2.jpg'}"></s:param></s:a><a href="download.action?fileName=file3.jpg">文件下载3</a>
</body>
</html>
<?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><package name="down" extends="struts-default" namespace="/"><action name="download" class="com.qwx.download.DownloadAction"><!--stream是在struts-default.xml中配置的  --><result type="stream"><!--下载的如口  --><param name="inputName">ist</param><!--直接下载,不要打开 ;下载时显示文件名(EL表达式取名称) --><param name="contentDisposition">attachment;fileName=${fileName}</param></result></action></package>
</struts>
public class DownloadAction extends ActionSupport {private static final long serialVersionUID = -460985879932343381L;private String fileName;private File file;//给配置文件提供一个文件下载的入口public InputStream getIst() throws FileNotFoundException {//将file设为全局的return new FileInputStream(file);}getter()/setter()....public String execute() throws Exception {String realPath = ServletActionContext.getServletContext().getRealPath("/WEB-INF/download");System.out.println("开始下载文件"+realPath+"\\"+fileName);file=new File(realPath,fileName);return SUCCESS;}
}

Struts2-初学小结相关推荐

  1. Asp.Net初学小结 判断数组中是否有重复的数据

    Asp.Net初学小结 第一章 1.搭建Asp.net开发环境 1).net FrameWork(VS) 2)IIS(xp:5.1,2003:6.0,vista:70,win7:7.5) C:\Win ...

  2. Struts2学习小结

    1 基础 使用:导入 jar 包,配置 web.xml,并引入 struts.xml 文件 DMI:动态方法调用,调用时使用!分隔 action 名与方法名,如 index ! add.action, ...

  3. docker初学小结

    文章目录 基础概念 理念 同虚拟机的区别 运用 输出helloworld镜像 配置加速器 帮助命令 镜像命令 查看本机镜像 搜索其他镜像 下载镜像 删除镜像 容器命令 新建并启动容器 查看日志 查看容 ...

  4. CSS hack 初学小结

    什么是浏览器HACK:当我们使用不同的浏览器(Firefox,IE7, IE6, IE 8, Safari, Opera, chrome)访问同一个网站,或者页面的时候,会出现一些不兼容的问题,有的显 ...

  5. Asp.Net初学小结

    第一章 1.搭建Asp.net开发环境 1).net FrameWork(VS) 2)IIS(xp:5.1,2003:6.0,vista:70,win7:7.5) C:\Windows\Microso ...

  6. 视频编码帧间学习笔记(个人向初学小结)

    以下链接是视频编码的浅析,原理解释的很详细(像素计算过程错了,但原理没错),小白必看. 视频编码技术详解_tiankong19999的博客-CSDN博客_视频编码1.引言 如今我们所处的时代,是移动互 ...

  7. angularjs2 mysql_AngularJS2初学小结

    本文的实例中用到了ng2-bootStrap ,是用Angular2和bootStrap开发的第三方Component.感兴趣的同学可以戳链接看看. ###Component 自定义Component ...

  8. Hibernate-初学小结

    Hibernate初学小结 前言: 之前学习使用过Mybatis这个ORM持久层框架,使用配置文件替代了复杂的JDBC操作:使用它对开发的便利性不言而喻.之前听老师说过Hibernate是个自动化的O ...

  9. webmagic采集CSDN的Java_WebDevelop页面

    项目中使用到了webmagic,采集论坛一类的页面时需要一些特殊的配置.在此记录一下 先来看看我要采集的页面 点击第2页可以看到它的url是http://bbs.csdn.net/forums/Jav ...

  10. 微信拜年信息“大爆发”,真挚的祝福只剩下粘帖与群发

    很多人都有这样的感觉:一到春节,手机信息提示音就响个不停,祝福信息一个接一个,心里开心的同时,也为内容重复的群发信息而苦恼.马上就是春节了,正是微信拜年信息"大爆发"的日子,许多朋 ...

最新文章

  1. 死锁产生条件-互斥条件
  2. matlab p-tite分割图像,P'tite fourmi
  3. 「C++」C++ Primer Plus 笔记:第三章 处理数据
  4. UVA - 12569 Planning mobile robot on Tree (EASY Version) BFS
  5. lucene,lucene.net学习教程
  6. 基于 Flink + ClickHouse 打造轻量级点击流实时数仓
  7. Hive的数据模型-分区表
  8. Cookie、Session、Token
  9. 【动态规划刷题笔记】线性dp:合唱队形(最长递增子序列的变体)
  10. 软件构造 第五章第三节 可复用的设计模式
  11. selenium--python如何定位一组元素并返回文本值
  12. pcs7服务器一直显示在同步,西门子PCS7OS系统时钟同步出现跳变的解决方法
  13. 使用Outlook 2007待办事项栏
  14. 12-14日小米4 手机不停的无限重启。用下面方法及清理电源,音量按钮恢复
  15. 计算机应用基础任务教化2010,【计算机应用论文】茶文化下的计算机应用基础课程改革(共5535字)...
  16. 【SSH】--鸿雁传书,信件发送
  17. 虚拟opc服务器软件,OPC Server
  18. 华为手机录屏大师录制的视频在本地目录找不到无法转移到PC的问题解决方案——免费转移视频
  19. 解决苹果浏览器点击事件无法生效的问题
  20. java自学--容器

热门文章

  1. unity文本隐藏_AI论文中隐藏的笑话,全看懂的绝对是高手!
  2. RK3588平台开发系列讲解(SPI篇)SPI内核配置及驱动使用
  3. AUC和ROC曲线的前世今生
  4. java web底层原理_详解Java开发Web应用程序的底层原理
  5. 星药科技李成涛:人工智能在药物研发中的应用
  6. 双十一活动三个阶段分别需要做什么,双十一怎样引流,双十一怎样开直通车
  7. pageadmin已经过时_为何激光光盘已经过时了
  8. Android 集成百度身份证识别
  9. 如何理解「外汇储备导致人民币货币增加」?
  10. V4L2视频驱动框架---v4l2_device管理模块简述