JAXB读取sql.xml的用法以及从yml读取配置属性的用法

2 篇文章 0 订阅

项目中用到了从sql.xml中获取sql语句模板并且根据前端参数配合yml配置参数将处理后的参数封装到模板形成完整sql后发送到数据库查询的用法,写这篇博客想与大家分享一下JAXB的用法和从yml读取配置的用法。

一.读取yml配置文件中的配置属性:

yml文件有如下配置:

myConfig:
  name: xiaoming
  age: 18
  sex: 1
  socre: 100

获取yml自定义配置的类:

@Component
@ConfigurationProperties("myConfig")
public class YmlUtils {

    private String name;
    private String age;
    private String sex;
    private Integer score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getScore() {
   		return score;
    }

    public void setScore(Integer score) {
    	this.score = score;
     }
}

Controller:
在这里插入图片描述
地址栏访问该TestController的test2地址:
在这里插入图片描述

二.yml配置封装到对象中:

yml配置修改如下:想要把people配置项封装到People对象中

myConfig:
  people:
    name: xiaoming
    age: 18
    sex: 1
  score: 100

People类:

public class People implements Serializable {
    private String name;
    private String age;
    private String sex;

    get/set...

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

Controller:
在这里插入图片描述
访问效果:
在这里插入图片描述
当然也可以把yml文件中的配置封装到Map中(yml是ky格式的):
yml:
在这里插入图片描述
配置类:
在这里插入图片描述
项目启动后控制台:
在这里插入图片描述

小结:

①想读取yml配置的类必须被spring扫描到,即要么新添加一个类加上@Component,要么在启动类新加一个方法加上@Bean(启动类操作的方式与新添加一个类的方式不太一样,启动类操作的是ConnectionSettings,新添加的类操作的是自己定义的类,有兴趣的可以百度)
②不论是自定义类还是启动类操作,必须有@ConfigurationProperties(“父级配置名字”)这个注解
③自定义类的属性名一定要和yml文件的子级配置名保持一致
④读取yml内容会自动类型转换,如score为Integer,age为String
⑤获取yml也可以使用@Value("${父级name.子级name}")获取(@Value还有别的用法,有兴趣自行百度)
⑥yml的配置结构是父级配置(顶格)+子级配置属性(换行、tab键)(或者在父级配置的:后面回车即可自动格式化)
⑦set方法一定要有

三.从sql.xml中获取sql语句

有如下两个xml文件:
one.xml:
在这里插入图片描述
two.xml:
在这里插入图片描述
现在的想法是把所有的sql语句存入一个map中,k就是每个sql的id,v就是sql语句,这样在实际开发中在对应的方法中可以根据k来获取能满足功能的sql,十分方便。(two.xml的sql最后会解释,以及k怎么获取):
获取sql的工具类:

@XmlRootElement(name = "sql")
public class XmlUtils {
    private Map<String, String> sqlMap = new HashMap<>();

    private List<SelectSql> selects = new ArrayList<>();
    
    @XmlElement(name = "select")
    public List<SelectSql> getSelects() {
        return selects;
    }

    public void setSelects(List<SelectSql> selects) {
        this.selects = selects;
    }
    public Map<String, String> getSqlMap() {
        return sqlMap;
    }

    public void setSqlMap(Map<String, String> sqlMap) {
        this.sqlMap = sqlMap;
    }

