struts2笔记

本文深入解析Struts2框架的请求处理流程,包括Action处理请求参数的方式、常量配置方法、访问Servlet API的途径、数据传递机制、拦截器定义与使用、OGNL表达式详解及值栈工作原理,同时还介绍了文件上传下载、类型转换器的自定义方法。

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

首先介绍下Action处理请求参数
    1,属性驱动
        1)基本数据类型字段驱动
            private String username;
            private String password;
            然后提供字段的getter,setter方法
        2)域对象字段驱动
            将上述字段封装成对象
            User user = new User();                     //前端页面提供的属性要与对象字段要一致,user.name
            然后提供对象的getter,setter方法
    2,模型驱动
        实现ModelDriven<User>接口
        User user = new User();
        @Override
            public User getModel() {
                return user;
            }
*********************************************************************************************
再讲讲常量的配置
Struts2常量的配置有3种方式
    1,在struts.xml文件中使用<constant>元素配置常量
           <constant>元素中两个必填的属性,name和value
    2,在struts.properties文件中配置常量,该文件由自己创建
    3,在web.xml文件filter中通过<init-param>元素配置常量
    <init-param>
        <param-name></param-name>
        <param-value></param-value>
    </init-param>
配置文件的加载顺序
    1,default.properties
    2,struts.xml
    3,struts.properties
    4,web.xml
    后加载文件会覆盖前面的文件
***********************************************************************************************
任何action类继承了ActionSupport都要声明serialVersionUID
private static final long serialVersionUID=1L;
***********************************************************************************************
Action访问ServletAPI的三种方式
    1,通过ActionContext类访问
        ActionContext context = ActionContext.getContext();
        context.put("name","王科一");
        context.getApplication().put("name","王科一");
        context.getSession().put("name","王科一");
    2,通过特定接口访问
        通过ActionContext类可以访问ServletAPI,但是无法提供Servlet实例
        实现以下接口,即可访问对应的实例
        ServletRequestAware,实现该接口可以直接访问Web应用的HttpServletRequest实例
        ServletResponseAware,实现该接口可以直接访问Web应用的HttpServletResponse实例
        SessionAware,实现该接口可以直接访问Web应用的HttpSession实例
        ServletContextAware,实现该接口可以直接访问Web应用的ServletContext实例

        HttpServletRequest request;
        @override
        public void setServletRequest(HttpServletRequest request)
        {
            this.request=request;
        }
        然后在execute()方法中使用request对象的方法了,request.setAttribute("name","王科一");
        最后使用EL表达式访问,${requestScope.name}
    3,通过ServletActionContext访问
        上述通过接口访问实例的方法,根本就没有使用Struts2,Struts2自身将上述操作整合后
        通过ServletActionContext就可访问Servlet实例
        ServletActionContext.getRequest().setAttribute("name","王科一");
******************************************************************************************************
struts.xml中action的Result结果类型的配置
数据的传递由两种,一种是请求转发,一种是重定向,在struts2中action也有这两种方式
处理action之间的数据传递有两种,处理页面之间的数据传递有两种
action之间的:chain,redirectAction,
    type属性为chain时,被跳转的action中仍能获取上个页面的值,如request
    type属性为redirectAction时,则不能获取上个页面的值
页面之间的数据传递:dispatcher,redirect
    type属性为dispatcher时,用来转向页面,处理jsp,是默认的类型
    type属性为redirect时,重定向页面,被跳转的页面丢失传递的信息
*****************************************************************************************************
下面讲struts2的拦截器,开发者需要定义拦截器的实现类,并把他们配置在struts.xml中即可
拦截器的定义:
    <interceptor name="拦截器名字" class="拦截器实现类">
        <param name="需要传入参数的名称">传入参数的值</param>
    </interceptor>
拦截器链/栈的定义:
    <interceptors>
        <interceptor name="interceptor1" class="interceptorClass"></interceptor>
        <interceptor name="interceptor2" class="interceptorClass"></interceptor>
        <interceptor-stack name="myStack">
                <interceptor-ref name="interceptor1"></interceptor-ref>
                <interceptor-ref name="interceptor2"></interceptor-ref>
        </interceptor-stack>
    </interceptors>
默认拦截器是指在一个包下默认进行的拦截器,每个包只有一个默认拦截器,该拦截器对包下所有action都有效
默认拦截器的声明:
    <default-interceptor-ref name="myStack"></default-interceptor-ref>
    myStack必须是已有的拦截器链或者普通单个拦截器
struts2默认拦截器栈:
    <default-interceptor-ref name="defaultStack"/>
