Struts笔记(入门)

本文深入探讨Struts2框架的核心概念,包括其架构、配置、执行流程及与SpringMVC等框架的区别。详细讲解了Struts2的Maven依赖设置、Action编写、配置文件解析、拦截器原理及自定义拦截器的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

struts2笔记

struts2概述

1.struts框架应用javaee三层结构中web层框架
2.struts2框架在struts1和webwork基础之上发展全新的框架
struts2解决问题
web层常见框架

  • springMVC
  • struts

struts2框架入门

第一步:设置maven依赖

 <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.3.16</version>
        </dependency>

第二步:创建action

package action;

public class HelloAction{
//一.每次访问servlet时候,都会执行service
//    1.继承HttpServlet,重写类里面的方法
//    2.在web.xml中配置servlet访问路径
//二.每次访问action,默认执行execute方法
//    1.配置action访问路径
    public String execute(){
        return "ok";
    }
}

第三步:配置action类访问路径
1.创建struts2核心配置文件(struts.xml)
2.引入dtd约束
3.action基本配置
4.配置struts2过滤器

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="helloDemo" extends="struts-default" namespace="/">
        <!--        name:访问名称-->
        <action name="hello" class="action.HelloAction">
            <!--        配置方法的返回值到页面-->
            <result name="ok">/hello.jsp</result>
        </action>
    </package>
</struts>

web.xml

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

hello.jsp

<%--
  Created by IntelliJ IDEA.
  User: MY
  Date: 2020/4/13
  Time: 14:18
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hello</title>
</head>
<body>
<h1>hello struts</h1>
</body>
</html>

访问路径:http://127.0.0.1/端口号/项目访问路径/hello.action

Struts2执行过程

查看源代码

package org.apache.struts2.dispatcher.ng.filter;

import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.ng.PrepareOperations;

public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
    protected PrepareOperations prepare;
    protected ExecuteOperations execute;
    protected List<Pattern> excludedPatterns = null;

    public StrutsPrepareAndExecuteFilter() {
    }
//过滤器在服务器启动时候创建,创建过滤器时候执行init方法
//加载配置文件(包含自己创建的配置文件和struts2自带配置文件)
//    *struts.xml
//    *web.xml
    public void init(FilterConfig filterConfig) throws ServletException {
        InitOperations init = new InitOperations();
        Dispatcher dispatcher = null;

        try {
            FilterHostConfig config = new FilterHostConfig(filterConfig);
            init.initLogging(config);
            dispatcher = init.initDispatcher(config);
            init.initStaticContentLoader(config, dispatcher);
            this.prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
            this.execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
            this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
            this.postInit(dispatcher, filterConfig);
        } finally {
            if (dispatcher != null) {
                dispatcher.cleanUpAfterInit();
            }

            init.cleanup();
        }

    }

    protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;

        try {
            if (this.excludedPatterns != null && this.prepare.isUrlExcluded(request, this.excludedPatterns)) {
                chain.doFilter(request, response);
            } else {
                this.prepare.setEncodingAndLocale(request, response);
                this.prepare.createActionContext(request, response);
                this.prepare.assignDispatcherToThread();
                request = this.prepare.wrapRequest(request);
                ActionMapping mapping = this.prepare.findActionMapping(request, response, true);
                if (mapping == null) {
                    boolean handled = this.execute.executeStaticResourceRequest(request, response);
                    if (!handled) {
                        chain.doFilter(request, response);
                    }
                } else {
                    this.execute.executeAction(request, response, mapping);
                }
            }
        } finally {
            this.prepare.cleanupRequest(request);
        }

    }

    public void destroy() {
        this.prepare.cleanupDispatcher();
    }
}

Struts2的核心配置文件

1.名称和位置固定的
2.在配置文件中主要三个标签package,action,result

  • package
    类似于代码包,区别不同的action,要配置action,必须首先写package,在package里面才能配置
    • (1)name属性
      • name属性值功能本身没有关系的,在一个配置文件中可以写多个package标签,name属性__不可以相同__
    • (2)extends属性
      • 这个属性值固定的,struts-default
      • 写了这个属性之后,在package里面配置的类具有action功能
    • (3)namespace属性
      • namespace属性值和action标签里面的name属性构成访问路径
  • action
    action标签配置action访问路径
    • action标签属性
      • name属性:namespace属性值和action标签里面的name属性构成访问路径,在package标签里面写多个action标签,但是action的name属性值__不能相同的__
      • class属性:action全路径
      • method属性:在action里面默认执行execute方法,但是在action里面可以写其他的方法,使用method进行配置
  • reslut
    根据action的方法返回值,配置到不同的路径里面
    result标签属性
    • (1)name属性:和方法返回值一样
    • (2)type属性:配置如何到路径中(转发或者重定向),默认为转发

