struts2笔记整理

整理struts2的概述、入门、执行过程、源代码、核心配置文件、分模块开发、action编写方式、action访问方法介绍

Struts2入门:

概述:

Struts2的框架是应用在web层的框架-显示层

Struts2是在struts1和webwork之上发展的全新的框架

Struts可以解决的问题:

         图。

Strut2的版本:

Web层常见的框架:

  1. springMVC
  2. struts2

入门案例:

开发流程:

  1. 导入jar包:
    1. Apps的目录下的War包放入到tomcat可以运行
    2. Docs是文档
    3. Src是源代码
    4. Lib是jar包

直接到apps下的实例程序中找jar包

  1. 创建action
    1. 访问aciton,默认执行action类中的execute()方法

package com.pshdhx.action;

 

import com.opensymphony.xwork2.ActionSupport;

 

public class HelloAction extends ActionSupport{

    public String execute() throws Exception {

        return "ok";

    }

}

    1. 配置action类的访问路径
      1. 创建struts2的核心配置文件,名称和位置是固定的,名称是struts.xml,位置在src目录下。
      2. 从apps下的*.war文件的实例程序中找到dtd约束

<!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <package name="helloDemo" extends="struts-default" namespace="/">

        <!-- name中写上访问的名称 -->

        <action name="hello" class="com.pshdhx.action.HelloAction">

            <!-- 配置方法的返回值到页面 -->

            <result name="ok">/hello.jsp</result>

        </action>

    </package>

</struts>

 

访问路径:

http://localhost/struts2_day01/hello.action          404不能访问

配置文件的过程由过滤器做,需要配置过滤器

   <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>

 

Struts2的执行过程:

Servlet默认是第一次访问时创建

过滤器是启动服务器时创建

过滤器操作:

  1. 获取到访问的路径,hello.action
  2. 到src下边找到strut2.xml文件,使用dom4j进行解析内容,拿着hello值到xml文件中匹配name属性是否一样
  3. 匹配name属性的值一样,都是hello,找到name属性所在标签的class属性,得到action的全路径,反射实现class的功能
  4. 反射代码,得到字节码文件

Class clazz = Class.forName(“action全路径”);

//得到的方法是execute

Method method = clazz.getMethod(“execute”);

//方法执行

Object obj = method.invoke();

  1. 得到action方法的返回值,配置result的name值,进行页面跳转。

Struts2的源代码:

过滤器源代码:

Init(),过滤器服务器启动时创建,执行init方法

  1. 加载自定义的xml配置文件和struts2自带的配置文件
  2. InitDispatch,创建路径来加载默认的配置文件

  Default.properties

  Struts-default.xml

  Struts-plugin.xml

  Struts.xml  :配置action和常量

  Struts.properties  :配置常量

  Web.xml  :配置核心过滤器和常量

Struts2的核心配置文件:

名称和位置固定 :src下的struts2.xml

Package:

         类似于代码中的包,区分不同的action,要配置action,必须先写package标签,在package里边才能配置action。

         Name:属性值和其本身的功能没有关系,类似于id,在一个配置文件中可以写多个package标签,但是name属性值不能相同。

         Extends:属性值固定为 struts-default。写了这个属性之后,在package里边配置的类,就有了action的功能。

         Namespace:属性值和action标签里的name属性值构成访问的路径 / hello.action,默认是/,可以不写。

 

Action:

         配置action的访问的路径

         Name属性:与namespace的属性值构成访问路径

         Class属性:action类的全路径

         Method属性:默认执行的是execute方法,让action里的多个方法进行执行,可使用method方法进行定义。

Result:

         根据返回值到不同的路径中去。不仅是页面,有可能是action

         Name属性:和你方法的返回值一样

         Type属性:配置如何到路径中去。默认值是转发的操作,还有可以是重定向的操作。转发操作:启动一次,地址栏不变。

Struts2的常量的配置:

在struts.xml文件中定义<constant name=”” ></constant>标签。

        

<constant name="struts.i18n.encoding" value="UTF-8"></constant>

在struts.properties文件中配置

struts.i18n.encoding=UTF-8

表单提交到action里边,在action可以获取表单的提交数据

表单提交数据有中文,有乱码问题,解决

Post提交直接设置编码

Get提交做编码转换

