Struts2

Struts2

 https://blog.csdn.net/qq_35064774/article/details/64934709

 

基础。配置,action,拦截器,Struts2UI标签,数据回显,资源国际化(省略),OGNL表达式,valueStack

 

基础1.为什么要引入struts?

既然Servlet能够完成的事,我们为啥要用框架呢??因为框架帮我们封装了很多常用的功能,更加灵活[不用把路径等信息写死在程序上],每个Servlet中都有doGet和doPost这样的方法,没必要的。我们抽取出来,通过配置文件来把这两个方法替换掉,那么我们的程序就会更加优化。

 

基础2.struts流程:

  • 加载web.xml文件
  • 找到我们配置的filter中的StrutsPrepareAndExecuteFilter拦截器
  • 调用init()方法,同时访问struts.xml
  • action方法返回页面

 

配置1 .路径配置:

  • 如果配置后缀为action。那么后缀一定要写action
  • 如果配置后缀为action,do,。那么后缀可以是action,可以是do,也可以不写
  • 如果配置后缀为action,,。那么后缀可以是action,可以不写

 

配置2.全局视图

    <global-results>
        <result name="success">/index.jsp</result> </global-results>

 

配置3.

 <!-- 什么情况不配置class? 即处理的aciton -->

         答案: 当只是需要跳转到WEB-INF下资源的时候。 -->
         <action name="test2"> <result name="success" >/WEB-INF/index.jsp</result> </action>

 

action 1:为什么继承ActionSupport

 

ActionSupport类实现了VlidationAware等数据校验功能的类。

在Action类中需要用到Struts为我们提供的数据校验等Struts已经帮我们实现的功能,我们就继承着ActionSupport类

  • 如果我们使用到了Struts2一些特用的功能,我们就需要继承ActionSupport
  • 如果我们没用到Struts2的特殊功能,只要平凡写一个Java类行了。
  • 大多情况下,我们还是会继承ActionSupport的。

 

 

 action 2: 数据封装

方法1. 表达式封装(params拦截器来实现)