struts2默认常量值

修改struts2默认常量

(1)常用的方式
在struts2.xml中进行配置

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

(2)还有两种方式(了解)
在src下面创建struts.properties,进行修改
在web.xml进行配置

最常用常量
struts.i18n.encoding=UTF-8
(1)表单提交数据到action里面,在action可以获取表单提交数据
(2)表单提交数据有中文,有乱码问题,解决
-post提交直接设置编码
-get提交做编码转换
(3)如果在action获取表单通过post提交中文,中文乱码问题帮解决了,不需要自己处理问题

分模块开发

1.单独写配置文件,把配置文件引入到核心配置文件中

  <include file=""></include>

Action编写方式

1.action编写方式有三种方式
第一种:创建普通类,这个不继承任何类,不实现任何接口
第二种:创建类,实现接口Action

import com.opensymphony.xwork2.Action;
public class UserAction implements Action {
    @Override
    public String execute() throws Exception {
        return null;
    }
}

第三种:创建类,继承类ActionSupport(一般使用)

import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
  @Override
    public String execute() throws Exception {
        return super.execute();
    }
}

访问action的方法

  • 第一种:使用action标签的method属性,在这个属性里面写执行的action方法(action少)
    缺陷:action每个方法都需要配置,如果action里面有多个方法,配置需要很多的action
import com.opensymphony.xwork2.ActionSupport;
//修改
public class HelloAction extends ActionSupport {
    public String add() {
        System.out.println("add...");
        return NONE;
    }
//更新
    public String update() {
        System.out.println("update...");
        return NONE;
    }
}
  • 第二种:使用通配符方法实现(action多)
    name属性值里面的*号
    *匹配任意内容
 <action name="*" class="action.HelloAction" method="{1}"> </action>
  • 第三种:动态访问实现(不用)

错误示例

(1)如果action方法有返回值,在配置文件中没有配置,出现错误

 <result name="not ok">/hello.jsp</result>
 public String execute(){
        return "ok";
    }

报错:HTTP Status 404 - No result defined for action action.HelloAction and result ok
(2)在action里面的方法有返回值,如果有返回值类型必须是__String__
(3)action里面的方法可以没有返回值,没有返回值时候,在result标签不需要配置
1.把方法返回值设置为void

public class HelloAction {
    public void execute() {
    }
}

2.让返回值,返回“none”

import com.opensymphony.xwork2.ActionSupport;
public class HelloAction extends ActionSupport {
    public String execute() {
        return Action.NONE;
    }
}

小案例,结合之前学的hibernate,显示全部地址到前端

dao层

public class AddressDao {
    public List<Address> finAll() {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try {
            //得到sessionFactory
            sessionFactory = HibernateUtils.getSessionFactory();
            //得到session
            session = sessionFactory.getCurrentSession();
            //开启事务
            tx = session.beginTransaction();

            //查询所有记录
            Criteria criteria = session.createCriteria(Address.class);
//			criteria.add(Restrictions.eq(propertyName, value))
            List<Address> list = criteria.list();
            //提交事务
            tx.commit();
            return list;
        } catch (Exception e) {
            tx.rollback();
       
        return null;
    }
}

service层

public class AddressService {
    public List<Address> findAll() {
        AddressDao addressDao = new AddressDao();
        return addressDao.finAll();
    }
}

Action

public class HelloAction extends ActionSupport {
    public String add() {
        System.out.println("add...");
        return NONE;
    }

    public String update() {
        System.out.println("update...");
        return NONE;
    }