如果在action获取表单通过post提交中文,中文的乱码方式解决了,不需要自己处理乱码问题。

在web.xml文件中进行配置

Struts2的分模块的开发【协同开发】:

每个人都可以写配置文件,把写的配置文件引入到struts.xml文件中

<struts>

    <!-- 引入其他的配置文件 -->

    <include file="cn/pshdhx/action/hello.xml"></include>

</struts>

 

Action的编写方式:

  1. 就是一个普通类,不继承任何类,也不实现任何接口
  2. 创建一个类,实现action接口【xwork中的】
  3. 创建一个类,继承actionsupport类

Action的访问方法介绍:

  1. 通过配置method属性完成
    1. Action中有多个方法,method属性是方法的名称
  2. 通配符book_*

<action name="book_*" class="com.pshdhx.action.HelloAction" method="{1}"></action>

    3.动态访问实现

整理struts2的结果页面操作、在action获取表单数据、struts2提供获取表单数据方式、struts2获取表单元素封装到集合

1、结果页面操作

  1. 全局结果页面

<package name="local" extends="struts-default" namespace="/">

        <!-- 多个界面返回相同的action -->

        <global-results>

            <result name="success">/hello.jsp</result>

        </global-results>

        <action name="hello" class="com.pshdhx.action.HelloAction"></action>

        <action name="others" class="com.pshdhx.action.OthersAction"></action>

    </package>

 

  1. 局部结果页面

既配置了全局页面,也有局部页面,以局部页面为准。

  1. Result标签的type属性

Type属性是如何到路径去

         默认值:做转发操作,dispatch【一次请求,地址栏不发生改变】

         重定向操作:redirect【两次请求,地址栏发生变化为*.jsp】

         Chain:转发到action,一般因为缓存问题不用

         RedirectAction:重定向到action。用处:添加之后到列表页面。

        

<result name="success" type="redirectAction">others.action</result>

 

2、在action获取表单提交的数据

之前在web阶段,提交表单到servlet里边,在servlet里边使用request对象获取到表单属性值,getParameter getParameterMap

         表达提交到action,但是action没有request对象,不能直接使用request对象。

1、使用ActionContext类获取

        

Map<String ,Object> getParameters() ;返回一个包含所有HttpServletRequest参数信息

 

因为方法不是静态的方法,需要创建ActionContext对象

这个ActionContext对象不是new出来的

Static ActionContext getContext();获取当前线程的ActionContext对象

静态的所以ActionContext.method();

public String execute() throws Exception{

        //第一种方式使用AcitonContext类获取

        //获取ActionContext对象

        ActionContext  context = ActionContext.getContext();

        //调用方法得到表单数据

        //key是表单中的name值,value是输入的值

        Map<String,Object> map = context.getParameters();

        Set<String> keys = map.keySet();

        for(String key:keys) {

            //根据key得到value

            //数组方式:因为输入项里边可能有复选框情况

            Object[] obj = (Object[]) map.get(key);

            System.out.println(Arrays.toString(obj));

        }

        return NONE;

    }

 

2、使用ServletActionContext类获取

        

Static HttpServletRequest getRequest(); 获取web应用的HttpServletRequest对象

Static HttpServletRequest getResponse(); 获取web应用的HttpServletResponse对象

Static ServletContext getServletContext(); 获取web应用的ServletContext对象

Static pageContext getPageContext(); 获取web应用的PageContext对象

静态方法的最大好处:类名可以直接调用;

public String execute() throws Exception{

        //使用ServletActionContext类获取表单数据

        HttpServletRequest request = ServletActionContext.getRequest();

        String username = request.getParameter("username");

        String password = request.getParameter("password");

        System.out.println(username+" "+password);

        return NONE;

    }

 

3、使用接口注入方式获取:

让action实现接口,为了得到request对象

public class FormAction3 extends ActionSupport implements ServletRequestAware{

    //使用接口方式得到servletrequest对象

    private HttpServletRequest request;

    @Override

    public void setServletRequest(HttpServletRequest request) {

        // TODO Auto-generated method stub

        this.request = request;

    }

    public String execute() throws Exception{

        String username = request.getParameter("username");

        String password = request.getParameter("password");

        System.out.println(username+" "+password);

        return NONE;

    }

}

  1. 在action中操作域对象
    1. Request域对象