struts2默认action类:
    <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

自定义拦截器
实现自定义拦截器有两种方式
    1,实现Interceptor接口
    2,继承AbstractInterceptor类,并实现intercept方法,此方式常用
自定义拦截器的使用过程
    1,用户自定义的拦截器类,必须实现Interceptor接口或继承AbstractInterceptor类
    2,需要在struts.xml中定义自定义拦截器
    3,在struts.xml中的action中使用拦截器
最后,在struts.xml中定义的拦截器要放在package最前面,即要放在action前面
******************************************************************************************************
今天讲讲Struts2标签库
struts2标签库的使用需要导入taglib指令
    <%@taglib prefix="s" uri="/struts-tags" %>
下面挑几个常用的标签学习一下:
1,<s:iterator>,遍历标签
    <s:iterator>标签属性:
    属性          默认值                     类型                           描述
    begin        0                         Integer                        迭代数组或集合的起始位置
    end          数组或集合的长度大小         Integer                       迭代数组或集合的结束位置
                 减1,假如step为负则为0
    status       false                      Boolean                       迭代过程中的状态
    step         1                          Integer                       指定每次迭代后索引增加的值
    value        无                         String                        迭代的数组或集合对象
    var          无                         String                        将生成的Iterator设置为page范围的属性
    如果标签中指定了status属性,那么通过该属性可以获取迭代过程中的状态信息,如元素数,当前索引值等
    通过status属性获取状态信息如下:
    方法                                      说明
    st.count                                 返回当前已经遍历的集合元素的个数
    st.first                                 返回当前遍历元素是否为集合的第一个元素
    st.last                                  返回当前遍历元素是否为集合的最后一个元素
    st.index                                 返回遍历元素的当前索引值
    st.even                                  返回当前遍历的元素的索引是否为偶数
    st.odd                                   返回当前遍历的元素的索引是否为奇数
    例子:
    <s:iterator value="#request.student2"  status="st" >
        <tr>
            <td><s:property value="stu_id"/></td>
            <td><s:property value="stu_name"/></td>
            <td><s:property value="stu_sno"/></td>
            <td><s:property value="stu_department"/></td>
            <td><s:property value="stu_hometown"/></td>
            <td><s:property value="stu_mark"/></td>
            <td><s:property value="stu_email"/></td>
            <td><s:property value="stu_tel"/></td>
            <td><s:property value="stu_sex"/></td>
            <td><a href="update.jsp?stu_id=${st.count}">修改</a></td>
        </tr>
    </s:iterator>
    其中,#使用了OGNL表达式,取request中的student2对象进行遍历

2,<s:file>
    <form action="" method="" enctype="multipart/form-data">
        <s:file name="" label="" />
        <s:submit value="上传"/>
        <s:reset value="重置"/>
    </form>
***************************************************************************************************************
下午来讲讲OGNL表达式
OGNL的操作实际上就是围绕着OGNL结构的三个要素而进行的,分别是表达式,根对象,上下文环境
表达式
    表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容
根对象
    OGNL的getValue()方法中的第二个参数就是Root对象,Root可以理解为OGNL的操作对象,
    表达式规定了“”“"做什么",而Root对象则规定了”“"对谁操作"
例子”:
    用java来导航访问
        System.out.println("java方式-"+user.getGroup().getBranch().getBranchId());
    用OGNL表达式访问
        System.out.println(“”"OGNL方式-"+(String)Ognl.getValue("group.branch.branchId"),user);
上下文环境
    设置了Root对象,OGNL可以对Root对象进行取值或写值等操作,Root对象所在环境就是OGNL的上下文环境
    上下文环境规定了OGNL的操作”“"在哪里进行",上下文环境Context是一个Map类型的对象,在表达式中访问Context中的对象
    需要使用#号加上对象名称,即”“"#对象名称"的形式“”
例子:
    user.setUsername("王科一");
    Map context = new HashMap();
    context.put("u",user);
    System.out.println("获取context中数据结果为:"+(String)Ognl.getValue("#u.username",context,user));

使用OGNL访问对象方法和静态方法
    1,使用OGNL访问实例对象方法
       语法: Ognl.getValue("方法名().方法名()",对象名);
       例子:
            System.out.println("username = "+(String)Ognl.getValue("getUsername()",user));
            System.out.println("groupName = "+(String)Ognl.getValue("getGroup().getName()",user));
    2,使用OGNL访问静态方法
       首先需要开启访问类静态方法的支持
            <constant name="struts.ognl.allowStaticAccess" value="true"/>
       Ognl表达式需要配合Struts2标签才可以使用
       语法:
            <s:property value="@全类名@变量名"/>
            <s:property value="@全类名@方法名"/>
        全类名就是类的绝对路径