    public String list() {
        AddressService addressService = new AddressService();
        List<Address> list = addressService.findAll();
        HttpServletRequest request = ServletActionContext.getRequest();
        request.setAttribute("list", list);
        return "list";
    }
}

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <constant name="struts.i18n.encoding" value="utf-8"/>
    <package name="helloDemo" extends="struts-default" namespace="/">
        <action name="address_*" class="action.HelloAction" method="{1}">
            <result name="list">/list.jsp</result>
        </action>
    </package>
</struts>

结果页面配置

(1)全局结果页面
如果有多个action,方法里面返回值相同,到的页面也是相同的,这个时候可以使用全局结果页面配置

  		<action name="book" class="action.BookAction">
            <result name="success">/hello.jsp</result>
        </action>

        <action name="orders" class="action.OrderAction">
            <result name="success">/hello.jsp</result>
        </action>
 		<global-results>
            <result name="success">/hello.jsp</result>
        </global-results>

        <action name="book" class="action.BookAction">
<!--            <result name="success">/hello.jsp</result>-->
        </action>

        <action name="orders" class="action.OrderAction">
<!--            <result name="success">/hello.jsp</result>-->
        </action>

(2)局部结果页面

 		<action name="book" class="action.BookAction">
            <result name="success">/hello.jsp</result>
        </action>

如果全局和局部都配置了,以局部为准
(3)result标签type属性
type:如何到路径里面(转发还是重定向)

  • type属性值
    • dispatcher,默认值,转发(type=“dispatcher”)
    • redirect,重定向(type=“redirect”)
    • chain:转发到action,一般不用,缓存问题
    • redirectAction:重定向到action

在action获取表单提交数据

(1)使用ActionContext类获取

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>form01</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/form01.action" method="post">
    username:<input type="text" name="username"/>
    <br/>
    password:<input type="text" name="password"/>
    <br/>
    address:<input type="text" name="address"/>
    <br/>
    <input type="submit" value="提交">
</form>
</body>
</html>
 <package name="demo02" extends="struts-default" namespace="/">
        <action name="form01" class="action.form01Action" method="execute">
        </action>
    </package>
public class form01Action extends ActionSupport {
    @Override
    public String execute() throws Exception {
        ActionContext actionContext = ActionContext.getContext();
        Map map = actionContext.getParameters();
        Set<String> keys = map.keySet();
        for (String key : keys) {
            Object[] obj = (Object[]) map.get(key);
            System.out.println(Arrays.toString(obj));
        }
        return NONE;
    }
}

结果

(2)使用ServletActionContext类获取

public String execute() throws Exception {
        HttpServletRequest httpServletRequest = ServletActionContext.getRequest();
        String username = httpServletRequest.getParameter("username");
        String password = httpServletRequest.getParameter("password");
        String address = httpServletRequest.getParameter("address");
        System.out.println(username + password + address);
        return NONE;
    }

(3)使用接口注入方式获取

public class form01Action extends ActionSupport implements ServletRequestAware {
    private HttpServletRequest request;

    @Override
    public String execute() throws Exception {
        request.getParameter("username");
        request.getParameter("password");
        request.getParameter("address");
        return NONE;
    }

    @Override
    public void setServletRequest(HttpServletRequest httpServletRequest) {
        this.request = httpServletRequest;
    }
}

在action操作域对象

request,session,servletContext
使用ServletActionContext类操作

//        request域对象
        HttpServletRequest request = ServletActionContext.getRequest();
        request.setAttribute("req", "reqValue");
//       session域对象
        HttpSession session = request.getSession();
        session.setAttribute("sess", "sessValue");
//        ServletContext域对象
        ServletContext context = ServletActionContext.getServletContext();
        context.setAttribute("context", "contextValue");

struts封装获取表单数据方式

(1)属性封装
1.在action员工变量位置定义变量,变量名称和表单输入项的name属性值__一样__
2.生成变量的set方法

public class form01Action extends ActionSupport {
    private String username;
    private String password;
    private String address;

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(username+password+address);
        return NONE;
    }
}

(2)模型驱动封装
1.使用模型驱动方法,可以直接把表单数据封装到实体类对象里面
2.实现步骤

  • action实现接口ModelDriven
  • 实现接口里面的方法getModel方法
  • 在action里面创建实体类对象
public class form01Action extends ActionSupport implements ModelDriven<loginUser> {
   private loginUser user = new loginUser();

   @Override
   public String execute() throws Exception {
       System.out.println(user.toString());
       return NONE;
   }

   @Override
   public loginUser getModel() {
       return user;
   }
}