HttpServletRequest request = ServletActionContext.getRequest();

Request.setAttribute(“req”,”reqValue”);

 

    1. Session域对象

HttpSession session = request.getSession();

Session.setAttribute(“sess”,”sessValue”);

 

    1. ServletContext域对象

ServletContext context = ServletActionContext.getServletContext();

Context.setAttribute(“contextName”,”contextValue”);

 

3、struts2提供获取表单数据方式

1、属性封装

         使用最原始的方式获取表单元素封装到实体类对象

        

    public String execute() throws Exception{

        HttpServletRequest request = ServletActionContext.getRequest();

        String username = request.getParameter("username");

        String password = request.getParameter("password");

        User user = new User();

        user.setUsername(username);

        user.setPassword(password);

        System.out.println(user);

        return NONE;

    }

直接把表达提交属性封装到action属性中

  1. 在action成员变量位置定义变量,变量名称与表单输入项的name属性值一样
  2. 生成变量的set方法,便可以得到表单数据,省去了原始的得到request对象的过程。
  3. 使用属性封装获取表单数据到action类的属性里边去,不能把数据直接封装到实体类对象里边去。

 

2、模型驱动封装【重点】

         可以直接把表单数据封装到实体类对象中去

  1. action类实现ModelDriven接口
  2. 实现接口里边的方法:getModel();把创建的对象返回即可
  3. 在action里边创建实体类对象
    1. 前提条件:表单输入项里边的name属性和实体类的属性值一样。

public class FormAction5 extends ActionSupport implements ModelDriven<User>{

    private User user = new User();//实体类对象必须实例化,否则会得到null

    @Override

    public User getModel() {

        // TODO Auto-generated method stub

        return user;

    }

    public String execute() throws Exception{

        System.out.println(user);

        return NONE;

    }

}

使用模型驱动和属性封装注意的问题:不能同时使用两个封装来封装一个表单对象,如果同时使用,那么执行的是模型驱动的方法,属性封装的内容为null

  1. 表达式封装
  1. 在action类里边声明实体类,前提是有了实体类,并且有实体类属性的set和get方法
  2. 生成实体类的set和get方法
  3. 在表单输入项的name属性写表达式形式,name=user.usernameèuser实体类的set方法

5、比较表达式封装和模型驱动封装:

         1、使用模型驱动只能把数据封装到一个实体类中。

         2、使用表达式封装可以把数据封装到不同的实体类对象中去。

        

4、struts2获取表单数据封装到集合中

1、封装到list集合

         1、在action声明List集合

         2、生成list的set和get方法

         3、在表单输入项里边写表达式封装的方法

        

<form action="${pageContext.request.contextPath}/list.action" method="post">

        用户名:<input type="text" name="list[0].username" /></br>

        密    码:<input type="password" name="list[0].password"/></br><br>

       

        用户名:<input type="text" name="list[1].username" /></br>

        密    码:<input type="password" name="list[1].password"/></br><br>

        <input type="submit" value="提交"/>

    </form>

 

2、封装到map集合

         1、声明map集合

         2、生成set和get方法

         3、在表单输入项的name属性写表达式

        

<form action="${pageContext.request.contextPath}/map.action" method="post">

        用户名:<input type="text" name="map[0].username" /></br>

        密    码:<input type="password" name="map[0].password"/></br><br>

       

        用户名:<input type="text" name="map[1].username" /></br>

        密    码:<input type="password" name="map[1].password"/></br><br>

        <input type="submit" value="提交"/>

    </form>

public class FormMapAction extends ActionSupport{

    private Map<Integer,User> map;

    public Map<Integer, User> getMap() {

        return map;

    }

    public void setMap(Map<Integer, User> map) {

        this.map = map;

    }

    public String execute() throws Exception{

        System.out.println(map);

        return NONE;

    }

}

 

struts2的ognl、值栈、foreach标签+EL表达式获取值栈元素

Ognl概述:

         在web阶段学习过表达式EL:只能用在jsp中获取域对象里边的值。

         也是一种表达式:功能更加强大,在struts2里边操作值栈数据,一般把ognl放在struts2里边进行操作;和struts2标签一起使用操作值栈,但它不是struts2的一部分,是一个单独的项目:

                  支持静态方法调用;调用objNamemethodName().

                  支持静态方法调用和值访问;@类全名@方法名(值).

                  支持赋值操作和表达式串联

                  访问ognl上下文和ActionContext

                  操作集合对象

         1、导入jar包,在struts2里边有jar包