ognl再补充
    当我们从值栈中取值的时候需要使用ognl,如果是取list集合中的值时,需要在页面中遍历集合
例子
    <s:iterator value="list" var="u">       //使用ognl表达式遍历
        <s:property value="#u.name"/>
    </s:iterator>

    <c:forEach items="${list}" var="u">     //使用el表达式遍历
        ${u.name}
    </c:forEach>

    如果是map集合,则实例如下
    <s:iterator value="map" var="u">       //使用ognl表达式遍历
        <s:property value="#u.value.name"/>
    </s:iterator>

    <c:forEach items="${map}" var="u">     //使用el表达式遍历
        ${u.value.name}
    </c:forEach>

***************************************************************************************************************
值栈
值栈就是OGNL表达式存取数据的地方,struts2为每个请求创建单独的值栈,值栈封装了一次请求所需要的所有数据
值栈可以作为一个数据中转站,用于在前台-后台之间传递数据,最经典的做法就是将Struts2标签与OGNL表达式结合
每个acton类的对象都拥有一个值栈对象,值栈的生命周期随着request的创建而创建,随着request的销毁而销毁
值栈的获取方式
    1,在request中获取值栈
        ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    2,在ActionContext中获取值栈
        ValueStack valueStack = ActionContext.getContext().getValueStack();
值栈的内部结构
    ObjectStack(对象栈):是CompoundRoot类型,用Arraylist定义,Struts2把动作和相关对象压入ObjectStack中,push()
    ContextMap(Map栈):是OgnlContext类型,是个Map集合,Struts2把各种各样的映射关系(一些Map类型的对象)压入ContextMap中,set()
    相关映射具体如下:
        parameters:该Map中包含当前请求的请求参数
        request:该Map中包含当前request对象中的所有属性
        session:该Map中包含当前session对象中的所有属性
        application:该Map中包含当前application对象中的所有属性
        attr:该Map按如下顺序来检索某个属性,request,session,application
struts2引入值栈最主要的目的,就是在页面与action之间进行数据交换,采用以下两种方式交换数据时,struts2会将对象自动存储到valueStack中
    属性驱动:每次请求访问action对象时,action中的属性对象会被自动压入ValueStack中
        <s:property value="p3.name"/><br>
        <s:property value="p3.price"/>
    模型驱动:action如果实现了ModelDriven接口,那么ModelDrivenInterceptor拦截器会生效,会将model对象压入到ValueStack中
    对象存储到ValueStack中后,页面所需的数据可以直接从ValueStack中获取
        <s:property value="model.name"/>
        <s:property value="model.price"/>
    还可以使用el表达式访问值栈中的数据
        ${model.name},${model.price}
取值的规则
    从root栈中获取值栈中的值,即对象栈
        <s:property value="表达式"/>
    从context栈中获取值栈中的值,即Map栈
        <s:property value="#表达式"/>
值栈再详解
    1、取出ValueStack中第一个name属性的值
    借助s:property标签来获取。
    取值栈中的数据:直接写属性名称,获取的就是属性值。不需要使用#号。
    OGNL表达式在获取值栈数据时,默认情况下都是从栈顶逐个对象往下寻找,寻找属性一致的,把属性值取出来。只要找到之后,就不再继续寻找。
    OGNL表达式获取值栈中的数据,只能是根据属性名称获取属性值。
    Name:<s:property value="name"/><br/>
    Age:<s:property value="age"/>

    2,获取指定位置属性值
    使用的OGNL表达式是:[x].name
    x指的是值栈中对象的索引位置。
    Name1:<s:property value="[0].name"/><br/>
    Name2:<s:property value="[1].name"/><br/>

    3,当我们使用s:property标签时,没有使用value属性,获取的是栈顶对象。
    当我们不操作值栈时,默认的栈顶对象是:当前执行的动作类
    <s:property/>

    4,OGNL表达式在OGNL上下文中查找数据时涉及的方法
    不管是在Map中找,还是在值栈中找,对应的方法只有一个。
    ValueStack的对象中的findValue(String expr)方法。参数的含义:是一个OGNL表达式
    ActionContext context = ActionContext.getContext();
    ValueStack vs = context.getValueStack();
    Object o1 = vs.findValue("name");
    out.println("name is "+o1);

    Object o2 = vs.findValue("[1].name");
    out.println("name1 is "+o2);

    Object o3 = vs.findValue("#session.sessionMap3");
    out.println(o3);
    Object o4 = vs.findValue("#application.applicationAttr");
    out.println(o4);