在一个action中,获取表单数据可以属性封装,使用模型封装,不能同时使用属性封装和模型驱动封装获取同一个表单数据,如果同时使用,只会执行模型驱动
(3)表达式封装
1.第一步:在action里面声明实体类
2.第二步:生成实体类变量的set和get方法
3.第三步:在表单输入项的name属性值里面写表达式形式

public class form01Action extends ActionSupport {
    private loginUser loginUser;

    public domain.loginUser getLoginUser() {
        return loginUser;
    }

    public void setLoginUser(domain.loginUser loginUser) {
        this.loginUser = loginUser;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(loginUser.toString());
        return NONE;
    }

}
<form action="${pageContext.request.contextPath}/form01.action" method="post">
    username:<input type="text" name="loginUser.username"/>
    <br/>
    password:<input type="text" name="loginUser.password"/>
    <br/>
    address:<input type="text" name="loginUser.address"/>
    <br/>
    <input type="submit" value="提交">

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

1.使用表达式封装和模型驱动封装都可以把数据封装到实体类对象中
2.不同点:

  • 使用模型驱动只能把数据封装到一个实体类对象里面
  • 使用表达式封装可以把数据封装到不同的实体类对象里面
<form action="${pageContext.request.contextPath}/form01.action" method="post">
    username:<input type="text" name="loginUser.username"/>
    <br/>
    password:<input type="text" name="loginUser.password"/>
    <br/>
    address:<input type="text" name="loginUser.address"/>
    <br/>
    bookName:<input type="text" name="book.name"/>
    <br/>
    <input type="submit" value="提交">
</form>
public class form01Action extends ActionSupport {
    private loginUser loginUser;
    private Book book;

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    public domain.loginUser getLoginUser() {
        return loginUser;
    }

    public void setLoginUser(domain.loginUser loginUser) {
        this.loginUser = loginUser;
    }

    @Override
    public String execute() throws Exception {
        System.out.println(loginUser.toString()+book.getName());
        return NONE;
    }

}

struts2获取数据封装到集合中

(1)List集合

  • 第一步:在action声明List
  • 第二步:生成list变量的get和set方法
  • 第三步:在表单输入项里面写表达式
<form action="${pageContext.request.contextPath}/form01.action" method="post">
    username:<input type="text" name="list[0].username"/>
    <br/>
    password:<input type="text" name="list[0].password"/>
    <br/>
    address:<input type="text" name="list[0].address"/>
    <br/>
    username:<input type="text" name="list[1].username"/>
    <br/>
    password:<input type="text" name="list[1].password"/>
    <br/>
    address:<input type="text" name="list[1].address"/>
    <br/>
    <input type="submit" value="提交">
</form>
private List<loginUser> list;

    public List<loginUser> getList() {
        return list;
    }

    public void setList(List<loginUser> list) {
        this.list = list;
    }

(2)map集合

<form action="${pageContext.request.contextPath}/form01.action" method="post">
    username:<input type="text" name="map['one'].username"/>
    <br/>
    password:<input type="text" name="map['one'].password"/>
    <br/>
    address:<input type="text" name="map['one'].address"/>
    <br/>
    username:<input type="text" name="map['two'].username"/>
    <br/>
    password:<input type="text" name="map['two'].password"/>
    <br/>
    address:<input type="text" name="map['two'].address"/>
    <br/>
    <input type="submit" value="提交">
public class form01Action extends ActionSupport {
    private Map<String,loginUser> map;

    public Map<String, loginUser> getMap() {
        return map;
    }

    public void setMap(Map<String, loginUser> map) {
        this.map = map;
    }

小案例:添加地址结合hibernate框架

struts的核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   
    <package name="helloDemo" extends="struts-default" namespace="/">

        <action name="address_list" class="action.formAction" method="list">
            <result name="success">/list.jsp</result>
        </action>
        <action name="address_add" class="action.formAction" method="execute">
            <result name="success">/add.jsp</result>
        </action>
        <action name="address_addToList" class="action.formAction" method="add_ToList">
            <result name="success" type="redirect">/address_list</result>
        </action>
    </package>
</struts>

添加城市的表单页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>add</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/address_addToList.action" method="post">
    城市名称:<input type="text" name="city_name">
    城市描述:<input type="text" name="city_description">
    <input type="submit" value="提交">
</form>
</body>
</html>

处理操作的action

package action;


import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import domain.Address;
import org.apache.struts2.ServletActionContext;
import service.AddressService;

import javax.servlet.http.HttpServletRequest;
import java.util.List;


public class formAction extends ActionSupport implements ModelDriven<Address> {
    private Address address = new Address();