Ognl入门案例:

  1. 使用struts2标签+ognl计算字符串长度
  2. 在java代码中,调用字符串.length()实现
  3. 使用struts2标签
    1. 在使用jstl时候,导入jar包之外,在jsp页面导入标签库

使用struts2标签的时候,在jsp中引入struts2的标签库

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

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

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

    <s:property value="'pshdhx'.length()"/>

</body>

</html>

什么是值栈:

         在web阶段,在servlet里边进行操作,把数据放到域对象里边,在页面中使用el表达式获取到,域对象在一定范围之内,可以存放值和取值。

         在struts之中,本身有存储机制,类似于域对象,可以存取数据。

         在action之中,把数据放到值栈之中,在页面中取得值栈数据。

         Servlet和action的区别:

  1. Servlet默认在第一次访问时创建,创建一次,单实例对象
  2. Action在访问时创建,每次访问都是创建一个action对象,多实例对象。

 

值栈的存放位置:

每次访问action的时候,都会产生一个action对象

在每个action对象里边都会有一个值栈对象,只有一个

获取值栈对象:

  1. 使用ActionContext类里边的方法得到值栈对象。也可获取表单数据

    ActionContext context = ActionContext.getContext();

        ValueStack stack = context.getValueStack();

 

值栈的内部结构:

  1. 值栈分为两部分:

第一部分root,结构是list集合

         一般的操作都是root里边的数据

第二部分context,结构是map集合

Context处打断点,服务器debug执行,得到如下画面:

 

向值栈中存放数据:

  1. 访问action,执行action的方法有返回值,配置返回值到jsp页面中去,使用<s:debug>标签可以值栈的结构和存储值。
  2. Action里边也有值栈对象,但只是值栈的引用。

向值栈中放数据:

  1. 获取值栈对象,调用值栈中的set方法放入数据
    1. Map结构,根据名称获取它的值。

<s:property value=”username”/>

 

  1. 调用值栈里边的push方法
    1. String结构,只有设置的值,根据数组获取它的值。

<s:property value=”[0].top”/>  //表示取到数组元素的第一个值,即栈顶元素的值。

 

  1. action里边定义变量,生成get方法,可以放入值栈中。 
  2. 可以向值栈中放入实例化的实体类对象。
  3. 可以向值栈中放入list集合。
    1. 实例化list对象
    2. 生成get方法
    3. 实例化user对象,多个,list.add();

 

从值栈中获取数据:

  1. 使用struts标签+ognl表达式获取值栈的数据
  2. <s:property value=”表达式”/>
  3. 可以获取属性值
  4. 可以得到对象
  5. 可以获取list集合

List[0].username;

<s:iterator value=”list” >

  <s:property value=”username”/>

</s:iterator>

遍历list集合,得到每个user对象

机制:把每次遍历出来的user对象放到Context里边

获取context里边数据特点:写ognl表达式,使用#获取数据对象。

<s:iterator value=”list” var=”user”>

  <s:property value=”#user.username”/>

</s:iterator>

使用foreach标签+El表达式获取值栈元素:

  1. 导入jstl包+stand包
  2. 引入标签库

  <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<c:forEach items="${list}" var="user">

        ${user.username }

        ${user.password }

    </c:forEach>

EL表达式获取域对象的值

向域对象里边放值使用setAttribute方法,获取值使getAttribute方法;

底层增强request对象里边的方法,getAttribute方法

         首先从request域里边获取值,获取到,直接返回;

         如果从request域里边获取不到值,到值栈中把值获取出来,把值方法域对象里边去;

查看源代码:

         增强request方法,有多种模式,有动态代理,继承。

Class StrutsRequestWrapper extends HttpServletRequestWrapper

Public Object getAttribute(String key)

#的使用:值栈的context里边的数据

获取request对象的值:

        

<s:property value=”#request.req”/>

%的使用:在struts2标签里边使用ognl表达式,如果直接再struts2表单标签里边使用ognl表达式不识别,只有在%之后才识别。

普通:<input type=”text” name=”username” value=”${req}”>