Struts预先帮我们完成了对数据封装的功能,它是通过params拦截器来实现数据封装的

  • 创建一个User类,基本的信息和JSP页面是相同的。提供get/set方法
    •  

       

  • 在JSP页面,提交的name要写成user.username之类的(
    用户名:<input type="text" name="user.username"><br>

 

方法2.模型驱动 ,实现 ModeDriven 接口

前提:当我们使用params拦截器完成数据自动封装的时候,如果要封装的是JavaBean对象,那么在web表单中就必须的name写上javaBean.属性名....

这样的话,web层和Action层就耦合。因为在web层必须要知道封装的JavaBean对象是什么才能够实现自动封装!而模型驱动就解决了这个问题!即时不知道Action层的JavaBean对象是什么,也能够完成数据自动封装!

操作:实现ModelDriven接口,

  • 实现ModelDriven接口,重写方法....实现接口时,要封装的对象是什么,形参类型就给什么。
    •  

  • JSP提交页面,直接写上JavaBean对象的属性就行了..不需要写上JavaBean对象的名称!(
        <td>用户名:<input type="text" name="username"></td>

 

3.属性方法:

属性封装
 在 action 中设置成员变量,变量名与表单中的 name 属性值相同
 生成变量的 set 方法

 

 

 

 

 

 

 action 3:  得到域对象

Struts怎么把数据保存在域对象中呢???Struts提供了三种方式

1.通过ServletActionContext得到Servlet API

    //通过ServletActionContext得到Servlet API
        javax.servlet.ServletContext context = ServletActionContext.getServletContext();
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        HttpServletResponse response = ServletActionContext.getResponse();

 2.通过ActionContext类来得到request、response、session、application被Struts封装的Map集合

//得到ActionContext 对象
        ActionContext context = ActionContext.getContext();
        Map<String, Object> session = context.getSession();
        Map<String, Object> application = context.getApplication();       
        //这是request的Map
        Map<String, Object> request = context.getContextMap();

 3.实现接口

当web容器发现该Action实现了Aware接口,会把相对应的资源通过Aware接口注射进去,实际上就是一种IOC。

Aware实际就是一种拦截器,拦截代码在执行Action之前执行、将资源注射到Action中.

小结:

如果我们需要使用到对象的其他方法,类似getContextPath()之类的,那么只能使用第一种

如果我们就按照平常的开发,我们就使用第二种【获取简单,没有耦合】

至于第三种,当我们将来可能开发BaseAction的时候,就使用它!

 

action 4:  日期转换问题

action 5:  文件上传和下载

 

 

 Interceptor

拦截器 1:为什么我们要使用拦截器

Struts为我们实现了很多的功能,比如数据自动封装阿..文件上传功能阿....Struts为我们提供的这些功能都是通过拦截器完成的

  • 数据自动封装通过<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>这个拦截器。
  • 文件上传通过<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>这个拦截器

值得注意的是:Struts2默认执行的是默认拦截器栈,一旦用户有指定执行哪些拦截器,那么默认的拦截器栈就不会被执行!

 

 

拦截器 2:自定义拦截器:

Struts2提供了Interceptor这个拦截器接口,只要我们实现这个接口,那么这就算是自定义开发拦截器

public class MyInterceptor implements Interceptor { @Override public void destroy() { } @Override public void init() { } @Override public String intercept(ActionInvocation actionInvocation) throws Exception {
//拦截方法案例:
//得到正在执行的代理对象
        ActionProxy proxy = actionInvocation.getProxy();
        //通过代理对象得到正在执行的方法
        String method = proxy.getMethod();
        //如果方法的名字不是login,那么就让他们返回到login页面上
        if (!method.equals("login")) { //查看用户是否登陆了 Object user = ActionContext.getContext().getSession().get("user"); //如果没有登陆,回到login页面 if (user == null) { return "input"; } else { //登陆了,那么就让它访问具体的用户信息页面 return actionInvocation.invoke(); } } else { //如果是访问login方法,那么就让它执行 return actionInvocation.invoke(); }
 // return null; } }

由于我们配置了自定义拦截器,那么struts默认的拦截器栈是不会执行的。如果我们想要使用默认拦截器栈的功能,就必须把它配置在我们自定义的栈中!

 <package name="xxx" extends="struts-default" > <interceptors> <!--配置用户自定义的拦截器--> <interceptor name="MyInterceptor" class="TestAction"/> <!--自定义拦截器栈,我们配置了自定义的拦截器,默认的拦截器栈就不会被执行,因此,想要使用默认的拦截器功能,就要配置进来--> <interceptor-stack name="mystack"> <!--引用默认的拦截器栈,一定要放在第一行--> <interceptor-ref name="defalutStack"/> <!--引用自定义的拦截器--> <interceptor-ref name="MyInterceptor"/> </interceptor-stack> </interceptors> <!--上面配置了拦截器栈,但是没有被执行...下面配置执行拦截器--> <default-interceptor-ref name="mystack"/> <action name="TestAction" class="TestAction" method="execute"> <result name="success">/index.jsp</result> </action> </package>


拦截器执行顺序:

  • 当服务器开启的时候,会执行拦截器的init()方法
  • 当访问Action时,Action实例被创建
  • 创建完Action实例,会调用拦截器的interceptor()方法
  • 最后,执行Action的execute()方法

 

拦截器 3: 其他拦截器

计时拦截器:

执行等待拦截器:

Struts2防止表单重复提交拦截器通过拦截器来实现,在需要提交的表单上使用token标签,<s:token></s:token>,

<table border="1"> <s:token></s:token> <tr> <td>用户名:<input type="text" name="username"></td> </tr>

在struts配置文件中配置拦截器,token拦截器默认是不会启动的,也就是说:需要我们手动配置.

 <action name="user_*" class="zhongfucheng.action.UserAction" method="{1}"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="token"> <!-- 要拦截的方法! --> <param name="includeMethods">register</param> </interceptor-ref> <!--如果是list,那么就跳转到list的JSP页面--> <result name="list"> /list.jsp</result>

 

 

Struts2UI标签:

显示页面的标签

<%--我们发现,Struts2UI标签用起来和HTML是差不多的--%>
<s:form id="form1" name="form1" method="POST" action="#"> <%--输入框数据,lable就相当于我们以前外边写的数据--%> <s:textfield label="用户名" name="user.username"/> <%--密码框--%> <s:password label="密码" name="user.password"/> <%--提交按钮--%> <s:submit value="提交"/> </s:form>

 

 

数据回显:

EL表达式的时候就已经用过了数据回显,Struts2也提供了数据回显的支持,并且,使用数据回显必须要使用Struts2的标签。有两种方法,表达方式的区别

方法1:

  • 把数据放到request域中存储,跳转到对应的JSP页面...
    public String login() { //把数据存储到域中 Map<String, Object> request = ActionContext.getContext().getContextMap(); request.put("username", "zhongfucheng"); request.put("password", "123"); return SUCCESS; }
  • JSP页面使用Struts2标签,设置value属性就可以进行数据回显了
<s:form id="form1" name="form1" method="POST" action="" > <%--输入框数据,lable就相当于我们以前外边写的数据--%> <s:textfield label="用户名" name="user.username" value="%{#request.username}"/> <%--密码框--%> <s:password label="密码" name="user.password"/> <%--提交按钮--%> <s:submit value="提交"/> </s:form>


方法2:

  • 直接放在值栈的数据就是根元素数据
        //得到值栈对象
        ValueStack valueStack = ActionContext.getContext().getValueStack();
        valueStack.set("username","zhongfucheng");
  • 在JSP就可以直接获取了
  <s:textfield label="用户名" name="username"/>

 

 

 

资源国际化:

 

 

 

OGNL表达式:

操作对象属性的开源表达式。

  • 支持对象方法调用,如xxx.doSomeSpecial()
  • 支持类静态的方法调用和值访问,表达式的格式【例如:"@@floor(10.9)"就是调用Math.floor()的方法了】
  • 支持赋值操作和表达式串联【这个其实EL表达式也能做】
  • 访问OGNL上下文(OGNL context)和ActionContext
  • 操作集合对象【EL只能遍历集合,OGNL可以创建集合】

 

1.valueStack对象   (值栈对象)

valueStack是Struts2数据存储的核心..ValueStack 实际是一个接口

.首先要知道数据是怎么存的,存到哪里,然后才讲解OGNL表达式是怎么取出数据的。

  • 当用户访问Action,都会创建一个Action对象,ActionContext对象、valueStack对象..
  • Struts2把Action对象放进valueStack对象之中。
  • 将valueStack放进request域中,传入JSP页面(key: struts.valueStack)
  • JSP页面就可以使用OGNL表达式获取值栈中的数据了!

在Action中我们可以手动获取值栈对象,有两种方式获取

// 获取值栈对象,方式1:
        HttpServletRequest request = ServletActionContext.getRequest();
        ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");
        
        // 获取值栈对象,方式2: ActionContext ac = ActionContext.getContext(); ValueStack vs2 = ac.getValueStack();

CompoundRoot保存着这样的数据:

  • Action对象以及Action对象的成员属性数据
  • 使用ValueStack对象.push()进去的数据
  • 使用ValueStack对象.set()进去的数据
  • 其他代理对象的数据
  • list存储结构

OgnlContext保存着这样的数据:

  • 维护了CompoundRoot中所有的数据
  • request、response等域对象所有的数据
  • map存储结构

 

2.OGNL表达式取值

  • Struts2会将valueStack对象封装进request对象域中,传入JSP页面。
  • valueStack存储着OgnlContext对象。
  • OgnlContext对象维护了CompoundRoot对象的数据
  • CompoundRoot存储着Action等数据

也就是说通过OgnlContext对象可以获取大部分我们需要的数据了。

 

 

构建一个OGNL表达式,再解析表达式

  • 如果是CompoundRoot类的数据,表达式不需要带#号
  • 如果不是CompoundRoot类的数据,表达式需要带#号

例如:

 <!-- 页面: 必须要拿到ValueStack -->
     <br/>1. 取根元素的值<br/> <s:property value="user.id"/> <s:property value="user.name"/>  <br/>2. 取非根元素的值<br/> <s:property value="#request.cn"/> <s:property value="#session.Session_data"/> <s:property value="#application.Application_data"/> <br/> <!-- 自动找request/session/application,找到后立刻返回 --> <s:property value="#request_data"/> <s:property value="#attr.Session_data"/> <s:property value="#attr.Application_data"/> <br/> <!-- 获取请求的参数数据 --> <s:property value="#parameters.userName"/> <!-- struts的调试标签:可以观测值栈数据 --> <s:debug></s:debug>

 (此处不确定是否正确,待完善)

 

 

 

3.在 jsp 中使用 OGNL 需要引入 struts tag lib。

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

然后使用 标签 s:property:

<s:property value="'hello world'"/>

 

转载于:https://www.cnblogs.com/StingLon/p/9816753.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值