    public String list() {
        AddressService addressService = new AddressService();
        HttpServletRequest request = ServletActionContext.getRequest();
        List<Address> list = addressService.findAll();
        request.setAttribute("list", list);
        return "success";
    }

    public String add_ToList() {
        AddressService addressService = new AddressService();
        addressService.add(address);
        return SUCCESS;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    @Override
    public Address getModel() {
        return address;
    }
}

service层(需要的一些功能)

package service;

import dao.AddressDao;
import domain.Address;

import java.util.List;

public class AddressService {
    public List<Address> findAll() {
        AddressDao addressDao = new AddressDao();
        return addressDao.finAll();
    }

    public void add(Address address) {
        AddressDao addressDao = new AddressDao();
        addressDao.add(address);
    }
}

dao层(操作数据库的原子操作)

import java.util.List;

public class AddressDao {
    public List<Address> finAll() {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try {
            //得到sessionFactory
            sessionFactory = HibernateUtils.getSessionFactory();
            //得到session
            session = sessionFactory.getCurrentSession();
            //开启事务
            tx = session.beginTransaction();

            //查询所有记录
            Criteria criteria = session.createCriteria(Address.class);
//			criteria.add(Restrictions.eq(propertyName, value))
            List<Address> list = criteria.list();
            //提交事务
            tx.commit();
            return list;
        } catch (Exception e) {
            tx.rollback();
        }
        return null;
    }
    public void  add(Address address) {
        SessionFactory sessionFactory = null;
        Session session = null;
        Transaction tx = null;
        try {
            //得到sessionFactory
            sessionFactory = HibernateUtils.getSessionFactory();
            //得到session
            session = sessionFactory.getCurrentSession();
            //开启事务
            tx = session.beginTransaction();
            session.save(address);
            //提交事务
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        }
    }
}

显示全部地址的页面

<%--
  Created by IntelliJ IDEA.
  User: MY
  Date: 2020/4/15
  Time: 19:21
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>list</title>
</head>
<body>
<c:if test="${!empty(list)}">
    <table border="1px">
        <td>编号</td>
        <td>城市名字</td>
        <td>城市简介</td>
        </th>
        <c:forEach items="${list}" var="list">
            <tr>
                <td>${list.city_id}</td>
                <td>${list.city_name}</td>
                <td>${list.city_description}</td>
            </tr>
        </c:forEach>
    </table>
</c:if>
</body>
</html>

值栈

  • 之前在web阶段,在servlet里面进行操作,把数据放到域对象里面,在页面中使用el表达式获取到,域对象在一定范围内,存值和取值
  • 在struts2里面提供本身一种存储机制,类似于域对象,是值栈,可以存值和取值
    • 在action里面把数据放到值栈里面, 在页面中获取到值栈数据
  • servlet和action区别
    • Servlet:默认在第一次访问时候创建,创建一次,单实例对象
    • Action:访问时候创建, 每次访问action时候,都会创建action对象,创建多次,多实例对象
  • 值栈存储位置
    • 每次访问action时候,都会创建action对象
    • 在每个action对象里面都会有一个值栈对象
获取值栈对象
  • 获取值栈对象有多种方式
    • 常用:AtionContext类里面的方法得到值栈对象
值栈的内部结构

栈:后进先出
第一部分__root__,结构式list集合,一般操作都是root里面数据
第二部分__context__,结构map集合

向值栈放数据

(1)s:debug标签

  • 使用这个标签可以查看值栈结构和存储值
  • 访问action,执行action的方法有返回值,配置返回值到jsp页面中,在jsp页面中使用这个标签(因为值栈在action中创建)

    在页面中显示[Debug],点击超链接看到值栈结构
  • 在action没有任何操作,栈顶元素就是action引用,action对象里面有值栈对象,值栈对象里面有action引用
    (2)向值栈中放数据
  • 第一种:获取值栈对象,调用值栈对象里面的set方法
   public String getValueStack() {
        ActionContext actionContext = ActionContext.getContext();
        ValueStack valueStack = actionContext.getValueStack();
        valueStack.set("username","张三");
        return SUCCESS;
    }