Ognl:<s:textfield  name=”username” value=”%{#request.req}”></s:textfield>,否则会当成字符串处理。

整理拦截器概述、底层原理、过滤器和拦截器的区别、自定义登录拦截器、struts2的标签库、表单标签

拦截器概述

         只是struts2的概念,把框架的功能都是封装在拦截器中。

         Struts2里边有很多的拦截器,不是每次所有拦截器都执行,只会执行一些默认的拦截器。

         Struts2里边默认的拦截器的位置:默认的常量在core包中的default.property里边。默认的拦截器在struts-default.xml文件中。

         拦截器在什么时候执行:

                  拦截器在action对象创建之后和action的方法执行之前

拦截器底层原理

  1. 拦截器的底层使用了aop的思想
    1. 文字描述:Aop叫做面向切面编程。有个基本的功能,想要扩展功能,不改变源代码实现。
    2. 流程图:

  1. 责任链的设计模式
  1. 在java中,有很多设计模式,责任链是其中一种,与web中的过滤链相似。
    1. 过滤链:一个请求可以有多个过滤器进行过滤,每个过滤器只有做放行操作才能到下一个过滤器。
    2. 要一次性执行多次操作,有添加,修改,删除操作,首先执行添加操作,做类似于放行的操作,之后依次进行。

Aop思想和责任链模式如何应用到拦截器里边

拦截器在action创建之后,在action方法执行之前执行。

在action方法执行之前使用使用拦截器,执行过程中使用使用aop思想。在action里边没有直接调用拦截器的方法,使用配置文件的方式进行操作。在struts-default.xml文件中。

在拦截器执行的时候,执行很多的拦截器,这个过程使用责任链模式。

执行action

Execute.executeAction(request,reponse,mapping);

创建action对象,使用动态代理模式

ActionProxy proxy = getContainer.getInstance(ActionProxyFactory.class).createActionProxy(

Namespace,name,method,extraContext,true,false);

执行很多的拦截器,遍历执行,放行。

If(interceptor.hasNext())

         执行action的方法

Proxy.execute();

Return invocation.invoke();

 

过滤器和拦截器的区别

过滤器:它可以过滤jsp,html,servlet,图片等路劲。

拦截器:它只会拦截action中的方法。

自定义登录拦截器

  1. 拦截器结构:

Class ModelDrivenInterceptor extends AbstractInterceptor implements Interceptor

Void init();

Void destory();

String interceptor(ActionInvocation invocation);

开发中建议使用继承MethodFilterInterceptor类实现

可以让action中的某个方法不进行拦截。

拦截器和action的关系

不是在action中调用拦截器的方法,而是通过配置文件的方式进行操作。

需求:在项目中,有很多action的超链接,实现只有是在登录的时候,才能点击点击action的超链接实现功能,如果不是登录状态,返回登录的界面。

使用session的域对象判断登录的状态:判断session里边是否有值。

 

  1. 实现登录的基本功能,成功之后向session中放值。

Request.getSession().setAttribute(“username”,username);

  1. 添加登录拦截器的功能:判断session中是否有username的值。
  1. 创建类,继承MethodFilterInterceptor类

Protected String doIntercept(ActionInvocation invocation) throws Exception{

  HttpServletRequest request = ServletActionContext.getRequest();

  Object obj = request.getSession().getAttribute(“username”);

  If(obj!=null){

  //登录状态,放行

  Return invocation.invoke();

}else{

  Return “login”;

}

}

 

  1. 配置action和拦截器的关系(注册拦截器)
  1. 在要拦截的action标签标签所在的的package标签里面声明拦截器

<!—声明拦截器-->

<interceptors>

  <interceptor name=”loginInterceptor” class=”com.pshdhx.Interceptor”>

  </interceptor>

</interceptors>

  1. 在具体的action标签里面使用声明的拦截器

<interceptor-ref name=”loginInterceptor”></interceptor-ref>  

  1. Struts里边执行很多的默认的拦截器,但是如果在action里边配置自定义自定义拦截器,问题:默认的拦截器不会执行了。必须把默认的拦截器执行一次。

<interceptor-ref name=”defaultStack” ></interceptor-ref>

 

 

对action方法不进行拦截:

 

Struts2标签库(会用)

同一行:

 

   

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值