精华内容
下载资源
问答
  • 主要介绍了spring boot如何配置请求的入参和出参json数据格式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了Spring中使用LocalDateTime、LocalDate等参数作为入参,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要给大家介绍了关于Spring Boot接收单个String入参的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • oracle存储过程中入参是逗号分隔,并且参数要使用在in过滤语句中查询数据。处理的方法与实现
  • shell编程经常会遇到参数个数不定的这种情况,这种情况怎么处理呢?shift就要闪亮登场了
  • 主要介绍了MyBatis版本升级导致OffsetDateTime入参解析异常问题复盘,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 官方例子没有sqlserver的,网上也没有找到带出的例子。自己琢磨了一个(基于MFC对话框-vs2017)。想用破解库就下载:http://download.csdn.net/detail/o_yale_o/9829598 相关sql脚本见 readme.txt
  • ReqTool 请求调试工具,格式化入参和出参。。。
  • 本文档详细介绍了,如何使用JDK代理技术动态打印出入及出的类型、名字及值,值得大家学习和借鉴。
  • 关于接口入参问题

    万次阅读 2021-10-11 09:53:35
    为了防止xss,我们使用了 jsoup 的 clean方式处理参数 但这种方式对入参有一定要求,否则将出现类似以下这种情况; 参数:{"coldContNo":"HT-20210927-0002","companyNo":"C002914","customerScore":5.15,...

    防xss攻击的引发的问题

    为了防止xss,我们使用了 jsoup 的 clean方式处理参数 但这种方式对入参有一定要求,否则将出现类似以下这种情况;

    参数:{"coldContNo":"HT-20210927-0002","companyNo":"C002914","customerScore":5.15,"detailList":[{"id":114,"coldContNo":"HT-20210927-0002","item":"商务","itemIndex":"经营年限(年)","proportion":"5%","score":"【1】10<br/>【2】 5<br/>【3】 0","standard":"【1】>5 年<br/>【2】≤5 年 并且≥ 2 年<br/>【3】< 2 年","actualScore":"0","finalScore":"0.0","rater":null,"version":null,"sort":1,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":1,"scoringOptions":"10,5,0","tempWeight":0.05,"tempOption":["10","5","0"]},{"id":115,"coldContNo":"HT-20210927-0002","item":"商务","itemIndex":"注册资本","proportion":"10%","score":"【1】10<br/>【2】 5<br/>【3】 0","standard":"【1】>RMB5百万<br/>【2】≤RMB5百万 并且≥RMB3百万<br/>【3】<RMB3百万","actualScore":"0","finalScore":"0.0","rater":null,"version":null,"sort":2,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":1,"scoringOptions":"10,5,0","tempWeight":0.1,"tempOption":["10","5","0"]},{"id":116,"coldContNo":"HT-20210927-0002","item":"管理","itemIndex":"公司类型","proportion":"5%","score":"【1】10<br/>【2】 5<br/>【3】 0","standard":"【1】上市公司<br/>【2】股份有限公司<br/>【3】其他","actualScore":"0","finalScore":"0.0","rater":null,"version":null,"sort":3,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":1,"scoringOptions":"10,5,0","tempWeight":0.05,"tempOption":["10","5","0"]},{"id":117,"coldContNo":"HT-20210927-0002","item":"管理","itemIndex":"与万科的关系","proportion":"10%","score":"【1】10<br/>【2】 5<br/>【3】 0","standard":"【1】至少2年<br/>【2】至少1年<br/>【3】其他","actualScore":"10","finalScore":1,"rater":null,"version":null,"sort":4,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":0,"scoringOptions":"10,5,0","tempWeight":0.1,"tempOption":["10","5","0"]},{"id":118,"coldContNo":"HT-20210927-0002","item":"财务","itemIndex":"过去支付记录","proportion":"15%","score":"【1】10<br/>【2】 5<br/>【3】 0","standard":"【1】准时付款<br/>【2】超期但得到特殊审批<br/>【3】超期加催收函","actualScore":"5","finalScore":0.75,"rater":null,"version":null,"sort":5,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":0,"scoringOptions":"10,5,0","tempWeight":0.15,"tempOption":["10","5","0"]},{"id":119,"coldContNo":"HT-20210927-0002","item":"财务","itemIndex":"企业征信报告","proportion":"10%","score":"【1】10<br/>【3】 0","standard":"【1】提供<br/>【3】未提供","actualScore":"10","finalScore":1,"rater":null,"version":null,"sort":6,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":0,"scoringOptions":"10,0","tempWeight":0.1,"tempOption":["10","0"]},{"id":120,"coldContNo":"HT-20210927-0002","item":"行业前景","itemIndex":"外部识别","proportion":"10%","score":"【1】10<br/>【2】 5<br/>【3】 0","standard":"【1】生产制造及快销行业等<br/>【2】贸易公司<br/>【3】第三方代理","actualScore":"10","finalScore":1,"rater":null,"version":null,"sort":7,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":0,"scoringOptions":"10,5,0","tempWeight":0.1,"tempOption":["10","5","0"]},{"id":121,"coldContNo":"HT-20210927-0002","item":"收入","itemIndex":"估计年收入","proportion":"15%","score":"【1】10<br/>【2】 6<br/>【3】 3","standard":"【1】>RMB1百万<br/>【2】RMB12万<X≤RMB1百万<br/>【3】≤RMB12万","actualScore":"6","finalScore":"0.9","rater":null,"version":null,"sort":8,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":1,"scoringOptions":"10,6,3","tempWeight":0.15,"tempOption":["10","6","3"]},{"id":122,"coldContNo":"HT-20210927-0002","item":"收入","itemIndex":"报价分析","proportion":"20%","score":"【1】10<br/>【2】 6<br/>【3】 3","standard":"【1】EBIT>0<br/>【2】EBITDA>0<br/>【3】GP>0","actualScore":"10","finalScore":"2.0","rater":null,"version":null,"sort":9,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":1,"scoringOptions":"10,6,3","tempWeight":0.2,"tempOption":["10","6","3"]},{"id":123,"coldContNo":"HT-20210927-0002","item":"扣分项","itemIndex":"过去3年的应收相关诉","proportion":"15%","score":"【1】-10<br/>【2】 -6<br/>【3】 -3<br/>【4】 0","standard":"【1】≥5<br/>【2】2≤X<5<br/>【3】1<br/>【4】0","actualScore":"-10","finalScore":-1.5,"rater":null,"version":null,"sort":10,"isDel":0,"createTime":null,"createUser":null,"updateTime":null,"updateUser":null,"editable":0,"scoringOptions":"-10,-6,-3,0","tempWeight":0.15,"tempOption":["-10","-6","-3","0"]}]}

    当接口对象接收这份入参时,detailList 会发生条目缺失,明明10条后台对象属性接收数据变成了9条 ,翻看源码发现 代码里写了个 XssHttpServletRequestWrapper 里面会把入参用 jsoup的clean 策略处理;jsoup 的clean 会把参数变成 jsoup封装的Document 对象 问题就来了,上面参数中的 < (小于符号) 会被当成 html 标签进行解析 例如 <xxx  会被当成 一个html 标签 ,但是 也发现如果当< 后面加个空格,就不会被解析成标签  例如 < xxx ;

    展开全文
  • 调用存储过程入参为二维数组的批量插入 出参为自定义对象(二维数组), 需要注意里边的数据库连接啊
  • 数据库mysql存储中的入参出参理解

    千次阅读 2021-01-27 10:37:40
    有些小伙伴看到我们标题中的入参形参不知道是什么意思,其实也不难理解。我们把出参和入参看成输入和输出的意思就可以了。想必这样说大家就理解其中的意思,至于入参和出参如何表示,我们一起往下进行详细的学习。...

    ec08230349c0477b047bc9bfdcbe518c.png

    在使用语句的时候,不可避免的要考虑参数的问题,而参数又是用来辅助变量的。有些小伙伴看到我们标题中的入参形参不知道是什么意思,其实也不难理解。我们把出参和入参看成输入和输出的意思就可以了。想必这样说大家就理解其中的意思,至于入参和出参如何表示,我们一起往下进行详细的学习。

    入参出参

    语法: in|out|inout 参数名 数据类型 , ...

    in 定义出参; out 定义入参; inout 定义出参和入参。

    出参in

    使用出参in时,就是需要我们传入参数,在这里可以对参入的参数加以改变。简单来说in只负责传入参数到存储过程中,类似Java中的形参。delimiter //

    create procedure val_in(in val_name varchar(32))

    begin

    # 使用用户变量出参(为用户变量赋参数值)

    set @val_name1 = val_name;

    end //

    # 调用函数

    call val_in('DK') //

    # 查询该用户变量

    select @val_name1 //

    入参out

    在使用out时,需要传入一个参数。而这个参数相当于是返回值,可以通过调用、接收来获取这个参数的内容。简单来说out只负责作返回值。delimiter //

    # 创建一个入参和出参的存储过程

    create procedure val_out(in val_id int,out val_name varchar(32))

    begin

    # 传入参数val_id查询员工返回name值(查询出的name值用出参接收并返回)

    select name into val_name from employee where id = val_id;

    end //

    # 调用函数传入参数并声明传入一个用户变量

    call val_out(1, @n) //

    # 查询用户变量

    select @n //

    入参出参inout

    inout关键字,就是把in和out合并成了一个关键字使用。被关键字修饰的参数既可以出参也可以入参。delimiter //

    create procedure val_inout(in val_name varchar(32), inout val_age int)

    begin

    # 声明一个a变量

    declare a int;

    # 将传入的参数赋值给a变量

    set a = val_age;

    # 通过name查询age并返回val_age

    select age into val_age from employee where name = val_name;

    # 将传入的a与-和查询age结果字符串做拼接并查询出来(concat——拼接字符串)

    select concat(a, '-', val_age);

    end //

    # 声明一个用户变量并赋予参数为40

    set @ages = '40' //

    # 调用函数并传入参数值

    call val_inout('Ziph', @ages) //

    # 执行结果

    # 40-18

    以上就是我们对于数据库mysql存储过程中参数的一些介绍,in是输入,out是输出,各自对应它们的中文意思,这样记忆就不会使用出错了。

    展开全文
  • AOP实现日志入参出参打印

    千次阅读 2020-07-23 15:09:41
    减少代码中接口的入参出参打印,减少工作量,保持打印风格一致性。 效果展示 [2020-07-23 14:50:09 INFO http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - top.gmaya....

    描述

    减少代码中接口的入参出参打印,减少工作量,保持打印风格一致性。

    效果展示

    [2020-07-23 14:50:09 INFO  http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - top.gmaya.gmayaserviceadminimpl.system.controller.UserController.add()【新增登录信息】:===================
    [2020-07-23 14:50:09 INFO  http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - top.gmaya.gmayaserviceadminimpl.system.controller.UserController.add()【方法请求参数为】:{"data":{"id":1,"name":"1212"},"token":"11111111"}
    [2020-07-23 14:50:09 INFO  http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - top.gmaya.gmayaserviceadminimpl.system.controller.UserController.add()【方法返回结果为】:{"msg":"success","code":0,"data":1}
    [2020-07-23 14:50:09 INFO  http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - top.gmaya.gmayaserviceadminimpl.system.controller.UserController.add()【方法执行时长为】:208 ms
    [2020-07-23 14:50:09 INFO  http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - {"method":"POST","createTime":1595487009526,"ip":"192.168.21.1","methodName":"add","className":"top.gmaya.gmayaserviceadminimpl.system.controller.UserController","createUser":"GMaya","time":208,"operation":"新增登录信息","url":"http://localhost:9001/user/add"}
    [2020-07-23 14:50:09 INFO  http-nio-9001-exec-2] t.g.gmayaserviceadminimpl.system.aspect.LogAspect - top.gmaya.gmayaserviceadminimpl.system.controller.UserController.add()【保存数据库成功!】:===================
    
    

    实现

    思路:
    一个注解类, 一个切面类。使用环绕通知,将入参出参打印出来,可以根据实际情况,有些接口只需要打印即可,有些需要打印并保存到数据库。

    注解类GmLog

    package top.gmaya.gmayaserviceadminimpl.system.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * 自定义日志注解
     * @author GMaya
     * @dateTime 2020/7/23 10:29
     * 1.运行时 使用使用注解
     * 2.注解作用于方法上
     * 3.注解是否将包含在 JavaDoc 中
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD })
    @Documented
    public @interface GmLog {
    
        // 打印日志描述信息
        String value() default "";
        // TODO 是否保存到数据库
        boolean isSave() default false;
    }
    
    

    切面类LogAspect
    里面有两种方式,一个是拦截添加注解的方法(适合新建项目,写接口的时候加上注解),一个是指定的包名下面所有的接口(适合现有项目,不必要改变其余代码)

    
    package top.gmaya.gmayaserviceadminimpl.system.aspect;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import top.gmaya.gmayaserviceadminimpl.system.annotation.GmLog;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    import java.net.InetAddress;
    import java.util.Date;
    
    /**
     * 用于记录注解上接口的入参出参,统一规范。
     */
    @Aspect
    @Component
    @Slf4j
    public class LogAspect {
    
        /**
         * 方法一: 不需要自定义注解, 直接拦截所有controller的请求。全部打印
         * 定义切入点表达式
         * 第一个*号:表示返回类型, *号表示所有的类型。
         * 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包.
         * 第二个*号:表示类名,*号表示所有的类。
         * *(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数
         */
        @Pointcut("execution(public * top.gmaya.gmayaserviceadminimpl.system.controller..*.*(..))")
        public void privilege() {
        }
    
        /**
         * 方法二:拦截该注解标识的方法
         */
        @Pointcut("@annotation(top.gmaya.gmayaserviceadminimpl.system.annotation.GmLog)")
        public void logPointCut() {
        }
    
        /**
         * 环绕通知
         * @param pjd
         * @return
         * @throws Throwable
         */
        //    @Around("privilege()") // 第一种方式
        @Around("logPointCut()") // 第二种方式
        public Object arount(ProceedingJoinPoint pjd) throws Throwable {
            long startTime = System.currentTimeMillis();
    
            // 类名
            String className = pjd.getTarget().getClass().getName();
            // 获取执行的方法名称
            String methodName = pjd.getSignature().getName();
    
            // 1. 如果是使用的第二种方式,则判断该方法是否使用了改注解
            // 2. 如果是使用的第一种方式,直接注释即可。
            GmLog gmLog = this.getAnnotationLog(pjd);
            if (gmLog != null) {
                String value = gmLog.value();
                log.info("{}.{}()【{}】:===================", className, methodName, value);
            }
    
            Object[] args = pjd.getArgs();
            try {
                String params = JSON.toJSONString(args[0]);
                //打印请求参数参数
                log.info("{}.{}()【方法请求参数为】:{}", className, methodName, params);
            } catch (Exception e) {
                log.info("{}.{}()【方法请求参数打印失败】:{}", className, methodName, e);
            }
            // 执行目标方法
            Object result = pjd.proceed();
            // 打印返回结果
            try {
                String s = JSON.toJSONString(result);
                log.info("{}.{}()【方法返回结果为】:{}", className, methodName, s);
            } catch (Exception e) {
                log.info("{}.{}()【方法返回结果打印失败】:{}", className, methodName, e);
            }
            // 获取执行完的时间
            long time = System.currentTimeMillis() - startTime;
            log.info("{}.{}()【方法执行时长为】:{}{}", className, methodName, time, " ms");
            // 如果使用第一种方式,把这里注释掉
            // TODO 这里可以考虑新加一个异步方法,保存信息到数据库,入参,出参,请求人,请求时间,ip信息等,如果有异常,还有异常信息。
            if (gmLog != null) {
                boolean save = gmLog.isSave();
                if (save) {
                    String val = gmLog.value();
                    // 调用异步保存数据库方法
                    int i = this.saveLog(pjd, time, val);
                    if (i > 0) {
                        // 判断插入条数,大于0,保存成功。
                        log.info("{}.{}()【{}】:===================", className, methodName, "保存数据库成功!");
                    }
                }
            }
            return result;
        }
    
        /**
         * 是否存在注解,如果存在就获取
         * @param joinPoint
         * @return
         */
        private GmLog getAnnotationLog(JoinPoint joinPoint) {
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            if (method != null) {
                return method.getAnnotation(GmLog.class);
            }
            return null;
        }
    
        /**
         * 保存到数据库
         * @param joinPoint
         * @param time 方法执行时间 单位ms
         * @param val 方法请求描述
         * @return
         */
        private int saveLog(JoinPoint joinPoint, long time, String val) {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            JSONObject jsonObject = new JSONObject();
            // ip地址
            String hostAddress = "";
            try {
                hostAddress = InetAddress.getLocalHost().getHostAddress();
            } catch (Exception e) {
                log.error("获取ip失败");
            }
            // redis.getUserId(); 结合实际情况 获取当前登录人信息
            // 类名
            String className = joinPoint.getTarget().getClass().getName();
            // 获取执行的方法名称
            String methodName = joinPoint.getSignature().getName();
            String url = request.getRequestURL().toString();
            String method = request.getMethod();
            jsonObject.put("ip", hostAddress);
            jsonObject.put("className", className);
            jsonObject.put("methodName", methodName);
            jsonObject.put("url", url);
            // 执行时间
            jsonObject.put("time", time);
            jsonObject.put("createTime", new Date());
            jsonObject.put("createUser", "GMaya");
            // 操作描述
            jsonObject.put("operation", val);
            jsonObject.put("method", method);
            String s = jsonObject.toJSONString();
            // 调用日志service的add方法即可!
            log.info(s);
            return 1;
        }
    
    }
    
    

    controller层接口展示:

        @RequestMapping("add")
        @GmLog(value = "新增登录信息" , isSave = true)
        public R add(@RequestBody F<UserEntity> f) {
            // 登录用户信息
            UserEntity user = this.getUser(f.getToken());
            return R.data(userService.add(f,user));
        }
    

    只需要添加注解即可,以及是否保存到数据库,默认不保存。

    @GmLog(value = "新增登录信息" , isSave = true)
    

    写完,测试一下,完美!

    展开全文
  • 函数入参分析

    千次阅读 2019-06-08 20:46:02
    函数入参分析背景固定参数可变参数总结 背景 一般来说,我们调用一个函数的时候,需要传入对应数据类型和个数的参数,例如调用int sum(int x,int y);我们需要传入两个int类型的数,且只能传入两个int类型的数。如果...

    背景

    一般来说,我们调用一个函数的时候,需要传入对应数据类型和个数的参数,例如调用int sum(int x,int y);我们需要传入两个int类型的数,且只能传入两个int类型的数。如果类型不匹配或者个数不匹配,编译器都会报warning或者error。我们将int x ,int y称作形参,下面就来分析以下参数是怎么传递给被调用函数的。
    备注:
    测试的平台x86_64-redhat-linux

    固定参数

    固定参数指的是,一个函数的形参个数是确定的,如上面举例的int sum(int x,int y); 它的参数个数是2,是一个固定值。还有一种参数个数是可变的,例如printf函数,对于可变参数入参在下一节中分析。
    大部分的课本或者图书上说,函数入参的顺序是从右往左依次压入栈中,由于栈的增长是由高地址向低地址增长,故可以得知越是靠近右边的参数,所处的地址应该是越大的。例如my_printf(char* fmt,int a,int b,int c),入栈的顺序:c->b->a->fmt(指针),地址的大小也是c->b->a->fmt(指针)。
    我写了一个测试程序来验证这个说法,这个测试程序把函数的入参地址打印出来了:

    void my_printf(char* fmt,int a,int b,int c)
    {
    	printf("addr: fmt:%p a:%p b:%p c:%p\n",&fmt,&a,&b,&c);
    }
    
    int main()
    {
    	my_printf("%d",2,3,4);
    	return 0;
    }
    

    运行的结果是:

    addr: fmt:0x7ffcd7e3d978 a:0x7ffcd7e3d974 b:0x7ffcd7e3d970 c:0x7ffcd7e3d96c
    

    从运行的结果看,c的地址最小(0x7ffcd7e3d96c),fmt的地址最大(0x7ffcd7e3d978 ),和大多数的资料上描述不相符。原因实际是:
    函数的入参顺序和编译器有关,编译器决定函数怎么入参,我测试的平台是x86_64-redhat-linux,大多数资料讲的平台是32位平台,所以会有差异。

    下面通过objdump生成汇编代码来分析参数入栈的过程:
    可以看出,main函数仅仅做了写入寄存器的操作
    main函数
    my_printf将寄存器中的参数写入到栈中:
    my_printf汇编代码

    可变参数

    按照我的理解,可变参函数入参应该和正常的函数一样,都会依次将参数压入到栈中,也会存储到寄存器中。为了验证这个想法,所以做了一个实验:
    1)编写测试代码

    int myprintf(int num,...)
    {
        va_list p_args ;
        va_start(p_args,num);
        printf("start addr:%p value:%d\n",p_args,*(int*)p_args);
        printf("num addr:%p\n",&num);
        printhex(&num-3,200);
    }
    int main()
    {
    	myprintf(3,1,2,3);
    	return 0;
    }
    

    2)gdb加载测试代码
    3)查看栈帧信息,可以看到args中只有num,并没有看到后面的入参1,2,3

    (gdb) info frame
    Stack level 0, frame at 0x7fffffffe3d0:
     rip = 0x400698 in myprintf (main.c:20); saved rip 0x40100f
     called by frame at 0x7fffffffe3f0
     source language c.
     Arglist at 0x7fffffffe3c0, args: num=3
     Locals at 0x7fffffffe3c0, Previous frame's sp is 0x7fffffffe3d0
     Saved registers:
      rbp at 0x7fffffffe3c0, rip at 0x7fffffffe3c8
    

    4)查看寄存器,在寄存器中可以看到入参1,2,3

    (gdb) info registers
    rax            0x0      0
    rbx            0x0      0
    rcx            0x3      3
    rdx            0x2      2
    rsi            0x1      1
    rdi            0x3      3
    

    可变参数在gdb上表现不出来,实际也是压入到栈中了
    在这里插入图片描述

    把栈内存打印出来,栈中有参数,但是参数2,3,4和参数1的位置并不是紧邻的,从汇编代码中也可以看出来,以下是栈的内容:
    在这里插入图片描述
    网上的资料和课本上所说的va_list va_arg等,都是在x86平台上,对于x64平台上来说,实现完全不一样。X86平台的va_list是一个char*类型,但是在我的平台上,va_list是一个结构体,从gdb可以看出来,p_args是va_list类型的变量,它有gp_offset,fp_offset,overflow_arg_area,reg_save_area成员。所以x86和x64的参数入参是不一样的,直接套用x86的参数入参会得不到想要的结果:

    (gdb) info locals
    p_args = {{gp_offset = 8, fp_offset = 48, overflow_arg_area = 0x7fffffffe3d0,
        reg_save_area = 0x7fffffffe310}}
    args_val = -134224728
    args_index = 32767
    

    总结

    平台不同,编译器不同会导致入参的顺序不同,课本和资料上所说的,可能和实际情况不相符,所以只能作为参考,具体情况还需要具体分析。通过分析汇编代码,会让你对入参有一个深入的了解。

    展开全文
  • Spring Aop 获取入参和出参 1. 概述 本次,我利用 Spring Aop 的注解方式获取切入点的入参和出参,因为比较简单,所以就直接上代码了。 2. 代码编写 注解类 /** * 日志注解 * * @author Jiantao Yan * @title: ...
  • 在实际的开发需求中,我们会对请求的入参和出参的信息打印,这些我们可以自定义一个注解来完成这些重复的冗余工作,还可以在此基础上进行日志的入表持久化,这样查日志的时候就可以不用再服务器上看了,可以在可视化界面...
  • AOP实现日志打印方法入参出参AOP术语1、通知(Advise)2、连接点(JoinPoint)3、切点(PointCut)4、切面(Aspect)5、引入(Introduction)6、织入(Weaving)自定义接口定义切面 AOP术语 1、通知(Advise) 通知 执行顺序 ...
  • 一般来讲,对一些post请求,我们可以使用@valid+javax.validation.constraints包下注解的方式,优雅把参数验证放在control层的requst中,举例说明如下图:但是此时,如果我们知道可以修改的状态只能为枚举类中存在的...
  • 请求入参校验

    千次阅读 2019-04-22 22:55:35
    请求入参的校验 转载原文地址 1. 依赖 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.4.1.Final</...
  • arthas监控方法的入参出参以及耗时

    千次阅读 2021-02-23 19:48:09
    } 抱怨归抱怨,为了尽快找了短信发送不成功的原因,我想到了老伙伴arthas(经常使用它定位线上问题),使用它可以监控方法的入参和出参,于是我在服务器快速输入了以下命令: # 下载arthas(其实服务器早就有这个...
  • 入参限制常用注解

    千次阅读 2020-02-17 15:10:31
    @NotNull(message = "缺少入参") 2、属性注解 @NotEmpty(message = "不能为空") @Length(max = 1024, message = "长度不能超过1024个字符") @Size(max = 100, message = "个数不能超过100个") @Pattern(regexp = "^\...
  • 方法入参

    千次阅读 2020-02-08 12:07:04
    方法从创建之初就定义了它本身所代表的含义,它代表的是一个或一类行为,所以方法的设计和程序的稳健性是紧密相关的。这本身也对方法的定义有更高的要求...非必需指这个入参可有可无,即方法需要的对象可以通过入参...
  • 我们在使用spring项目的时候,经常使用@Valid来对入参进行校验,比如必须为空,必须不为空,长度多少,是否符合邮件格式等等,同时也可以正则。 如下图所示, @Null(message = "id不能传入",groups = {...
  • 自定义注解+aop完成controller打印入参和出参日志写在前面开始上代码 写在前面 相信大家在开发的时候面对controller层有打印日志的习惯,controller层无需过多代码,基本上包括入参日志打印,调用service层方法,打印...
  • Spring Boot 实现接口统一入参校验

    千次阅读 2020-05-09 18:49:48
      本文示例代码基于Spring Boot 2.2.6、JDK1.8。...1.基本类型参数入参校验及校验异常统一处理接口返回数据: package com.qiwan.validated.controller; import org.hibernate.validator.constraints.Length; imp
  • swagger兼容map入参

    千次阅读 2019-12-20 10:25:50
    @ApiOperation(value = "获取资产", notes = "入参为map,userId必传") public String valuationValue(@ApiJsonObject(name = "RequestModel", value = { @ApiJsonProperty(key = "userId", example = "xsy123",...
  • Log - Log日志入参

    万次阅读 2020-07-22 22:38:59
    选优化代码的方向,方法入参和返回结果日志首当其冲,每个方法都会有这两个日志,一大堆冗余的代码,而且什么样的打印格式都有,非常的杂乱。 `public OrderDTO getOrder(OrderVO orderVO, String name) { log.info...
  • 目录前言前提AOP增强入参和出参 前言 很多时候,我们会需要对方法的入参或者出参进行一些额外的处理,这时候使用AOP可以很好的满足我们的需求。因为AOP的侵入性较低,与业务逻辑的代码耦合度低,并且有较好的可重用...
  • 关于Map入参,出参

    千次阅读 2020-06-03 13:51:07
    现在有很多小伙伴 非常喜欢 用map,jsonObject来接收前端的参数 如下图: @PostMapping(... } 所以,综上所述:我的建议是,能使用bean定义就用bean定义,这样方便维护,而且接手的人很容易知道你代码里面的入参,出参
  • 的高阶应用篇,由于增加了框架级别的入参和出参定义,导致swagger无法识别外部的定义,仅仅识别为控制器方法的定义。如果追根溯源,这个跟swagger也没太大的关系,应该是asp提供的ApiExplorer的问题,毕竟是静态反射...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 229,527
精华内容 91,810
关键字:

入参