  • 第二种:获取值栈对象,调用值栈对象里面的push方法
  public String getValueStack() {
        ActionContext actionContext = ActionContext.getContext();
        ValueStack valueStack = actionContext.getValueStack();
        valueStack.set("username","张三");
        valueStack.push("李四");
        return SUCCESS;
    }

  • 第三种:在action定义变量,生成定义变量,生成变量的get方法
private String name;

    public String  getName() {
        return this.name;
    }

    public String findValueStack() {
        name="张三";
        return SUCCESS;
    }

向值栈放对象

1.第一步:定义对象
2.第二步:生成变量的get方法
3.第三步:在执行的方法里面设置对象的值

 private Address address = new Address();
 public Address getAddress() {
        return address;
    }

    public String findValueStack() {
       address.setCity_name("南通");
       address.setCity_description("美女很多。。");
        return SUCCESS;
    }
向值栈放list对象

1.第一步:定义list集合变量
2.第二步:生成变量的get方法
3.第三步:在执行的方法里面向list集合设置值

private List<Address> list = new ArrayList<Address>();

    public List<Address> getList() {
        return list;
    }

    public String findValueStack() {
        Address address=new Address();
        address.setCity_name("东京");
        address.setCity_description("东京热~~");
        Address address1=new Address();
        address1.setCity_name("墨西哥");
        address1.setCity_description("墨西哥黑帮");
        list.add(address);
        list.add(address1);
        return SUCCESS;
    }
从值栈获取数据

使用struts2的标签+ognl表达式获取值栈数据

<s:property value=""></s:property>
  • 获取字符串
<s:property value="username"/>
  • 获取对象
<s:property value="address.city_name"/>
<s:property value="address.city_description"/>
  • 获取list集合
<s:property value="list[0].city_description"/>
<s:property value="list[0].city_name"/>
<s:iterator value="list">
    <s:property value="city_description"/>
    <s:property value="city_name"/>
</s:iterator>
<s:iterator value="list" var="address">
    <s:property value="#address.city_description"/>
    <s:property value="#address.city_name"/>
</s:iterator>
  • 其他操作

(1)使用set方法向值栈放数据,获取

<s:property value="username"/>

(2)使用push方法向值栈放数据,获取

<s:property value="[0].top"/>
el表达式为什么也可以获取值栈数据?
<c:forEach items="${list}" var="address">
    ${address.city_name}
    ${address.city_description}
    <br/>
</c:forEach>
  1. EL表达式获取值栈数据
    2.向域对象里面放值使用setAttribute方法,获取值使用getSttribute方法
    3.底层增强request对象里面的方法getAttribute方法
    (1)首先从request域获取值,如果获取到,直接返回
    (2)如果从request域获取不到值,到值栈中把值获取出来,把值放到域对象里面
public class StrutsRequestWrapper extends HttpServletRequestWrapper {
.
.
.
    public Object getAttribute(String key) {}
    .
    .
    .
OGNL的#,%作用

在值栈中获取request域中数据

  HttpServletRequest request=ServletActionContext.getRequest();
        request.setAttribute("req","hello word");
<s:property value="#request.req"/>

在struts2表单标签中显示request域数据

<s:textfield name="username" value="%{#request.req}"> </s:textfield>

Struts2拦截器概述

1.struts2是框架,封装了很多的功能,struts2里面封装的功能都是在拦截器里面
2.struts2里面封装了很多的功能,有很多拦截器,不是每次这些拦截器都执行,每次执行默认的拦截器
3.struts2里面默认拦截器位置

 <interceptor-stack name="defaultStack">
                <interceptor-ref name="exception"/>
                <interceptor-ref name="alias"/>
                <interceptor-ref name="servletConfig"/>
                <interceptor-ref name="i18n"/>
                <interceptor-ref name="prepare"/>
                <interceptor-ref name="chain"/>
                <interceptor-ref name="scopedModelDriven"/>
                <interceptor-ref name="modelDriven"/>
                <interceptor-ref name="fileUpload"/>
                <interceptor-ref name="checkbox"/>
                <interceptor-ref name="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params">
                ...

4.拦截器在什么时候执行?
(1)在action对象创建之后,action的方法执行之前

拦截器底层原理

