精华内容
下载资源
问答
  • 只用Spring注解开发的时候,可以使用@Value搭配@PropertySource注解进行给对象的属性进行赋值。 @Value注解的定义: @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType....

    属性赋值

    只用Spring注解开发的时候,可以使用@Value搭配@PropertySource注解进行给Bean的属性进行赋值。

    @Value

    @Value注解的定义:

    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Value {
    
    	/**
    	 * The actual value expression: for example {@code #{systemProperties.myProp}}.
    	 */
    	String value();
    }
    

    可以看到@Value注解接受的参数只能是字符串,所以使用时参数都需要带上双引号。并且可以在属性,方法,参数等位置上标注。value属性支持以下三种类型:

    1. 基本数据类型,包括String,int,boolean等类型。
    2. SpEL,#{}的形式即表示使用SpEL表达式,一般用于获取环境中其他bean的属性,当使用Elivis运算符“表达式1?:表达式2”,比如#{ “obj.property? :default_value” }形式时,这里的obj是取当前容器中的对象,default_value就是前面的值为空时的默认值。
    3. 在主配置类中通过@PropertySource注解加载配置文件,然后通过${ property : default_value}的形式取配置文件中的值,其中default_value表示前面的值为空时的默认值。

    测试

    1.在添加了Spring依赖的Maven项目中创建以下两个实体类Student类和Teacher类

    public class Teacher {
    	public int id;
    	public String name;
    	
    	public Teacher() {
    		// TODO Auto-generated constructor stub
    	 System.out.println("teacher-----创建");
    	}
    	
    	
    	public Teacher(int id, String name) {
    		super();
    		this.id = id;
    		this.name = name;
    	}	
    //省略getter和setter方法
    }
    
    

    在Student类中使用${}取配置文件的值,#{}取容器中的teacher对象的name属性

    public class Student{
    	
    	@Value("1")
    	private int id;
    	@Value("${student.name}")
    	private String name;
    	@Value("${student.address:北京}")
    	private String address;
    	@Value("#{teacher.name?:'老子'}")
    	private String teacherName;
    	@Override
    	public String toString() {
    		return "Student [id=" + id + ", name=" + name + ", address=" + address + ", teacherName=" + teacherName + "]";
    	}
    //省略getter和setter方法
    }
    

    2.在resources目录下创建一个配置文件person.properties,添加以下值:

    student.name=张三
    person.address=广州市
    

    3.创建配置类,使用@PropertySource注解读取外部配置文件person.properties中的key/value保存到运行的环境变量中。

    @Configuration
    @PropertySource("person.properties")
    public class SpringConfig2 {	
        @Bean
    	public Student student() {
    		return new Student();		
    	}
        @Bean
    	public Teacher teacher() {
    		return new Teacher(2,"老李");
    	}
    }
    

    4.创建测试类进行测试,编写代码获取容器中的id为student的bean和直接获取配置环境的属性值。

    public class IoCTest {
    	@Test
    	public void test() {
    		//获取Spring的IOC容器
    		AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig2.class);
    		//从容器中获取bean
           Student stu = (Student) applicationContext.getBean("student");
           System.out.println(stu);			
    	    //获取环境变量
    		ConfigurableEnvironment environment = applicationContext.getEnvironment();
    		String property = environment.getProperty("person.address");
    		System.out.println(property);
    		//关闭容器
    		applicationContext.close();
    	}
    }
    

    5.测试结果:
    在这里插入图片描述


    拓展阅读:
    SpEL语法

    展开全文
  • 项目中使用配置文件多是取配置文件(applicatoion.yml)的值,使用@Value获取,为了秉持非侵入性的原则,我决定写一套自定义注解,以实现最少的代码量实现业务需求。思路需要实现类似springboot...

    背景

    项目中为了统一管理项目的配置,比如接口地址,操作类别等信息,需要一个统一的配置管理中心,类似nacos。

    我根据项目的需求写了一套分布式配置中心,测试无误后,改为单体应用并耦合到项目中。项目中使用配置文件多是取配置文件(applicatoion.yml)的值,使用@Value获取,为了秉持非侵入性的原则,我决定写一套自定义注解,以实现最少的代码量实现业务需求。

    思路

    需要实现类似springboot @Value注解获取配置文件对应key的值的功能。但区别在于 我是从自己写的自动配置中获取,原理就是数据库中查询所有的配置信息,并放入一个对象applicationConfigContext,同时创建一个bean交给spring托管,同时写了个aop,为被注解的属性赋入applicationConfigContext的对应的值。

    换句话说,自定义的这个注解为类赋值的时间线大概是

    spring bean初始化 —-> 第三方插件初始化 --> 我写的自动配置初始化 ---- 用户调用某个方法,触发aop机制,我通过反射动态改变了触发aop的对象的bean的属性,将值赋值给他。

    难点

    本项目的难点在于如何修改对象的值。看似简单,其实里面的文章很多。

    自动配置代码

    配置映射数据库pojo

    import lombok.AllArgsConstructor;

    import lombok.Builder;

    import lombok.Data;

    import lombok.NoArgsConstructor;

    import java.util.Date;

    /**

    * @Describtion config bean

    * @Author yonyong

    * @Date 2020/7/13 15:43

    * @Version 1.0.0

    **/

    @Data

    @AllArgsConstructor

    @NoArgsConstructor

    @Builder(toBuilder = true)

    public class TblConfig {

    private Integer id;

    /**

    * 配置名称

    */

    private String keyName;

    /**

    * 默认配置值

    */

    private String keyValue;

    /**

    * 分类

    */

    private String keyGroup;

    /**

    * 备注

    */

    private String description;

    /**

    * 创建时间

    */

    private Date insertTime;

    /**

    * 更新时间

    */

    private Date updateTime;

    /**

    * 创建人

    */

    private String creator;

    private Integer start;

    private Integer rows;

    /**

    * 是否是系统自带

    */

    private String type;

    /**

    * 修改人

    */

    private String modifier;

    }

    创建用于防止配置信息的对象容器

    import lombok.AllArgsConstructor;

    import lombok.Builder;

    import lombok.Data;

    import lombok.NoArgsConstructor;

    import java.util.List;

    import java.util.stream.Collectors;

    /**

    * @Describtion config container

    * @Author yonyong

    * @Date 2020/7/13 15:40

    * @Version 1.0.0

    **/

    @Data

    @Builder(toBuilder = true)

    @AllArgsConstructor

    @NoArgsConstructor

    public class ConfigContext {

    /**

    * config key-val map

    */

    private List vals;

    /**

    * env type

    */

    private String group;

    /**

    * get config

    * @param key

    * @return

    */

    public String getValue(String key){

    final List collect = vals.stream()

    .filter(tblConfig -> tblConfig.getKeyName().equals(key))

    .collect(Collectors.toList());

    if (null == collect || collect.size() == 0)

    return null;

    return collect.get(0).getKeyValue();

    }

    }

    创建配置,查询出数据库里配置并创建一个容器bean

    import org.apache.commons.lang3.StringUtils;

    import org.springframework.beans.factory.annotation.Value;

    import org.springframework.beans.factory.config.ConfigurableBeanFactory;

    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.context.annotation.Scope;

    import javax.annotation.Resource;

    import java.util.List;

    /**

    * @Describtion manual auto inject bean

    * @Author yonyong

    * @Date 2020/7/13 15:55

    * @Version 1.0.0

    **/

    @Configuration

    @ConditionalOnClass(ConfigContext.class)

    public class ConfigContextAutoConfig {

    @Value("${config.center.group:DEFAULT_ENV}")

    private String group;

    @Resource

    private TblConfigcenterMapper tblConfigcenterMapper;

    @Bean(name = "applicationConfigContext")

    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)

    @ConditionalOnMissingBean(ConfigContext.class)

    public ConfigContext myConfigContext() {

    ConfigContext configContext = ConfigContext.builder().build();

    //set group

    if (StringUtils.isNotBlank(group))

    group = "DEFAULT_ENV";

    //set vals

    TblConfig tblConfig = TblConfig.builder().keyGroup(group).build();

    final List tblConfigs = tblConfigcenterMapper.selectByExample(tblConfig);

    configContext = configContext.toBuilder()

    .vals(tblConfigs)

    .group(group)

    .build();

    return configContext;

    }

    }

    AOP相关代码

    创建自定义注解

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    /**

    * @Author yonyong

    * @Description //配置

    * @Date 2020/7/17 11:20

    * @Param

    * @return

    **/

    @Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface MyConfig {

    /**

    * 如果此value为空,修改值为获取当前group,不为空正常获取配置文件中指定key的val

    * @return

    */

    String value() default "";

    Class> clazz() default MyConfig.class;

    }

    创建aop业务功能

    import lombok.extern.slf4j.Slf4j;

    import org.apache.commons.lang3.StringUtils;

    import org.aspectj.lang.JoinPoint;

    import org.aspectj.lang.annotation.Aspect;

    import org.aspectj.lang.annotation.Before;

    import org.aspectj.lang.annotation.Pointcut;

    import org.aspectj.lang.reflect.MethodSignature;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Component;

    import java.lang.reflect.Field;

    import java.lang.reflect.InvocationTargetException;

    import java.lang.reflect.Method;

    import java.util.Date;

    /**

    * @Describtion config service aop

    * @Author yonyong

    * @Date 2020/7/17 11:21

    * @Version 1.0.0

    **/

    @Aspect

    @Component

    @Slf4j

    public class SystemConfigAop {

    @Autowired

    ConfigContext applicationConfigContext;

    @Autowired

    MySpringContext mySpringContext;

    @Pointcut("@annotation(com.ai.api.config.configcenter.aop.MyConfig)")

    public void pointcut(){}

    @Before("pointcut()")

    public void before(JoinPoint joinPoint){

    final MethodSignature signature = (MethodSignature) joinPoint.getSignature();

    Method method = signature.getMethod();

    MyConfig myConfig = method.getAnnotation(MyConfig.class);

    Class> clazz = myConfig.clazz();

    final Field[] declaredFields = clazz.getDeclaredFields();

    Object bean = mySpringContext.getBean(clazz);

    for (Field declaredField : declaredFields) {

    final MyConfig annotation = declaredField.getAnnotation(MyConfig.class);

    if (null != annotation && StringUtils.isNotBlank(annotation.value())){

    log.info(annotation.value());

    String val = getVal(annotation.value());

    try {

    // setFieldData(declaredField,clazz.newInstance(),val);

    // setFieldData(declaredField,bean,val);

    buildMethod(clazz,bean,declaredField,val);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    // mySpringContext.refresh(bean.getClass());

    }

    private void setFieldData(Field field, Object bean, String data) throws Exception {

    // 注意这里要设置权限为true

    field.setAccessible(true);

    Class> type = field.getType();

    if (type.equals(String.class)) {

    field.set(bean, data);

    } else if (type.equals(Integer.class)) {

    field.set(bean, Integer.valueOf(data));

    } else if (type.equals(Long.class)) {

    field.set(bean, Long.valueOf(data));

    } else if (type.equals(Double.class)) {

    field.set(bean, Double.valueOf(data));

    } else if (type.equals(Short.class)) {

    field.set(bean, Short.valueOf(data));

    } else if (type.equals(Byte.class)) {

    field.set(bean, Byte.valueOf(data));

    } else if (type.equals(Boolean.class)) {

    field.set(bean, Boolean.valueOf(data));

    } else if (type.equals(Date.class)) {

    field.set(bean, new Date(Long.valueOf(data)));

    }

    }

    private String getVal(String key){

    if (StringUtils.isNotBlank(key)){

    return applicationConfigContext.getValue(key);

    }else {

    return applicationConfigContext.getGroup();

    }

    }

    private void buildMethod(Class> clz ,Object obj,Field field,String propertiedValue) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    // 获取属性的名字

    String name = field.getName();

    // 将属性的首字符大写, 构造get,set方法

    name = name.substring(0, 1).toUpperCase() + name.substring(1);

    // 获取属性的类型

    String type = field.getGenericType().toString();

    // 如果type是类类型,则前面包含"class ",后面跟类名

    // String 类型

    if (type.equals("class java.lang.String")) {

    Method m = clz.getMethod("set" + name, String.class);

    // invoke方法传递实例对象,因为要对实例处理,而不是类

    m.invoke(obj, propertiedValue);

    }

    // int Integer类型

    if (type.equals("class java.lang.Integer")) {

    Method m = clz.getMethod("set" + name, Integer.class);

    m.invoke(obj, Integer.parseInt(propertiedValue));

    }

    if (type.equals("int")) {

    Method m = clz.getMethod("set" + name, int.class);

    m.invoke(obj, (int) Integer.parseInt(propertiedValue));

    }

    // boolean Boolean类型

    if (type.equals("class java.lang.Boolean")) {

    Method m = clz.getMethod("set" + name, Boolean.class);

    if (propertiedValue.equalsIgnoreCase("true")) {

    m.invoke(obj, true);

    }

    if (propertiedValue.equalsIgnoreCase("false")) {

    m.invoke(obj, true);

    }

    }

    if (type.equals("boolean")) {

    Method m = clz.getMethod("set" + name, boolean.class);

    if (propertiedValue.equalsIgnoreCase("true")) {

    m.invoke(obj, true);

    }

    if (propertiedValue.equalsIgnoreCase("false")) {

    m.invoke(obj, true);

    }

    }

    // long Long 数据类型

    if (type.equals("class java.lang.Long")) {

    Method m = clz.getMethod("set" + name, Long.class);

    m.invoke(obj, Long.parseLong(propertiedValue));

    }

    if (type.equals("long")) {

    Method m = clz.getMethod("set" + name, long.class);

    m.invoke(obj, Long.parseLong(propertiedValue));

    }

    // 时间数据类型

    if (type.equals("class java.util.Date")) {

    Method m = clz.getMethod("set" + name, java.util.Date.class);

    m.invoke(obj, DataConverter.convert(propertiedValue));

    }

    }

    }

    使用方式demo类

    @RestController

    @RequestMapping("/version")

    @Api(tags = "版本")

    @ApiSort(value = 0)

    @Data

    public class VersionController {

    @MyConfig("opcl.url")

    public String url = "1";

    @GetMapping(value="/test", produces = "application/json;charset=utf-8")

    @MyConfig(clazz = VersionController.class)

    public Object test(){

    return url;

    }

    }

    这里如果想在VersionController 注入配置url,首先需要在配置url上添加注解MyConfig,value为配置在容器中的key;其次需要在使用url的方法test上添加注解MyConfig,并将当前class传入,当调用此方法,便会触发aop机制,更新url的值

    开发过程遇到的问题

    简述

    在aop中我使用几种方式进行修改对象的属性。

    最终是是第三种证实修改成功。首先spring的bean都是采用动态代理的方式产生。而默认的都是采用单例模式。所以我们需要搞清楚:

    versioncontroller方法中拿取url这个属性时,拿取者是谁,是VersionController还是spring进行cglib动态代理产生的bean(以下简称bean)?

    这里可以看到Versioncontroller的方法执行时,这里的this是Versioncontroller@9250,这其实代表着是对象本身而非代理对象。后面我们会看到,springbean其实是代理对象代理了被代理对象,执行了其(Versioncontroller)方法。

    我们的目的是修改什么?是修改VersionController还是这个bean?

    我们讲到,springbean其实是代理对象代理了被代理对象,执行了其(Versioncontroller)方法。那么我们修改的理所应该是被代理对象的属性值。

    当进行反射赋值的时候,我们修改的是VersionController这个类还是bean?

    首先上面已经明确,修改的应该是被代理对象的属性值。

    我这里三种方法。第一种只修改一个新建对象的实例,很明显与springbean理念相悖,不可能实现我们的需求,所以只谈后两种。

    先看第二种是通过工具类获取bean,然后通过反射为对应的属性赋值。

    这里写一个testController便于验证。

    package com.ai.api.controller;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.web.bind.annotation.GetMapping;

    import org.springframework.web.bind.annotation.RequestMapping;

    import org.springframework.web.bind.annotation.RestController;

    @RestController

    @RequestMapping("/test")

    public class TestController {

    @Autowired

    VersionController versionController;

    @GetMapping("/1")

    public Object getUrl(){

    System.out.println(versionController.getUrl());

    System.out.println(versionController.url);

    return versionController.getUrl();

    }

    }

    这里我们是直接为bean的属性赋值。我们先调用VersionController中的test方法,让其先走一遍Aop。因为springbean如果没有配置,默认的都是单例模式,所以说如果修改成功,那么testController中,注入的VersionController,因为是同一个VersionController的实例,它的代理对象一定也被修改。我们调试后得出:

    我们可以看到,我们确实修改掉了bean的值,但被代理对象的url仍然是1。并没有实现我们想要的效果。

    第三种,通过获取这个bean,通过这个代理bean的set方法,间接修改被代理对象VersionController的属性值。我们先调用VersionController中的test方法,让其先走一遍Aop,因为springbean如果没有配置,默认的都是单例模式。如果修改成功,那么testController中,注入的VersionController,因为是同一个VersionController的实例,它的代理对象一定也被修改了。

    我们调用TestController 方法可以看到:

    这里我们可以看到,被代理的对象已经被成功修改,大功告成!

    助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 如何分析SpringBoot源码模块及结构?--SpringBoot源码(二) 上一篇分析了SpringBoo ...

    这样讲 SpringBoot 自动配置原理,你应该能明白了吧

    https://juejin.im/post/5ce5effb6fb9a07f0b039a14 前言 小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题 ...

    SpringBoot实战之SpringBoot自动配置原理

    SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...

    springboot自动配置源码解析

    springboot版本:2.1.6.RELEASE SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfig ...

    案例解析:springboot自动配置未生效问题定位(条件断点)

    Spring Boot在为开发人员提供更高层次的封装,进而提高开发效率的同时,也为出现问题时如何进行定位带来了一定复杂性与难度.但Spring Boot同时又提供了一些诊断工具来辅助开发与分析,如sp ...

    源码学习系列之SpringBoot自动配置(篇一)

    源码学习系列之SpringBoot自动配置源码学习(篇一) ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属 ...

    Springboot 自动配置浅析

    Introduction 我们知道,SpringBoot之所以强大,就是因为他提供了各种默认的配置,可以让我们在集成各个组件的时候从各种各样的配置文件中解放出来. 拿一个最普通的 web 项目举例.我 ...

    小BUG大原理:重写WebMvcConfigurationSupport后SpringBoot自动配置失效

    一.背景 公司的项目前段时间发版上线后,测试反馈用户的批量删除功能报错.正常情况下看起来应该是个小 BUG,可怪就怪在上个版本正常,且此次发版未涉及用户功能的改动.因为这个看似小 BUG 我了解到不少 ...

    小BUG大原理 | 第一篇:重写WebMvcConfigurationSupport后SpringBoot自动配置失效

    一.背景 公司的项目前段时间发版上线后,测试反馈用户的批量删除功能报错.正常情况下看起来应该是个小BUG,可怪就怪在上个版本正常,且此次发版未涉及用户功能的改动.因为这个看似小BUG我了解到不少未知的 ...

    随机推荐

    pt-online-schema-change中update触发器的bug

    pt-online-schema-change在对表进行表结构变更时,会创建三个触发器. 如下文测试案例中的t2表,表结构如下: mysql> show create table t2\G . ...

    【FFmpeg】Windows下64位ffmpeg编译

    本文主要记录在64位Windows 7下,编译64位ffmpeg的过程. 1.资源准备 (1). MSYS http://sourceforge.net/projects/mingwbuilds/fi ...

    [转]AngularJS的$resource

    转自:http://blog.csdn.net/violet_day/article/details/17403207 $http $http服务是基于$q服务的,提供了promise封装,它接受一个 ...

    codeforce 606C - Sorting Railway Cars

    题意:给你一串数,没个数只能往前提到首位,或则往后放末尾.问最少步骤使操作后的序列成上升序列. 思路:最长连续子序列. #include #include

    2014Esri全球用户大会之标准和互操作

    1.   ArcGIS是一个开放协作的平台吗?Esri是怎样看待"开放"的? 是的,ArcGIS是一个开放协作的平台.Esri公司致力于支持我们的用户更加easy的在异构环境下工作 ...

    oracle-plsql序列问题

    场景:用来汇总工作中数据库的异常问题! 1 问题 序列在会话中未定义 解决: 创建Sequence后直接查询它的当前值(CURRVAL)会出错,要先调用Sequence对象.NEXTVAL,才能查询当 ...

    TensorFlow框架(4)之CNN卷积神经网络

    1. 卷积神经网络 1.1 多层前馈神经网络 多层前馈神经网络是指在多层的神经网络中,每层神经元与下一层神经元完全互连,神经元之间不存在同层连接,也不存在跨层连接的情况,如图 11所示. 图 11 对 ...

    PHP-CGI,FASTcgi,php-fpm,之间的关系?

    刚开始对这个问题我也挺纠结的,看了后,感觉清晰了不少.首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者.   ...

    HiJson(Json格式化工具)64位中文版下载 v2.1.2

    链接:https://pan.baidu.com/s/15gMvig15iUjpqSX7nUZ-5Q 密码:8086

    为wordpress后台登陆添加算术验证码

    对于新建站(个人博客-柠檬https://ninmong.com)的站长来说提高后台的安全性,是一件非常重要的事,添加验证可以起到很好的效果,废话少说,贴代码 //后台登陆数学验证码 function ...

    展开全文
  • 项目中使用配置文件多是取配置文件(applicatoion.yml)的值,使用@Value获取,为了秉持非侵入性的原则,我决定写一套自定义注解,以实现最少的代码量实现业务需求。思路需要实现类似springboot...

    背景

    项目中为了统一管理项目的配置,比如接口地址,操作类别等信息,需要一个统一的配置管理中心,类似nacos。

    我根据项目的需求写了一套分布式配置中心,测试无误后,改为单体应用并耦合到项目中。项目中使用配置文件多是取配置文件(applicatoion.yml)的值,使用@Value获取,为了秉持非侵入性的原则,我决定写一套自定义注解,以实现最少的代码量实现业务需求。

    思路

    需要实现类似springboot @Value注解获取配置文件对应key的值的功能。但区别在于 我是从自己写的自动配置中获取,原理就是数据库中查询所有的配置信息,并放入一个对象applicationConfigContext,同时创建一个bean交给spring托管,同时写了个aop,为被注解的属性赋入applicationConfigContext的对应的值。

    换句话说,自定义的这个注解为类赋值的时间线大概是

    spring bean初始化 —-> 第三方插件初始化 --> 我写的自动配置初始化 ---- 用户调用某个方法,触发aop机制,我通过反射动态改变了触发aop的对象的bean的属性,将值赋值给他。

    难点

    本项目的难点在于如何修改对象的值。看似简单,其实里面的文章很多。

    自动配置代码

    配置映射数据库pojo

    import lombok.AllArgsConstructor;

    import lombok.Builder;

    import lombok.Data;

    import lombok.NoArgsConstructor;

    import java.util.Date;

    /**

    * @Describtion config bean

    * @Author yonyong

    * @Date 2020/7/13 15:43

    * @Version 1.0.0

    **/

    @Data

    @AllArgsConstructor

    @NoArgsConstructor

    @Builder(toBuilder = true)

    public class TblConfig {

    private Integer id;

    /**

    * 配置名称

    */

    private String keyName;

    /**

    * 默认配置值

    */

    private String keyValue;

    /**

    * 分类

    */

    private String keyGroup;

    /**

    * 备注

    */

    private String description;

    /**

    * 创建时间

    */

    private Date insertTime;

    /**

    * 更新时间

    */

    private Date updateTime;

    /**

    * 创建人

    */

    private String creator;

    private Integer start;

    private Integer rows;

    /**

    * 是否是系统自带

    */

    private String type;

    /**

    * 修改人

    */

    private String modifier;

    }

    创建用于防止配置信息的对象容器

    import lombok.AllArgsConstructor;

    import lombok.Builder;

    import lombok.Data;

    import lombok.NoArgsConstructor;

    import java.util.List;

    import java.util.stream.Collectors;

    /**

    * @Describtion config container

    * @Author yonyong

    * @Date 2020/7/13 15:40

    * @Version 1.0.0

    **/

    @Data

    @Builder(toBuilder = true)

    @AllArgsConstructor

    @NoArgsConstructor

    public class ConfigContext {

    /**

    * config key-val map

    */

    private List vals;

    /**

    * env type

    */

    private String group;

    /**

    * get config

    * @param key

    * @return

    */

    public String getValue(String key){

    final List collect = vals.stream()

    .filter(tblConfig -> tblConfig.getKeyName().equals(key))

    .collect(Collectors.toList());

    if (null == collect || collect.size() == 0)

    return null;

    return collect.get(0).getKeyValue();

    }

    }

    创建配置,查询出数据库里配置并创建一个容器bean

    import org.apache.commons.lang3.StringUtils;

    import org.springframework.beans.factory.annotation.Value;

    import org.springframework.beans.factory.config.ConfigurableBeanFactory;

    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;

    import org.springframework.context.annotation.Bean;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.context.annotation.Scope;

    import javax.annotation.Resource;

    import java.util.List;

    /**

    * @Describtion manual auto inject bean

    * @Author yonyong

    * @Date 2020/7/13 15:55

    * @Version 1.0.0

    **/

    @Configuration

    @ConditionalOnClass(ConfigContext.class)

    public class ConfigContextAutoConfig {

    @Value("${config.center.group:DEFAULT_ENV}")

    private String group;

    @Resource

    private TblConfigcenterMapper tblConfigcenterMapper;

    @Bean(name = "applicationConfigContext")

    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)

    @ConditionalOnMissingBean(ConfigContext.class)

    public ConfigContext myConfigContext() {

    ConfigContext configContext = ConfigContext.builder().build();

    //set group

    if (StringUtils.isNotBlank(group))

    group = "DEFAULT_ENV";

    //set vals

    TblConfig tblConfig = TblConfig.builder().keyGroup(group).build();

    final List tblConfigs = tblConfigcenterMapper.selectByExample(tblConfig);

    configContext = configContext.toBuilder()

    .vals(tblConfigs)

    .group(group)

    .build();

    return configContext;

    }

    }

    AOP相关代码

    创建自定义注解

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

    /**

    * @Author yonyong

    * @Description //配置

    * @Date 2020/7/17 11:20

    * @Param

    * @return

    **/

    @Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface MyConfig {

    /**

    * 如果此value为空,修改值为获取当前group,不为空正常获取配置文件中指定key的val

    * @return

    */

    String value() default "";

    Class> clazz() default MyConfig.class;

    }

    创建aop业务功能

    import lombok.extern.slf4j.Slf4j;

    import org.apache.commons.lang3.StringUtils;

    import org.aspectj.lang.JoinPoint;

    import org.aspectj.lang.annotation.Aspect;

    import org.aspectj.lang.annotation.Before;

    import org.aspectj.lang.annotation.Pointcut;

    import org.aspectj.lang.reflect.MethodSignature;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.stereotype.Component;

    import java.lang.reflect.Field;

    import java.lang.reflect.InvocationTargetException;

    import java.lang.reflect.Method;

    import java.util.Date;

    /**

    * @Describtion config service aop

    * @Author yonyong

    * @Date 2020/7/17 11:21

    * @Version 1.0.0

    **/

    @Aspect

    @Component

    @Slf4j

    public class SystemConfigAop {

    @Autowired

    ConfigContext applicationConfigContext;

    @Autowired

    MySpringContext mySpringContext;

    @Pointcut("@annotation(com.ai.api.config.configcenter.aop.MyConfig)")

    public void pointcut(){}

    @Before("pointcut()")

    public void before(JoinPoint joinPoint){

    final MethodSignature signature = (MethodSignature) joinPoint.getSignature();

    Method method = signature.getMethod();

    MyConfig myConfig = method.getAnnotation(MyConfig.class);

    Class> clazz = myConfig.clazz();

    final Field[] declaredFields = clazz.getDeclaredFields();

    Object bean = mySpringContext.getBean(clazz);

    for (Field declaredField : declaredFields) {

    final MyConfig annotation = declaredField.getAnnotation(MyConfig.class);

    if (null != annotation && StringUtils.isNotBlank(annotation.value())){

    log.info(annotation.value());

    String val = getVal(annotation.value());

    try {

    // setFieldData(declaredField,clazz.newInstance(),val);

    // setFieldData(declaredField,bean,val);

    buildMethod(clazz,bean,declaredField,val);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    // mySpringContext.refresh(bean.getClass());

    }

    private void setFieldData(Field field, Object bean, String data) throws Exception {

    // 注意这里要设置权限为true

    field.setAccessible(true);

    Class> type = field.getType();

    if (type.equals(String.class)) {

    field.set(bean, data);

    } else if (type.equals(Integer.class)) {

    field.set(bean, Integer.valueOf(data));

    } else if (type.equals(Long.class)) {

    field.set(bean, Long.valueOf(data));

    } else if (type.equals(Double.class)) {

    field.set(bean, Double.valueOf(data));

    } else if (type.equals(Short.class)) {

    field.set(bean, Short.valueOf(data));

    } else if (type.equals(Byte.class)) {

    field.set(bean, Byte.valueOf(data));

    } else if (type.equals(Boolean.class)) {

    field.set(bean, Boolean.valueOf(data));

    } else if (type.equals(Date.class)) {

    field.set(bean, new Date(Long.valueOf(data)));

    }

    }

    private String getVal(String key){

    if (StringUtils.isNotBlank(key)){

    return applicationConfigContext.getValue(key);

    }else {

    return applicationConfigContext.getGroup();

    }

    }

    private void buildMethod(Class> clz ,Object obj,Field field,String propertiedValue) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    // 获取属性的名字

    String name = field.getName();

    // 将属性的首字符大写, 构造get,set方法

    name = name.substring(0, 1).toUpperCase() + name.substring(1);

    // 获取属性的类型

    String type = field.getGenericType().toString();

    // 如果type是类类型,则前面包含"class ",后面跟类名

    // String 类型

    if (type.equals("class java.lang.String")) {

    Method m = clz.getMethod("set" + name, String.class);

    // invoke方法传递实例对象,因为要对实例处理,而不是类

    m.invoke(obj, propertiedValue);

    }

    // int Integer类型

    if (type.equals("class java.lang.Integer")) {

    Method m = clz.getMethod("set" + name, Integer.class);

    m.invoke(obj, Integer.parseInt(propertiedValue));

    }

    if (type.equals("int")) {

    Method m = clz.getMethod("set" + name, int.class);

    m.invoke(obj, (int) Integer.parseInt(propertiedValue));

    }

    // boolean Boolean类型

    if (type.equals("class java.lang.Boolean")) {

    Method m = clz.getMethod("set" + name, Boolean.class);

    if (propertiedValue.equalsIgnoreCase("true")) {

    m.invoke(obj, true);

    }

    if (propertiedValue.equalsIgnoreCase("false")) {

    m.invoke(obj, true);

    }

    }

    if (type.equals("boolean")) {

    Method m = clz.getMethod("set" + name, boolean.class);

    if (propertiedValue.equalsIgnoreCase("true")) {

    m.invoke(obj, true);

    }

    if (propertiedValue.equalsIgnoreCase("false")) {

    m.invoke(obj, true);

    }

    }

    // long Long 数据类型

    if (type.equals("class java.lang.Long")) {

    Method m = clz.getMethod("set" + name, Long.class);

    m.invoke(obj, Long.parseLong(propertiedValue));

    }

    if (type.equals("long")) {

    Method m = clz.getMethod("set" + name, long.class);

    m.invoke(obj, Long.parseLong(propertiedValue));

    }

    // 时间数据类型

    if (type.equals("class java.util.Date")) {

    Method m = clz.getMethod("set" + name, java.util.Date.class);

    m.invoke(obj, DataConverter.convert(propertiedValue));

    }

    }

    }

    使用方式demo类

    @RestController

    @RequestMapping("/version")

    @Api(tags = "版本")

    @ApiSort(value = 0)

    @Data

    public class VersionController {

    @MyConfig("opcl.url")

    public String url = "1";

    @GetMapping(value="/test", produces = "application/json;charset=utf-8")

    @MyConfig(clazz = VersionController.class)

    public Object test(){

    return url;

    }

    }

    这里如果想在VersionController 注入配置url,首先需要在配置url上添加注解MyConfig,value为配置在容器中的key;其次需要在使用url的方法test上添加注解MyConfig,并将当前class传入,当调用此方法,便会触发aop机制,更新url的值

    开发过程遇到的问题

    简述

    在aop中我使用几种方式进行修改对象的属性。

    20200719175507305309.png

    最终是是第三种证实修改成功。首先spring的bean都是采用动态代理的方式产生。而默认的都是采用单例模式。所以我们需要搞清楚:

    versioncontroller方法中拿取url这个属性时,拿取者是谁,是VersionController还是spring进行cglib动态代理产生的bean(以下简称bean)?

    20200719175507619775.png

    这里可以看到Versioncontroller的方法执行时,这里的this是Versioncontroller@9250,这其实代表着是对象本身而非代理对象。后面我们会看到,springbean其实是代理对象代理了被代理对象,执行了其(Versioncontroller)方法。

    我们的目的是修改什么?是修改VersionController还是这个bean?

    我们讲到,springbean其实是代理对象代理了被代理对象,执行了其(Versioncontroller)方法。那么我们修改的理所应该是被代理对象的属性值。

    当进行反射赋值的时候,我们修改的是VersionController这个类还是bean?

    20200719175507305309.png

    首先上面已经明确,修改的应该是被代理对象的属性值。

    我这里三种方法。第一种只修改一个新建对象的实例,很明显与springbean理念相悖,不可能实现我们的需求,所以只谈后两种。

    先看第二种是通过工具类获取bean,然后通过反射为对应的属性赋值。

    这里写一个testController便于验证。

    package com.ai.api.controller;

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.web.bind.annotation.GetMapping;

    import org.springframework.web.bind.annotation.RequestMapping;

    import org.springframework.web.bind.annotation.RestController;

    @RestController

    @RequestMapping("/test")

    public class TestController {

    @Autowired

    VersionController versionController;

    @GetMapping("/1")

    public Object getUrl(){

    System.out.println(versionController.getUrl());

    System.out.println(versionController.url);

    return versionController.getUrl();

    }

    }

    这里我们是直接为bean的属性赋值。我们先调用VersionController中的test方法,让其先走一遍Aop。因为springbean如果没有配置,默认的都是单例模式,所以说如果修改成功,那么testController中,注入的VersionController,因为是同一个VersionController的实例,它的代理对象一定也被修改。我们调试后得出:

    20200719175508124677.png

    我们可以看到,我们确实修改掉了bean的值,但被代理对象的url仍然是1。并没有实现我们想要的效果。

    第三种,通过获取这个bean,通过这个代理bean的set方法,间接修改被代理对象VersionController的属性值。我们先调用VersionController中的test方法,让其先走一遍Aop,因为springbean如果没有配置,默认的都是单例模式。如果修改成功,那么testController中,注入的VersionController,因为是同一个VersionController的实例,它的代理对象一定也被修改了。

    我们调用TestController 方法可以看到:

    20200719175508607117.png

    这里我们可以看到,被代理的对象已经被成功修改,大功告成!

    展开全文
  • returnValue of Chrome

    2014-07-05 16:55:00
    说实话,我一看到这个returnValue就有点反感,感觉这个就是IE式的老套的用法,因为项目中有用到就了解了下,以下主要是一些我...returnValue是与showModalDialog搭配使用的,showModalDialog用于打开窗口,与open类...

    说实话,我一看到这个returnValue就有点反感,感觉这个就是IE式的老套的用法,因为项目中有用到就了解了下,以下主要是一些我的理解和发现吧。

    PS:returnValuewindow的属性,showModalDialogopenwindow的方法。

    returnValue是与showModalDialog搭配使用的,showModalDialog用于打开窗口,与open类似效果,但通过showModalDialog打开窗口时有如下特点:

    1. 打开窗口后,将不能再操作父窗口了(正常情况下,父窗口将获取不到焦点了);
    2. 确切的说父窗口在执行showModalDialog这一步时停止了,等待子窗口操作返回,而showModalDialog之后的js代码也就暂时不会执行了;
    3. returnValue就是返回值,子窗口通过window.returnValue将操作结果返回给父窗口,在子窗口调用window.close方法后,returnValue将作为showModalDialog的返回值传递到父窗口中,之后继续执行showModalDialog后面的js代码;

    网上的搜罗了下,都说IE、Firefox支持的,而Chrome虽然有showModalDialog方法,但效果仅仅类似open,且不支持returnValue,至于Opera则完全不支持(应该说的不是Webkit内核的Opera)。

    初步写代码测试了下(只测IE、Firefox、Chrome),我写了三个页面,主要逻辑是:t1中打开t2、t2中打开t3、同时每个页面上添加点击测试、刷新测试按钮(用于Chrome测试),基本html代码如下,可直接点击页面地址进行浏览:

    t1.html代码:
    <!doctype html>
    <html>
        <meta charset="utf-8"/>
        <title>t1</title>
        <script>
            alert("load t1");
            function openT2(){
                alert(showModalDialog('t2.html',{msg:"arguments from t1.html",win:window},''));
                alert('子窗口已关闭');
            }
            function openT1Self(){
                alert(showModalDialog('t1.html',{msg:"arguments from t1.html",win:window},''));
                alert('子窗口已关闭');
            }
            function closeSelf(){
                window.returnValue='从t1正常返回的returnValue';
                window.close();
            }
            if(window.dialogArguments){
                if(window.dialogArguments.msg){
                    alert(window.dialogArguments.msg);
                }else{
                    alert(window.dialogArguments);
                }
            }
            function reloadPage(){
                alert('before');
                window.location.reload();
                alert('after');
            }
            function setReturnValue(){
                var str = prompt("请输入returnValue值")
                window.returnValue = "t1在刷新前所赋的returnValue:"+str;
                alert("赋值完毕,请点击刷新!");
            }
        </script>
        <body>
            <a href="javascript:openT2();">打开t2</a>
            <a href="javascript:openT1Self();">打开t1自己</a>
            <a href="javascript:closeSelf();">关闭</a>
            <a href="javascript:alert('点击了');">Chrome下点击测试</a>
            <a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
            <a href="javascript:reloadPage();">点击刷新</a>
        </body>
    </html>
    t2.html代码:

     

    <!doctype html>
    <html>
        <meta charset="utf-8"/>
        <title>t2</title>
        <script>
            alert("load t2");
            function openT3(){
                alert(showModalDialog('t3.html',{msg:"arguments from t2.html",win:window},''));
                alert('子窗口已关闭');
            }
            function closeSelf(){
                window.returnValue='从t2正常返回的returnValue';
                window.close();
            }
            if(window.dialogArguments){
                if(window.dialogArguments.msg){
                    alert(window.dialogArguments.msg);
                }else{
                    alert(window.dialogArguments);
                }
            }
            function reloadPage(){
                alert('before');
                window.location.reload();
                alert('after');
            }
            function setReturnValue(){
                var str = prompt("请输入returnValue值")
                window.returnValue = "t2在刷新前所赋的returnValue:"+str;
                alert("赋值完毕,请点击刷新!");
            }
        </script>
        <body>
            <a href="javascript:openT3();">打开t3</a>
            <a href="javascript:closeSelf();">关闭</a>
            <a href="javascript:alert('点击了');">Chrome下点击测试</a>
            <a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
            <a href="javascript:reloadPage();">点击刷新</a>
        </body>
    </html>
    t3.html代码:

     

    <!doctype html>
    <html>
        <meta charset="utf-8"/>
        <title>t3</title>
        <script>
            alert("load t3");
            function closeSelf(){
                window.returnValue='从t3正常返回的returnValue';
                window.close();
            }
            if(window.dialogArguments){
                if(window.dialogArguments.msg){
                    alert(window.dialogArguments.msg);
                }else{
                    alert(window.dialogArguments);
                }
            }
            function reloadPage(){
                alert('before');
                window.location.reload();
                alert('after');
            }
            function setReturnValue(){
                var str = prompt("请输入returnValue值")
                window.returnValue = "t3在刷新前所赋的returnValue:"+str;
                alert("赋值完毕,请点击刷新!");
            }
        </script>
        <body>
            <a href="javascript:closeSelf();">关闭</a>
            <a href="javascript:setReturnValue();">在刷新前给returnValue赋值</a>
            <a href="javascript:reloadPage();">点击刷新</a>
        </body>
    </html>
    测试1

    直接将t1.html文件拖入浏览器浏览进行测试。

    测试结果:
    • IE、Firefox没有问题;
    • Chrome下则returnValue几乎无效,具体细节:

      1. showModalDialog效果接近open,即只是打开了一个新窗口而已,父窗口仍然可以操作,而showModalDialog后的语句没有执行,但控制台上却有些信息提示,有一个警告(灰色)和错误(红色):

        Chromium is considering deprecating showModalDialog. Please use window.open and postMessage instead.

        Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.

        警告信息表明Chromium将弃用showModalDialog(经验证,在Chromium38.0.2074.0中,showModalDialog已报undefined错误,看来已被遗弃,见官方Issue345831,不知Chrome之后会不会如此……)。

        错误信息是在关闭子窗口后出来的,这个就是说明了为什么returnValue无效以及showModalDialog后面的语句为什么没执行(报错了么,呵呵),这个错误似乎跟跨域访问有点类似啊。

        PS:在较老版本的Chrome中并不会有这里的警告及错误信息,故可能让人误以为不支持returnValue

        PPS@2014/09/14: 最近无意间在Firefox(版本号是32)的控制台也看到类似的提示信息,如下所示,看来ShowModalDialog的结局可想而知了。

        window.showModalDialog() 已废弃。请使用 window.open() 代替。更多信息见 https://developer.mozilla.org/en-US/docs/Web/API/Window.open

      2. 当t1.html通过showModalDialog打开t1.html(即自己)的时候,returnValue竟起作用了,但在子窗口打开的情况下父窗口仍然可以操作,不同的是的showModalDialog后面的语句在关闭子窗口后执行了,说明此时没有1中的那个错误了;

      3. 但如果子页面刷新了,则无论之后给returnValue赋什么值,最终showModalDialog的返回值将一直是子页面第一次刷新前给returnValue所赋的值,如果第一次刷新前没有给returnValue赋值,则将是undefined,这说明子页面在刷新后与父页面失去了联系,导致returnValue失效;

      4. 在子窗口打开情况下,虽然父窗口能够操作,但在父窗口中点击“点击刷新”后两个alert都执行了,而页面却没有刷新,说明有些特殊操作如window.location.reload();将会等到子窗口关闭后才会执行。

    通过测试1得知在chrome下本地直接浏览网页的形式使用showModalDialog存在类似跨域访问的错误,因此需要将网页放到Web应用服务器上测试,至于子页面刷新导致的问题也许就那样了,算是个bug吧。

    测试2

    将三个页面放到Web应用服务器(Tomcat)上,然后打开t1.html浏览进行测试。

    测试结果:
    • IE、Firefox没有问题;
    • Chrome下则returnValue基本有效,具体细节:
      1. 正常操作情况下,能够通过returnValue返回数据,showModalDialog后面的代码也能在关闭子窗口后执行;
      2. 但如果子页面刷新了,则无论之后给returnValue赋什么值,最终showModalDialog的返回值将一直是子页面第一次刷新前给returnValue所赋的值,如果第一次刷新前没有给returnValue赋值,则将是undefined,这说明子页面在刷新后与父页面失去了联系,导致returnValue失效;
      3. 在子窗口打开情况下,虽然父窗口能够操作,但在父窗口中点击“点击刷新”后两个alert都执行了,而页面却没有刷新,说明有些特殊操作如window.location.reload();将会等到子窗口关闭后才会执行。

    总结

    鉴于网上发表的关于Chrome之returnValue的文章都是几年前的,也许那时确实是完全不支持returnValue吧,不过我拿了个较老的版本(v11)测过,结果大致跟新版一样。

    但Chrome虽然支持returnValue,但使用体验却不怎么样,有以下几点:

    1. 打开子窗口情况下,还是能够操作父窗口;
    2. 子窗口在刷新后,returnValue就失效了(window.dialogArguments也变为undefined了),只能返回第一次刷新前的returnValue(该问题可通window.opener传参解决,该属性指向父窗口,且不会因为刷新导致失效,具体请参考ref1文中的“解决returnValue问题”小节)

    于是乎可以说Chrome不支持returnValue吧,在之后的版本中showModalDialog这个方法应该会被移除了,所以说这个没有什么意义了啊。

    如果一定要继续用showModalDialog的话,可以考虑在子窗口中通过window.opener与父窗口进行传参来代替returnValue的方式,而用open来代替showModalDialog,而在子窗口打开情况下,可以在父窗口中覆盖一层div来禁用用户操作等等,还是可以将就着模拟showModalDialog的效果的,但要完全模拟,有点困难啊。

    参考资料

    转载于:https://www.cnblogs.com/yevon/p/returnvalue_of_chrome.html

    展开全文
  • 搭配购买

    2020-10-21 16:00:54
    并查集+01背包 #include<bits/stdc++.h>...int fa[N],value[N],cost[N],dp[N]; int n,m,w; set<PII> s; int find(int x) { if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } int main
  • 在使用SpringMVC和jackson时,如果报错No converter found for return value of type 解决方案: 检查有没有jackson-core,jackson-annotations,jackson-databind这三个包 检查SpringMVC与Jackson的兼容问题:...
  • input的name、value、placeholder三者关系

    千次阅读 2019-06-02 19:37:20
    在做页面的时候input标签经常用到,这里要说的是的它其中的几个属性: name、value、placeholder还有常和input标签搭配使用的lable标签。 ① Name在W3School中的解释: 也就是给当前的input起个名字,当当前这个...
  • gazebo搭配虚拟环境

    2021-03-21 16:08:34
    gazebo搭配虚拟环境一、创建环境二、仿真1、摄像头2、激光雷达3、Kinect仿真三、总结与参考资料1、总结2、参考资料 一、创建环境 打开gazebo roslaunch gazebo_ros empty_world.launch 查看环境 二、仿真 1、...
  • Toggle真的是让人又爱又恨,它既有和ToggleGroup组合搭配的方便,又有一些不可控的情况,我就在项目中遇到了一个棘手的问题。 我们常常用到Toggle的onValueChanged改变事件,它很方便,即可改变自己状态,又可以...
  • 从Map中取出第一个 key 和 value 的方法,使用Map.Entry进行操作; 可与LinckedHashMap(按元素存入顺序排序的有序Hash表)搭配使用;实现特定的业务要求;/** * 获取map中第一个key值 * * @param map 数据源 * ...
  • Column count doesn\'t match value count at row 1 出现这种情况可能是values两边的数值个数不对; 还有种就是数据库字段的编码可能是gbk和utf不搭配
  • vue 中 Type of the default value for ‘data’ prop must be a function的解决方案 vue官方文档 搭配es6语法简单粗暴解决 props: { dataList: { type: Object, default: () => ({ a:1, b:2 }) } }
  • 这几个傻逼语言傻逼框架再搭配这个傻逼组件,弄到一起真的浪费时间 1、html弹出层组件写法,这里返回combobox的value属性值,不要把name弄成文本节点的内容 <tr> <td class="label">tag:</td&...
  • php list each搭配循环

    2018-06-19 16:47:00
    键/值对被返回带有4个元素的关联和索引混合的数组,键名分别为0、1、key和value。其中键名0和key对应的值是一样的,是数组元素的键名,1和value则包含有数组元素的值。如果内部指针越过了数组的末端,则each()返回...
  • data- 和JQuery的搭配

    2018-07-11 16:45:29
    开发当中,前台页面需要和后台页面进行交互。...但有时,这个value还需要给它赋予其它的值,那么问题是:如果给value赋予其它值的同时,如何也能给这个input加上后台传递过来对象的ID值呢?在这里使...
  • 首先单纯使用idhttp是只能访问http,而https则需要搭配IdSSLIOHandlerSocketOpenSSL来实现对https的访问支持,当然还需要在系统目录或编译目标程序的同目录下有ssleay32.dll与libeay32.dll两个SLL协议的支持库。...
  • 一: ModelAttribute RequestParam 搭配categoryId不会被添加到model @RequestMapping(value = "/list", method = RequestMethod.GET) public String list(@ModelAttribute("categoryId") @RequestParam(...
  • 当在spring boot的拦截器/过滤器中要读取配置文件时,最常用的@Component 搭配@Value 或者 @Autowired 都无法读取到值,究其原因是因为加载顺序的问题,简单来说,listener->filter->servlet,所以过滤器/拦截...
  • Spring5以上的版本,搭配2.9.X以上的Jackson,原因官网有详细说明 :会报这个errorjava.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/exc/InvalidDefinitionException <!--Spring--> <...
  • swagger使用 类注解 @Api(tags = "注解分组") public class controller { ... @ApiOperation(value = "接口名称",notes = "接口说明") public String selectAll(PartyNewsQuery query) { return ""; } }
  • 原来是 Laravel 4.2 和 Mysql 5.7 搭配出了问题,5.7 里 Mysql 不允许时间戳的值为 0 。 解决 方案1. 修改默认的 Mysql 配置 sudo vi /etc/mysql/my.cnf 在 [mysqld] 区域添加: sql_mode="ONLY_FULL_GROUP_BY...
  • public class printNum { static class SoulutionTask implements Runnable{ static int value = 0; @Override public void...
  • springboot 搭配mysql启动时,报如下错误 java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.  You must configure either...
  • 在Vue中 使用select下拉框 主要靠的是 v-model 来绑定选项 option 的 value 值。 select下拉框在界面的展示,我们都希望看到框中有一个值 而不是空白,比如显示 “请选择” 或者 “全部” 的默认值。 关于select...
  • 前台页面带着areaid参数请求更新此id的数据...用request.setAttribute和request.getAttribute的搭配使用来解决此问题。 @RequestMapping(value="area_updateInput.action") public String areaUpdateInput(int areaId
  • .properties配置文件中,我们想通过@Value搭配Spring EL来读取配置文件中的值来给我们的变量赋值。 在spring1.5一下提供了一个类注解:@ConfigurationProperties: 常用的两个属性是: locations:指定配置文件 ...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 322
精华内容 128
关键字:

value搭配