push和set方法
    ValueStack对象使用push()方法和set方法将数据对象放入栈顶
******************************************************************************************************************
struts2的文件上传和下载
要使用struts2进行文件上传,首先要将form表单的enctype属性值设置为multipart/form-date,文件上传还需要<s:file>标签
要放在<s:form>标签中
    <form action="" method="" enctype="multipart/form-data">
        <s:file name="" label="" />
        <s:submit value="上传"/>
        <s:reset value="重置"/>
    </form>
除了要对表单form进行设置,其action类的编写也有相应的规定
    private File xxx;                   //用户上传的文件,xxx要与<s:file>标签的name属性值要一致
    private String xxxFileName;         //上传文件的文件名
    private String xxxContentType;      //上传文件的类型
最后需要在struts.xml中加入文件过滤器拦截fileUpload,其本身已经在struts-default中已经配置好了,使用时需要增加一些参数
    <action name="fileUpload" class="top.kubino1.fileUpload.FileAction">
        <result name="success">/success.jsp</result>
        <interceptor-ref name="defaultStack">
            <!--                限制文件上传最大值为4M-->
            <param name="fileUpload.maximumSize">4194304</param>
            <param name="fileUpload.allowedExtensions">.txt,.doc,.jpg</param>
            <param name="fileUpload.allowedTypes">text/plain,image/jpeg</param>
        </interceptor-ref>
    </action>

文件的下载
    struts.xml中增加action的配置,其代码如下:
        <action name="download" class="top.kubino1.fileUpload.DownLoad">
            <result name="success" type="stream">
                <!--文件类型-->
                <param name="contentType">${contentType}</param>
                <!--指定文件名-->
                <param name="contentDisposition">//这里是分号
                    attachment;filename=${fileName}
                </param>
                <!--输入流-->
                <param name="inputName">downFile</param>
            </result>
        </action>
    action类中代码如下:
        private String fileName;
        public String getFileName()
        {
                return fileName;
        }

        public void setFileName(String fileName) {
            try {
                fileName = new String(fileName.getBytes("iso8859-1"),"utf-8");
            } catch (UnsupportedEncodingException e) {
                System.out.println("编码转换异常"+e);
            }
            this.fileName=fileName;
        }

        public InputStream getDownFile()
        {
            return ServletActionContext.getServletContext().getResourceAsStream("/upload/"+fileName);
        }

        @Override
        public String execute() throws Exception {
            return ActionSupport.SUCCESS;
        }
    只需要在字段fileName的setter方法中进行字符的转换
    jsp页面的代码如下:
        <a href="download.action?fileName=英语.txt" download="英语.txt">下载英语资料</a>
    download属性则要求浏览器直接下载文件,而不是在浏览器中打开,其值表示下载的文件名跟传参的值没有关系
******************************************************************************************************************
struts2的类型转换器
    Struts2在接收表单提交过来的参数时,但表单提交过来的数据统统是字符串,意味着Struts2默认给我们提供了各种类型转换
    在实际开发中,往往还需要自定义类型转化,来完成实际的功能或者补充默认转换所不能实现的需求
局部类型转换器
    1,定义一个DefaultTypeConverter,并重写public Object convertValue(Object value,Class toType)方法
    实例
        public class DateConverter extends DefaultTypeConverter {
            private DateFormat[] formats = new SimpleDateFormat[]{
                    new SimpleDateFormat("yyyy-MM-dd"),
                    new SimpleDateFormat("yyyy/MM/dd"),
                    new SimpleDateFormat("yyyy.MM.dd"),
                    new SimpleDateFormat("yyyy_MM_dd"),
            };
            @Override
            public Object convertValue(Object value, Class toType) {
                System.out.println("经过类型转换器");
                String date = ((String[])value)[0];
                for (int i =0;i<formats.length;i++)
                {
                    try {
                        return formats[i].parse(date);
                    } catch (ParseException e) {
                        continue;
                    }
                }
                return null;
            }
        }
    注意,value是个字符串数组

    2,转换器配置方法有两种:一、局部配置   二、全局配置
        一、局部配置文件 LoginAction-conversion.properties
           birthday=top.kubino1.conversion.DateConverter

        二、全局配置文件 xwork-conversion.properties
           java.util.Date=top.kubino1.conversion.DateConverter
    注意:以上使用ModelDriven接口传递参数,只能配置全局自定义类型转换,不能配置局部类型转换
         当使用属性传递的两种方式传递数据时,自定义全局和局部类型转化都可以使用
******************************************************************************************************************






基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值