  • AOP思想
    AOP是面向切面编程。如果要扩展功能,不通过修改源代码方式扩展功能
  • 责任链模式
    (1)在java中有很多的设计模式
    (2)责任链模式和过滤链很相似的
    过滤链:一个请求可以有多个过滤器进行过滤,每个过滤器只有放行才能到下一个过滤器

    责任链模式:要执行多个操作,有添加,修改,删除三个操作。首先执行添加操作,添加操作执行之后做类似于放行的操作,修改操作执行之后做类似放行操作,执行删除操作
aop思想和责任链模式如何应用到拦截器里面

(1)文字描述:

  • 拦截器在action对象创建之后,action的方法执行之前
  • 在action方法执行之前只执行默认拦截器,执行过程使用aop思想,在action里面没有直接调用拦截器的方法,使用配置文件方式进行操作
  • 在执行拦截器时候,执行很多的拦截器,这个过程使用责任链模式
  • 假如执行三个拦截器,执行拦截器1,执行拦截器1之后做放行操作,执行拦截器2,以此类推,然后执行action的方法
    (2)画图分析:
    n

过滤器和拦截器

(1)过滤器:过滤器理论上可以过滤任意内容,html,jsp,servlet,图片路径
(2)拦截器:拦截器可以拦截action

Servlet和action区别

(1)servlet默认第一次访问时候创建,创建依次,单实例对象
(2)action每次访问时候创建,创建多次,多实例对象

自定义拦截器

(1)在struts2里面有很多的拦截器,这些拦截器是struts2封装的功能,但是在实际开发中,struts2里面的拦截器中没有要使用的功能,这个时候需要自己写拦截器实现

public interface Interceptor extends Serializable {
    void destroy();//销毁

    void init();//初始化操作

    String intercept(ActionInvocation var1) throws Exception;//拦截逻辑的操作
}

(2)开发中,建议使用另外一种方式

  • 写类,继承MethodFilterInterceptor类实现
  • 让action里面的某个方法不进行拦截
    (3)让拦截器和action有关系
  • 不是在action调用拦截器方法,而是通过配置文件方式建立关系
自定义登陆拦截器

第一步 创建类,继承__MethodFilterInterceptor__类

public class LoginInterceptor extends MethodFilterInterceptor {

第二步重写MethodFilterInterceptor类里面的方法写拦截器逻辑

 @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        Object obj = request.getSession().getAttribute("user");
        if (obj != null) {
            return actionInvocation.invoke();
        } else {
            return "error";
        }
    }

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

        <interceptors>
            <interceptor name="logininterceptor" class="interceptor.LoginInterceptor"></interceptor>
        </interceptors>

(2)在具体的action标签里面使用声明的拦截器

 <interceptor-ref name="login"></interceptor-ref>

(3)struts里面执行很多的默认拦截器,但是如果在action里面配置自定义拦截器,问题:默认的拦截器都不会执行了。
解决:把默认拦截器手动使用一次

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

但是登陆的action不能拦截,不然永远不能登陆
解决:在声明的拦截器中添加

 <param name="excludeMethods">login</param>
* 让action里面的某个方法不进行拦截
(3)让拦截器和action有关系
* 不是在action调用拦截器方法,而是通过配置文件方式建立关系
#### 自定义登陆拦截器
第一步 创建类,继承__MethodFilterInterceptor__类
```java
public class LoginInterceptor extends MethodFilterInterceptor {

第二步重写MethodFilterInterceptor类里面的方法写拦截器逻辑

 @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        Object obj = request.getSession().getAttribute("user");
        if (obj != null) {
            return actionInvocation.invoke();
        } else {
            return "error";
        }
    }

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

        <interceptors>
            <interceptor name="logininterceptor" class="interceptor.LoginInterceptor"></interceptor>
        </interceptors>

(2)在具体的action标签里面使用声明的拦截器

 <interceptor-ref name="login"></interceptor-ref>

(3)struts里面执行很多的默认拦截器,但是如果在action里面配置自定义拦截器,问题:默认的拦截器都不会执行了。
解决:把默认拦截器手动使用一次

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

但是登陆的action不能拦截,不然永远不能登陆
解决:在声明的拦截器中添加

 <param name="excludeMethods">login</param>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小赵OvO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值