    static class SelectSql {
        private String id;
        private String sql;
        @XmlAttribute(name = "id")
        public String getId() {
            return id;
        }
        @XmlValue
        @XmlJavaTypeAdapter(MyXmlAdapter.class)
        public String getSql() {
            return sql;
        }
        public void setId(String id) {
            this.id = id;
        }
        public void setSql(String sql) {
            this.sql = sql;
        }
    }

注解简单解释(网上拷贝):
①@XmlRootElement(name = “XXX”):类级别的注解,将类映射为xml全局元素,也就是根元素。简洁:从哪个根标签开始获取内容,例子为<sql>标签开始
②@XmlElement(name = “YYY”):字段,方法,参数级别的注解。该注解可以将被注解的字段(非静态),或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。默认使用字段名或get/set方法去掉前缀剩下部分小写作为元素名(在字段名和get/set方法符合命名规范的情况下)。简洁:要获取哪些子标签的内容,例子为<select>
③@XmlAttribute(name = “ZZZ”):字段和方法级别的注解。该注解会将字段或get/set方法对应的字段映射成本类对应元素的属性,属性名默认使用字段名或get/set方法去掉前缀剩下部分首字母小写(在字段名和get/set方法符合命名规范的情况下)。简洁:获取子标签的哪个字段内容,例子为id字段,因为要作为k
④@XmlValue:字段和方法级别的注解。该注解的作用,简单理解就是定义xml元素文本值的类型。简洁:具体作用萌新博主还不知道,大概就是注入子标签内容
⑤@XmlJavaTypeAdapter:包、类、字段,方法、参数级别的注解。可以对xml的内容自定义处理。简洁:对子标签内容进行自定义处理,如日期等,例子为去掉转义<![CDATA[ ]]>
⑥ @XmlAccessorType的默认访问级别是 XmlAccessType.PUBLIC_MEMBER(有兴趣自行百度),因此,如果java对象中的private成员变量设置了public权限的 getter/setter方法,就不要在private变量上使用@XmlElement和@XmlAttribute注解,否则在由java对象生成 xml时会报同一个属性在java类里存在两次的错误。
自定义处理标签内容的类:

public class MyXmlAdapter extends XmlAdapter<String,String> {
    @Override
    public String unmarshal(String v) {
        if (StringUtils.isEmpty(v)){
            return "";
        }
        String startStr="<![CDATA[";
        String endStr="]]>";
        if (v.contains(startStr)&&v.contains(endStr)) {
            return v.substring(v.indexOf(startStr)+1,v.indexOf(endStr));
        }
        return v;
    }
    @Override
    public String marshal(String v) {
        return "<![CDATA[" + v + "]]>";
    }
}

注意:
marshal是对象–>xml文件,unmarshal是xml–>对象
②XmlAdapter的两个泛型,第一个是unmarshal的类型,第二个是marshal的类型
接下来就差最后一步,将获取的sql放入到map中:

@Configuration
public class LoadSqlConfig {
    @Bean
    public XmlUtils loadSQL(){
        XmlUtils xmlUtils=new XmlUtils();
        Map<String,String> sqlMap=new HashMap<>(8);
        try {
            JAXBContext context=JAXBContext.newInstance(XmlUtils.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            String[] strs={"one.xml","two.xml"};
            for (String s : strs) {
                Resource resource=new ClassPathResource("sql/"+s);
                XmlUtils xml = (XmlUtils)unmarshaller.unmarshal(resource.getInputStream());
             	xml.getSelects().stream().forEach(e-> {
                    System.out.println(e.getId());
                    System.out.println(e.getSql());
                    sqlMap.put(e.getId(),e.getSql());
                });
                xmlUtils.getSelects().addAll(xml.getSelects());
            }
            xmlUtils.setSqlMap(sqlMap);
        }catch (Exception e){
            e.printStackTrace();
        }
        return xmlUtils;
    }
}

①既然sql要放入map中,在项目运行时就要获取,那么应该在在项目启动时就初始化好,可以自定义类配置类,也可以在启动类操作。
②获取xml–>Java对象的unmarshaller 对象

JAXBContext context=JAXBContext.newInstance(XmlUtils.class);
Unmarshaller unmarshaller = context.createUnmarshaller();

③sql是resources目录下的sql包,存放各种sql.xml
④获取内容:

XmlUtils xml = (XmlUtils)unmarshaller.unmarshal(resource.getInputStream());

一定要强转类型为自定义的sql工具类
⑤遍历一次,只是获取一个sql.xml的内容,所以最外层的xmlUtils才是我们需要的类
启动项目查看效果:
在这里插入图片描述

四.sql.xml文件有<select>、<update>等多个标签:

one.xml添加<update>:
在这里插入图片描述
XmlUtils修改:

@XmlElements({@XmlElement(name = "select"),@XmlElement(name = "update")})
public List<SelectSql> getSelects() {
        return selects;
}

@XmlElements是要获取哪些子标签的内容,当然可以定义多个子标签。启动项目查看是否有one.xml的update语句:
在这里插入图片描述

五.实际用法

①大致思路就是如上所述,先把所有的sql.xml文件封装到工具类中,sqlMap的k则在yml中定义(也可以在conf.properties中定义,操作方式不同,有兴趣的可以百度下),通过@Value获取k,然后在相应的方法中获取相应的sql。
②two.xml的sql应该是比较常见的,
在这里插入图片描述
第一个sql是用于列表查询,只展示基本的信息:学生id,名字,头像,平均分
第二个sql查询详细信息,展示名字,性别,年龄,班级,各科分数等
在后端代码获取到初始的sql之后,是需要把参数绑定到sql语句中,最终形成可执行的sql,这需要手动封装一个类,把${XXX}替换成相应的实际参数。提示:sql转换工具类的方法参数传两个,一个是初始sql,一个是参数map,k为${paramName}的paramName,v为实际参数。

六.声明:

代码从来都不止一种写法,以上只是个人的用法。可能有不足的地方,只是给大家一个参考思路。

萌新发言,不喜勿喷,欢迎指出不当之处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值