搜索

基于循环变量法的流程-尊龙官方网站

发布时间:2022-12-02 16:05 作者:黑马程序员 点击: 【 字体:

基于循环变量法的流程?如果你对这个不了解,来看看!

自定义代码生成器(上),下面一起来看看本站小编黑马程序员给大家精心整理的答案,希望对您有帮助

基于循环变量法的流程1

1 概述

1.1 介绍

在项目开发过程中,有很多业务模块的代码是具有一定规律性的,例如controller控制器、service接口、service实现类、mapper接口、model实体类等等,这部分代码可以使用代码生成器生成,我们就可以将更多的时间放在业务逻辑上。

传统的开发步骤:

创建数据库和表 根据表设计实体类 ​ 编写mapper接口 ​ 编写service接口和实现类 ​ 编写controller控制器 ​ 编写前端页面 ​ 前后端联调

基于代码生成器开发步骤:

创建数据库和表 ​ 使用代码生成器生成实体类、mapper、service、controller、前端页面 ​ 将生成好的代码拷贝到项目中并做调整 ​ 前后端联调

我们只需要知道数据库和表相关信息,就可以结合模版生成各个模块的代码,减少了很多重复工作,也减少出错概率,提高效率。

1.2 实现思路

(1)需要对数据库表解析获取到元数据,包含表字段名称、字段类型等等

(2)将通用的代码编写成模版文件,部分数据需使用占位符替换

(3)将元数据和模版文件结合,使用一些模版引擎工具(例如freemarker)即可生成源代码文件

2 freemarker

2.1 介绍

freemarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(html网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个java类库,是一款程序员可以嵌入他们所开发产品的组件。

模板编写为freemarker template language (ftl)。它是简单的,专用的语言, 在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。

2.2 应用场景

(1)动态页面

freemarker可以作为springmvc一种视图格式,像jsp一样被浏览器访问。

(2)页面静态化

对于一些内容比较多,更新频率很小,访问又很频繁的页面,可以使用freemarker静态化,减少db的压力,提高页面打开速度。

(3)代码生成器

根据配置生成页面和代码,减少重复工作,提高开发效率。

2.3 快速入门

(1)创建freemarker-demo模块,并导入相关依赖



    4.0.0
    com.itheima
    freemarker-demo
    1.0-snapshot
    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.1.release
    
    
        8
        8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
        
        
        
            org.springframework.boot
            spring-boot-starter-freemarker
        
        
        
            org.projectlombok
            lombok
        
    

(2)application.yml相关配置

server:
  port: 8881 #服务端口
spring:
  application:
    name: freemarker-demo #指定服务名
  freemarker:
    cache: false #关闭模板缓存,方便测试
    settings:
      template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查,如果时间大于0会有缓存不方便进行模板测试
    suffix: .ftl #指定freemarker模板文件的后缀名

(3)创建启动类

package com.heima.freemarker;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
@springbootapplication
public class freemarkerdemotapplication {
    public static void main(string[] args) {
        springapplication.run(freemarkerdemotapplication.class,args);
    }
}

(4)创建student模型类

package com.itheima.freemarker.entity;
import lombok.allargsconstructor;
import lombok.data;
import lombok.noargsconstructor;
import java.util.date;
@data
@noargsconstructor
@allargsconstructor
public class student {
    private integer id;
    private string name;//姓名
    private integer age;//年龄
    private date birthday;//生日
    private float money;//钱包
}

(5)创建studentcontroller

package com.itheima.freemarker.controller;
import com.itheima.freemarker.entity.student;
import org.springframework.stereotype.controller;
import org.springframework.ui.model;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.requestmapping;
import java.util.date;
@controller
@requestmapping("student")
public class studentcontroller {
    @getmapping("index")
    public string index(model model){
        //1.纯文本形式的参数
        model.addattribute("name", "freemarker");
        //2.实体类相关的参数
        student student = new student();
        student.setname("黑马");
        student.setage(18);
        model.addattribute("stu", student);
        return "01-index";
    }
}

(6)在resources/templates下创建01-index.ftl模版文件


    
    尊龙凯时官方网站首页
普通文本 string 展示:
hello ${name}

对象student中的数据展示:
姓名:${stu.name}
年龄:${stu.age}

(7)测试

浏览器访问 http://localhost:8881/student/index

效果如下

2.4 模版

2.4.1 基础语法种类

(1)注释,即<#-- -->,介于其之间的内容会被freemarker忽略

<#--我是一个freemarker注释-->

(2)插值(interpolation):即 ${..} 部分,freemarker会用真实的值代替${..}

hello ${name}

(3)ftl指令:和html标记类似,名字前加#予以区分,freemarker会解析标签中的表达式或逻辑。

<# >ftl指令 

(4)文本,仅文本信息,这些不是freemarker的注释、插值、ftl指令的内容会被freemarker忽略解析,直接输出内容。

<#--freemarker中的普通文本-->
我是一个普通的文本

2.4.2 if指令

if 指令即判断指令,是常用的ftl指令,freemarker在解析时遇到if会进行判断,条件为真则输出if中间的内容,否则跳过内容不再输出。

格式如下

<#if condition>
  ....
<#elseif condition2>
  ...
<#elseif condition3>   
  ...
<#else>
  ...

需求:根据年龄输出所处的年龄段

童年:0岁—6岁(周岁,下同) 少年:7岁—17岁 青年:18岁—40岁 中年:41—65岁 老年:66岁以后

实例代码:

(1)在01-index.ftl添加如下代码

<#if stu.age <= 6>
童年
<#elseif stu.age <= 17>
少年
<#elseif stu.age <= 40>   
青年
<#elseif stu.age <= 65>   
中年
<#else>
老年

(2)测试

浏览器访问http://localhost:8881/student/index

效果如下

2.4.3 list指令

list指令时一个迭代输出指令,用于迭代输出数据模型中的集合

格式如下

<#list items as item>
    ${item_index   1}------${item}-----<#if item_has_next>,

迭代集合对象时,包括两个特殊的循环变量: (1)item_index:当前变量的索引值。 (2)item_has_next:是否存在下一个对象

item_index 和 item_has_nex 中的item为<#list items as item> 中as后面的临时变量

需求:遍历学生集合,输出序号,学生id,姓名,所处的年龄段,是否最后一条数据

(1)在studentcontroller中增加方法

@getmapping("list")
public string list(model model) throws parseexception {
    list list = new arraylist<>();
    list.add(new student(1001,"张飞",15, null, 1000.11f));
    list.add(new student(1002,"刘备",28, null, 5000.3f));
    list.add(new student(1003,"关羽",45, null, 9000.63f));
    list.add(new student(1004,"诸葛亮",62, null, 10000.99f));
    list.add(new student(1005,"成吉思汗",75, null, 16000.66f));
    model.addattribute("stus",list);
    return "02-list";
}

(2)在resources/templates目录下创建02-list.ftl模版


    
    列表页面
    
<#list stus as stu >
        
序号 id 姓名 所处的年龄段 生日 钱包 是否最后一条数据
${stu_index 1} ${stu.id} ${stu.name} <#if stu.age <= 6> 童年 <#elseif stu.age <= 17> 少年 <#elseif stu.age <= 40> 青年 <#elseif stu.age <= 65> 中年 <#else> 老年 ${stu.money} <#if stu_has_next> 否 <#else> 是

(2)测试

浏览器访问http://localhost:8881/student/list

效果如下

2.4.4 include指令

include指令的作用类似于jsp的包含指令,用于包含指定页,include指令的语法格式如下

<#include filename [options]>

(1)filename:该参数指定被包含的模板文件 (2)options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,encoding 指定包含页面时所使用的解码集,而parse指定被包含是否作为ftl文件来解析。如果省略了parse选项值,则该选项值默认是true

需求:"早上好,尊敬的 某某 用户!" 这句话在很多页面都有用到,请合理设计!

(1)在resources/templates目录下创建00-head.ftl模版,内容如下

早上好,尊敬的 ${name} 用户!

(2)在resources/templates目录下创建03-include.ftl模版,使用include引入00-head.ftl模版,内容如下


    
    详情页
<#include "00-head.ftl" />

欢迎来到黑马程序员。

(3)在studentcontroller中增加方法

@getmapping("include")
public string include(model model) throws parseexception {
model.addattribute("name", "黑马");
return "03-include";
}

(4)测试

浏览器访问http://localhost:8881/student/include

效果如下

2.4.5 assign指令

它用于为该模板页面创建或替换一个顶层变量

<#assign name = "zhangsan" />

2.4.6 运算符

(1)算数运算符

freemarker表达式中完全支持算术运算,freemarker支持的算术运算符包括:

  • 加法:
  • 减法: -
  • 乘法: *
  • 除法: /
  • 求模 (求余): %

(2)比较运算符

  • =或者==:判断两个值是否相等.
  • !=:判断两个值是否不等.
  • >或者gt:判断左边值是否大于右边值
  • >=或者gte:判断左边值是否大于等于右边值
  • <或者lt:判断左边值是否小于右边值
  • <=或者lte:判断左边值是否小于等于右边值

比较运算符注意

  • =!=可以用于字符串、数值和日期来比较是否相等
  • =!=两边必须是相同类型的值,否则会产生错误
  • 字符串 "x""x ""x"比较是不等的.因为freemarker是精确比较
  • 其它的运行符可以作用于数字和日期,但不能作用于字符串
  • 使用gt等字母运算符代替>会有更好的效果,因为 freemarker会把>解释成ftl标签的结束字符
  • 可以使用括号来避免这种情况,如:<#if (x>y)>

(3)逻辑运算符

  • 逻辑与:&&
  • 逻辑或:||
  • 逻辑非:!

逻辑运算符只能作用于布尔值,否则将产生错误 。

2.4.7 空值处理

(1)缺失变量默认值使用 “!”

  • 使用!要以指定一个默认值,当变量为空时显示默认值
  • 例: ${name!''}表示如果name为空显示空字符串。
  • 如果是嵌套对象则建议使用()括起来
  • 例: ${(stu.bestfriend.name)!''}表示,如果stu或bestfriend或name为空默认显示空字符串。

(2)判断某变量是否存在使用 “??”

用法为:variable??,如果该变量存在,返回true,否则返回false

例:为防止stus为空报错可以加上判断如下:

    <#if stus??>
        <#list stus as stu>
            ......
        
    

2.4.8 内建函数

内建函数语法格式: 变量 ? 函数名称

(1)求集合的大小

${集合名?size}

(2)日期格式化

显示年月日: ${today?date} 显示时分秒:${today?time} 显示日期 时间:${today?datetime} 自定义格式化: ${today?string("yyyy年mm月")}

(3)内建函数c

model.addattribute("point", 102920122);

point是数字型,使用${point}会显示这个数字的值,每三位使用逗号分隔。

如果不想显示为每三位分隔的数字,可以使用c函数将数字型转成字符串输出

${point?c}

(4)将json字符串转成对象

一个例子:

其中用到了 assign标签,assign的作用是定义一个变量。

<#assign text="{'bank':'工商银行','account':'10101920201920212'}" />
<#assign data=text?eval />
开户行:${data.bank}  账号:${data.account}

(5)常见内建函数汇总

?html:html字符转义
?cap_first: 字符串的第一个字母变为大写形式
?lower_case :字符串的小写形式
?upper_case :字符串的大写形式
?trim:去掉字符串首尾的空格
?substring(from,to):截字符串  from是第一个字符的开始索引,to最后一个字符之后的位置索引,当to为空时,默认的是字符串的长度
?lenth: 取长度
?size: 序列中元素的个数
?int: 数字的整数部分(比如 -1.9?int 就是 -1)
?replace(param1,param2):字符串替换  param1是匹配的字符串 param2是将匹配的字符替换成指定字符

内建函数测试demo1

(1)在studentcontroller新增方法:

@getmapping("innerfunc")
public string testinnerfunc(model model) {
    //1.1 小强对象模型数据
    student stu1 = new student();
    stu1.setname("小强");
    stu1.setage(18);
    stu1.setmoney(1000.86f);
    stu1.setbirthday(new date());
    //1.2 小红对象模型数据
    student stu2 = new student();
    stu2.setname("小红");
    stu2.setmoney(200.1f);
    stu2.setage(19);
    //1.3 将两个对象模型数据存放到list集合中
    list stus = new arraylist<>();
    stus.add(stu1);
    stus.add(stu2);
    model.addattribute("stus", stus);
    // 2.1 添加日期
    date date = new date();
    model.addattribute("today", date);
    // 3.1 添加数值
    model.addattribute("point", 102920122);
    return "04-innerfunc";
}

(2)在resources/templates目录下创建04-innerfunc.ftl模版页面:


    
    inner function
    获得集合大小
集合大小:${stus?size}
获得日期
显示年月日: ${today?date}
显示时分秒:${today?time}
显示日期 时间:${today?datetime}
自定义格式化: ${today?string("yyyy年mm月")}

内建函数c
没有c函数显示的数值:${point}
有c函数显示的数值:${point?c}
声明变量assign
<#assign text="{'bank':'工商银行','account':'10101920201920212'}" /> <#assign data=text?eval /> 开户行:${data.bank} 账号:${data.account}

(3)测试

浏览器访问http://localhost:8881/student/innerfunc

效果如下

内建函数测试demo2

需求:遍历学生集合,显示集合总条数,id不要逗号隔开,显示学生的生日(只显示年月日),钱包显示整数并显示单位元,用户姓名做脱敏处理(如果是两个字第二个字显示为星号,例如张三显示为张*,如果大于两个字,中间字显示为星号,例如成吉思汗显示为成*汗,诸葛亮显示为诸*亮)

(1)修改studentcontroller中的list方法,

@getmapping("list")
public string list(model model) throws parseexception {
    dateformat dateformat = new simpledateformat("yyyy-mm-dd hh:mm:ss");
    list list = new arraylist<>();
    list.add(new student(1001,"张三",15, dateformat.parse("2007-10-01 10:00:00"), 1000.11f));
    list.add(new student(1002,"李四",28, dateformat.parse("1994-10-01 10:00:00"), 5000.3f));
    list.add(new student(1003,"王五",45, dateformat.parse("1977-10-01 10:00:00"), 9000.63f));
    list.add(new student(1004,"赵六",62, dateformat.parse("1960-10-01 10:00:00"), 10000.99f));
    list.add(new student(1005,"孙七",75, dateformat.parse("1947-10-01 10:00:00"), 16000.66f));
    model.addattribute("stus",list);
    return "02-list";
}

(2)修改02-list.ftl模版

共${stus?size}条数据:输出总条数

stu.id后面加?c:id不需要逗号分割

stu.birthday后面加?date:生日只输出年月日

stu.money后面加?int:金额取整

姓名需要使用replace和substring函数处理

完整内容如下


    
    列表页面
    
共${stus?size}条数据
<#list stus as stu >
        
序号 id 姓名 所处的年龄段 生日 钱包 是否最后一条数据
${stu_index 1} ${stu.id?c} <#if stu.name?length=2> ${stu.name?replace(stu.name?substring(1), "*")} <#else> ${stu.name?replace(stu.name?substring(1, stu.name?length-1), "*")} <#if stu.age <= 6> 童年 <#elseif stu.age <= 17> 少年 <#elseif stu.age <= 40> 青年 <#elseif stu.age <= 65> 中年 <#else> 老年 ${stu.birthday?date} ${stu.money?int}元 <#if stu_has_next> 否 <#else> 是

(3)测试

浏览器访问http://localhost:8881/student/list

效果如下

2.4.9 静态化

(1)springboot整合freemarker静态化文件用法

编写springboot测试用例

package com.itheima.test;
import com.itheima.freemarker.freemarkerdemoapplication;
import com.itheima.freemarker.entity.student;
import freemarker.template.configuration;
import freemarker.template.template;
import freemarker.template.templateexception;
import org.junit.test;
import org.junit.runner.runwith;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.test.context.springboottest;
import org.springframework.test.context.junit4.springrunner;
import java.io.filewriter;
import java.io.ioexception;
import java.util.*;
@springboottest(classes = freemarkerdemoapplication.class)
@runwith(springrunner.class)
public class freemarkertest {
    //注入freemarker配置类
    @autowired
    private configuration configuration;
    @test
    public void test() throws ioexception, templateexception {
        template template = configuration.gettemplate("04-innerfunc.ftl");
        /**
         * 静态化并输出到文件中   参数1:数据模型     参数2:文件输出流
         */
        template.process(getdata(), new filewriter("d:/list.html"));
        /**
         * 静态化并输出到字节输出流中
         */
        //stringwriter out = new stringwriter();
        //template.process(getdata(), out);
        //system.out.println(out.tostring());
    }
    private map getdata(){
        map map = new hashmap<>();
        student stu1 = new student();
        stu1.setname("小强");
        stu1.setage(18);
        stu1.setmoney(1000.86f);
        stu1.setbirthday(new date());
        //小红对象模型数据
        student stu2 = new student();
        stu2.setname("小红");
        stu2.setmoney(200.1f);
        stu2.setage(19);
        //将两个对象模型数据存放到list集合中
        list stus = new arraylist<>();
        stus.add(stu1);
        stus.add(stu2);
        //向model中存放list集合数据
        map.put("stus",stus);
        //map数据
        map stumap = new hashmap<>();
        stumap.put("stu1",stu1);
        stumap.put("stu2",stu2);
        map.put("stumap",stumap);
        //日期
        map.put("today",new date());
        //长数值
        map.put("point",38473897438743l);
        return map;
    }
}

(2)freemarker原生静态化用法

package com.itheima.freemarker.test;
import com.itheima.freemarker.entity.student;
import freemarker.cache.filetemplateloader;
import freemarker.cache.nullcachestorage;
import freemarker.template.configuration;
import freemarker.template.template;
import freemarker.template.templateexception;
import freemarker.template.templateexceptionhandler;
import java.io.file;
import java.io.filewriter;
import java.io.ioexception;
import java.util.*;
public class freemarkertest {
    public static void main(string[] args) throws ioexception, templateexception {
        //创建配置类
        configuration configuration = new configuration(configuration.version_2_3_22);
        //设置模版加载路径
        //classtemplateloader方式:需要将模版放在freemarkertest类所在的包,加载模版时会从该包下加载
        //configuration.settemplateloader(new classtemplateloader(freemarkertest.class,""));
        string path = java.net.urldecoder.decode(freemarkertest.class.getclassloader().getresource("").getpath(),"utf-8");
        //filetemplateloader方式:需要将模版放置在classpath目录下 目录有中文也可以
        configuration.settemplateloader(new filetemplateloader(new file(path)));
        //设置编码
        configuration.setdefaultencoding("utf-8");
        //设置异常处理器
        configuration.settemplateexceptionhandler(templateexceptionhandler.rethrow_handler);
        //设置缓存方式
        configuration.setcachestorage(nullcachestorage.instance);
        //加载模版
        template template = configuration.gettemplate("templates/04-innerfunc.ftl");
        /**
         * 静态化并输出到文件中   参数1:数据模型     参数2:文件输出流
         */
        template.process(getmodel(), new filewriter("d:/list.html"));
        /**
         * 静态化并输出到字节输出流中
         */
        //stringwriter out = new stringwriter();
        //template.process(getdata(), out);
        //system.out.println(out.tostring());
    }
    public static map getmodel(){
        map map = new hashmap();
        //1.1 小强对象模型数据
        student stu1 = new student();
        stu1.setname("小强");
        stu1.setage(18);
        stu1.setmoney(1000.86f);
        stu1.setbirthday(new date());
        //1.2 小红对象模型数据
        student stu2 = new student();
        stu2.setname("小红");
        stu2.setmoney(200.1f);
        stu2.setage(19);
        //1.3 将两个对象模型数据存放到list集合中
        list stus = new arraylist<>();
        stus.add(stu1);
        stus.add(stu2);
        map.put("stus", stus);
        // 2.1 添加日期
        date date = new date();
        map.put("today", date);
        // 3.1 添加数值
        map.put("point", 102920122);
        return map;
    }
}

3 数据库元数据

3.1 介绍

元数据(metadata)是描述数据的数据。

数据库元数据(databasemetadata)就是指定义数据库各类对象结构的数据。

在mysql中可以通过show关键字获取相关的元数据

show status; 获取数据库的状态
show databases; 列出所有数据库
show tables; 列出所有表
show create database [数据库名]; 获取数据库的定义
show create table [数据表名]; 获取数据表的定义
show columns from ; 显示表的结构
show index from ; 显示表中有关索引和索引列的信息
show character set; 显示可用的字符集以及其默认整理
show collation; 显示每个字符集的整理
show variables; 列出数据库中的参数定义值

也可以从 information_schema库中获取元数据,information_schema数据库是mysql自带的信息数据库,它提供了访问数据库元数据的方式。存着其他数据库的信息。

select schema_name from information_schema.schemata; 列出所有的库
select table_name from information_schema.tables; 列出所有的表

在代码中可以由jdbc的connection对象通过getmetadata方法获取而来,主要封装了是对数据库本身的一些整体综合信息,例如数据库的产品名称,数据库的版本号,数据库的url,是否支持事务等等。

databasemetadata的常用方法:

getdatabaseproductname:获取数据库的产品名称
getdatabaseproductname:获取数据库的版本号
getusername:获取数据库的用户名
geturl:获取数据库连接的url
getdrivername:获取数据库的驱动名称
driverversion:获取数据库的驱动版本号
isreadonly:查看数据库是否只允许读操作
supportstransactions:查看数据库是否支持事务

3.2 搭建环境

(1)导入mysql依赖


    mysql
    mysql-connector-java
    5.1.47

(2)创建测试用例

package com.itheima.test;
import org.junit.before;
import org.junit.test;
import java.sql.*;
import java.util.properties;
public class databasemetadatatest {
    private connection conn;
    @before
    public void init() throws exception {
        properties pro = new properties();
        pro.setproperty("user", "root");
        pro.setproperty("password", "123456");
        pro.put("useinformationschema", "true");//获取mysql表注释
        //pro.setproperty("remarksreporting","true");//获取oracle表注释
        conn = drivermanager.getconnection("jdbc:mysql://127.0.0.1:3306/?useunicode=true&characterencoding=utf8", pro);
    }   
}

3.3 综合信息元数据

(1)获取数据库元信息综合信息

@test
public void testdatabasemetadata() throws sqlexception {
    //获取数据库元数据
    databasemetadata dbmetadata = conn.getmetadata();
    //获取数据库产品名称
    string productname = dbmetadata.getdatabaseproductname();
    system.out.println(productname);
    //获取数据库版本号
    string productversion = dbmetadata.getdatabaseproductversion();
    system.out.println(productversion);
    //获取数据库用户名
    string username = dbmetadata.getusername();
    system.out.println(username);
    //获取数据库连接url
    string userurl = dbmetadata.get;
    system.out.println(userurl);
    //获取数据库驱动
    string drivername = dbmetadata.getdrivername();
    system.out.println(drivername);
    //获取数据库驱动版本号
    string driverversion = dbmetadata.getdriverversion();
    system.out.println(driverversion);
    //查看数据库是否允许读操作
    boolean isreadonly = dbmetadata.isreadonly();
    system.out.println(isreadonly);
    //查看数据库是否支持事务操作
    boolean supportstransactions = dbmetadata.supportstransactions();
    system.out.println(supportstransactions);
}

(2)获取数据库列表

@test
public void testfindallcatalogs() throws exception {
    //获取元数据
    databasemetadata metadata = conn.getmetadata();
    //获取数据库列表
    resultset rs = metadata.getcatalogs();
    //遍历获取所有数据库表
    while (rs.next()) {
        //打印数据库名称
        system.out.println(rs.getstring(1));
    }
    //释放资源
    rs.close();
    conn.close();
}

(3)获取某数据库中的所有表信息

@test
public void testfindalltable() throws exception {
    //获取元数据
    databasemetadata metadata = conn.getmetadata();
    //获取所有的数据库表信息
    resultset rs = metadata.gettables("库名", "%", "%", new string[]{"table"});
    //拼装table
    while (rs.next()) {
        //所属数据库
        system.out.println(rs.getstring(1));
        //所属schema
        system.out.println(rs.getstring(2));
        //表名
        system.out.println(rs.getstring(3));
        //数据库表类型
        system.out.println(rs.getstring(4));
        //数据库表备注
        system.out.println(rs.getstring(5));
        system.out.println("--------------");
    }
}

(4)获取某张表所有的列信息

@test
public void testfindallcolumns() throws exception {
    //获取元数据
    databasemetadata metadata = conn.getmetadata();
    //获取所有的数据库某张表所有列信息
    resultset rs = metadata.getcolumns("库名", "%", "表名","%");
    while(rs.next()) {
        //表名
        system.out.println(rs.getstring("table_name"));
        //列名
        system.out.println(rs.getstring("column_name"));
        //类型码值
        system.out.println(rs.getstring("data_type"));
        //类型名称
        system.out.println(rs.getstring("type_name"));
        //列的大小
        system.out.println(rs.getstring("column_size"));
        //小数部分位数,不适用的类型会返回null
        system.out.println(rs.getstring("decimal_digits"));
        //是否允许使用null
        system.out.println(rs.getstring("nullable"));
        //列的注释信息
        system.out.println(rs.getstring("remarks"));
        //默认值
        system.out.println(rs.getstring("column_def"));
        //是否自增
        system.out.println(rs.getstring("is_autoincrement"));
        //表中的列的索引(从 1 开始
        system.out.println(rs.getstring("ordinal_position"));
        system.out.println("--------------");
    }
}

3.4 参数元数据

参数元数据(parametermetadata):是由preparedstatement对象通过getparametermetadata方法获取而 来,主要是针对preparedstatement对象和其预编译的sql命令语句提供一些信息,parametermetadata能提供占位符参数的个数,获取指定位置占位符的sql类型等等 以下有一些关于parametermetadata的常用方法:

getparametercount:获取预编译sql语句中占位符参数的个数
@test
public void testparametermetadata() throws exception {
    string sql = "select * from health.t_checkgroup where id=? and code=?";
    preparedstatement pstmt = conn.preparestatement(sql);
    pstmt.setstring(1, "7");
    pstmt.setstring(2, "0003");
    //获取parametermetadata对象
    parametermetadata parammetadata = pstmt.getparametermetadata();
    //获取参数个数
    int paramcount = parammetadata.getparametercount();
    system.out.println(paramcount);
}

3.5 结果集元数据

结果集元数据(resultsetmetadata):是由resultset对象通过getmetadata方法获取而来,主要是针对由数据库执行的sql脚本命令获取的结果集对象resultset中提供的一些信息,比如结果集中的列数、指定列的名称、指 定列的sql类型等等,可以说这个是对于框架来说非常重要的一个对象。 以下有一些关于resultsetmetadata的常用方法:

getcolumncount:获取结果集中列项目的个数
getcolumntype:获取指定列的sql类型对应于java中types类的字段
getcolumntypename:获取指定列的sql类型
getclassname:获取指定列sql类型对应于java中的类型(包名加类名
@test
public void testresultsetmetadata() throws exception {
    string sql = "select * from health.t_checkgroup where id=?";
    preparedstatement pstmt = conn.preparestatement(sql);
    pstmt.setstring(1, "7");
    //执行sql语句
    resultset rs = pstmt.executequery();
    //获取resultsetmetadata对象
    resultsetmetadata metadata = rs.getmetadata();
    //获取查询字段数量
    int columncount = metadata.getcolumncount();
    system.out.println("字段总数量:"  columncount);
    for (int i = 1; i <= columncount; i  ) {
        //获取表名称
        system.out.println(metadata.getcolumnname(i));
        //获取java类型
        system.out.println(metadata.getcolumnclassname(i));
        //获取sql类型
        system.out.println(metadata.getcolumntypename(i));
        system.out.println("----------");
    }
}

4 代码生成器环境搭建

4.1 创建maven工程

创建maven工程并导入以下依赖


    11
    
    utf-8
    utf-8
    
    11
    11


    
        org.freemarker
        freemarker
        2.3.23
    
    
        mysql
        mysql-connector-java
        5.1.47
    
    
        org.projectlombok
        lombok
        1.18.8
    
    
        org.apache.commons
        commons-lang3
        3.10
    

目录结构如下




基于循环变量法的流程2

自学既可以让你觉得很美妙又可以让你觉得很沮丧。如果方式正确,你可以用短短几个月教会自己任何事情。但是如果做得不好,自学会让你觉得充满压力,这种压力如噩梦般缠绕你。我想分享一些我的技巧,从而做到第一种自学,而避免后一种情况。

我自学的内容十分的广泛。我自学了如何编程,创建图像(2d和3d),如何设计网页和博客。我在五年级的时候就自己学习了基本的化学知识,并在学校正式上课教学之前阅读了很多有关化学知识的书籍。虽然,我不记得了,但是我的父母告诉我,在上学之前我就已经学会了要去阅读。

自学对于任何你想要学习的知识或者技能都是十分有益的。以下有一些技能或许是你想要学习的:

学习一门语言;自学数学或其他学科的分支;学习做饭;掌握一项新运动;在公众场所演讲;训练你的沟通技巧等等。在短短三个月内要学会一些东西,靠摸着石头过河是不够的。以下就是我发现的自学中非常重要的原则:

第一,清楚你的学习目的。学习之后,你应当能做什么,实现什么或者知道什么?我自学时效果最好的尝试通常有具体应用。对知识的要求越精确,学习效率就越高。举个例子,你是想学西班牙语,是想要说一两句呢,还是要进行95%的基本对话?

第二,买一本教科书。网上的文章和零散的资源可以提供帮助,但扎实的基础要比这好得多。每种技能和知识的分支都有成百上千种教科书。书本可以让你靠自己摸索无法获得的知识基础。

第三,确定要学的知识和技能。在开始之前知道你需要什么背景技能,这样你就可以事先去学习,或者在学习的过程中掌握你所需要学习的技能。

第四,截止日期决定了时间投入。如果你想在三个月内学会某样东西,这可能意味着一周一小时或者一天几个小时的投入。你的截止日期决定了你需要投入多少时间。

第五,耐心是一种美德。自学和在课堂学习不一样,甚至更难。当你进入了死胡同而且没有人指点你的时候,你会觉得很难。你自学的能力和想要放弃时依然不懈尝试的能力紧密相关。

第六,回归基础。任何知识和技能都基于一些核心的理解或能力。复杂的算法基于循环和变量等简单的编程概念,任何舞蹈都基于一些核心的步法,掌握基础之后,学习高阶的东西就会相对来说简单一点。

第七,以失财为目标。做足够多的尝试,因为你的失败率会很高。人很容易回去重复解决相同的东西,但这对你没有任何帮助。要在每个练习中,加入新的东西,这样你的学习曲线不会趋于平坦。

第八,15分钟法则。如果你被某个问题难住了,给自己15分钟完全专注于解决这个问题。如果时间到了,还没有解决这个问题,就休息一会。少于15分钟,说明你缺少学习必须的持久性。给自己一个解决问题的时间界定,可以激活你的创造力,从而解决问题。

第九,目的是什么?必要性是最好的老师。如果你不想学习一件事,那你遇到挫折的时候就很难坚持不懈。让要学习的东西成为你所设目标的内在组成部分,这样督促你学习的就不只是随机的兴趣。而且驱使你去学习的动力。

第十,运用你的社交能力。去寻找和你志同道合的伙伴,你们相互督促,共同进步。让自己沉浸在这群人里,虽然他们的能力不能沉浸到你身上,但是他们可以给你提供帮助,提供你所需要的东西。

今天就给大家整理到这里了。学习是要持之以恒的,唯有坚持可以达到目的。不要在意别人对你不友好的眼光,因为总有人会知道你在改变。

--翻译于高效学习法

基于循环变量法的流程3

作者:奥斯瓦尔德·坎佩萨托(oswald campesato)

来源:华章科技

python 支持for循环,它的语法与其他语言(如javascript 或java)稍有不同。下面的代码块演示如何在python 中使用for循环来遍历列表中的元素:

上述的代码段是将三个字母分行打印的。你可以通过在print语句的后面添加逗号“,”将输出限制在同一行显示(如果指定打印的字符很多,则会“换行”),代码如下所示:

当你希望通过一行而不是多行显示文本中的内容时,可以使用上述形式的代码。python 还提供了内置函数reversed(),它可以反转循环的方向,例如:

注意,只有当对象的大小是确定的,或者对象实现了_reversed_()方法的时候反向遍历的功能才有效。

01 使用tryexcept的for循环

清单1 的stringtonums.py说明了如何对一组从字符串转换而来的整数求和。

  • 清单1 stringtonums.py
line = '1 2 3 4 10e abc'
sum = 0
invalidstr = ""
print('string of numbers:',line)
for str in line.split(" "):
try:
sum = sum   eval(str)
except:
invalidstr = invalidstr   str   ' '
print('sum:', sum)
if(invalidstr != ""):
print('invalid strings:',invalidstr)
else:
print('all substrings are valid numbers')

清单1 首先初始化变量line、sum和invalidstr,然后显示line的内容。接下来将line中的内容分割为单词,然后通过try代码块逐个将单词的数值累加到变量sum 中。如果发生异常,则将当前str的内容追加到变量invalidstr。

当循环执行结束,清单1 打印出数值单词的和,并在后面显示非数值单词。它的输出如下所示:

02 指数运算

清单2 的nth_exponet.py说明了如何计算一组整数的幂。

  • 清单2 nth_exponet.py
maxpower = 4
maxcount = 4
def pwr(num):
prod = 1
for n in range(1,maxpower 1):
prod = prod*num
print(num,'to the power',n, 'equals',prod)
print('-----------')
for num in range(1,maxcount 1):
pwr(num)

清单2 中有一个pwr()函数,其参数为一个数值。此函数中的循环可打印出参数的1 到n次方,n的取值范围在1到maxcount 1之间。

代码的第二部分通过一个for循环调用pwr()函数从1到maxcount 1的值。它的输出如下所示:

03 嵌套的循环

清单3 的triangular1.py说明了如何打印一行连续整数(从1开始),其中每一行的长度都比前一行大1。

  • 清单3 triangular1.py
max = 8
for x in range(1,max 1):
for y in range(1,x 1):
print(y,'', end='')
print() 

清单3 首先初始化max变量为8,之后通过变量x从1到max 1执行循环。内层循环有一个值为从1到x 1的循环变量y,并打印y的值。它的输出如下所示:

04 在for循环中使用split()函数

python 支持各种便捷的字符串操作相关函数,包括split()函数和join()函数。在需要将一行文本分词化(即“分割”)为单词,然后使用for循环遍历这些单词时,split()函数非常有用。

join()函数与split()函数相反,它将两个或多个单词“连接”为一行。通过使用split()函数,你可以轻松地删除句子中多余的空格,然后调用join()函数,使文本行中每个单词之间只有一个空格。

1. 使用split()函数做单词比较

清单4 的compare2.py说明了如何通过split()函数将文本字符串中的每个单词与另一个单词进行比较。

  • 清单4 compare2.py
x = 'this is a string that contains abc and abc'
y = 'abc'
identical = 0
casematch = 0
for w in x.split():
if(w == y):
identical = identical   1
elif (w.lower() == y.lower()):
casematch = casematch   1
if(identical > 0):
print('found identical matches:', identical)
if(casematch > 0):
print('found case matches:', casematch)
if(casematch == 0 and identical == 0):
print('no matches found')

清单4 通过split()函数对字符串x中的每个单词与单词abc进行比较。如果单词精确匹配,就将identical变量加1 ;否则就尝试不区分大小写进行比较,若匹配就将casematch变量加1。

清单4 的输出如下所示:

2. 使用split()函数打印指定格式的文本

清单5 的fixedcolumncount1.py 说明了如何打印一组设定固定宽度的字符串。

  • 清单5 fixedcolumncount1.py
import string
wordcount = 0
str1 = 'this is a string with a set of words in it'
print('left-justified strings:')
print('-----------------------')
for w in str1.split():
print('%-10s' % w)
wordcount = wordcount   1
if(wordcount % 2 == 0):
print("")
print("\n")
print('right-justified strings:') 
print('------------------------') 
wordcount = 0
for w in str1.split():
print('s' % w)
wordcount = wordcount   1
if(wordcount % 2 == 0):
print()

清单5 首先初始化变量wordcount和str1,然后执行两个for循环。第一个for 循环对str1的每个单词进行左对齐打印,第二个for循环对str1的每个单词进行右对齐打印。在每个循环中当wordcount是偶数的时候就输出一次换行,这样每打印两个连续的单词之后就换行。清单5 的输出如下所示:

3. 使用split()函数打印固定宽度的文本

清单6 的fixedcolumnwidth3.py说明了如何打印固定宽度的文本。

  • 清单6 fixedcolumnwidth3.py
import string
left = 0
right = 0
columnwidth = 8
str1 = 'this is a string with a set of words in it and it will be split into a fixed column width'
strlen = len(str1)
print('left-justified column:') 
print('----------------------') 
rowcount = int(strlen/columnwidth)
for i in range(0,rowcount):
left = i*columnwidth
right = (i 1)*columnwidth-1
word = str1[left:right]
print("%-10s" % word)
# check for a 'partial row'
if(rowcount*columnwidth < strlen):
left = rowcount*columnwidth-1;
right = strlen
word = str1[left:right]
print("%-10s" % word)

清单6 初始化整型变量columnwidth和字符串类型变量str1。变量strlen是str1的长度,变量rowcount是strlen除以columnwidth的值。之后通过循环打印rowcount行,每行包含columnwidth个字符。代码的最后部分输出所有“剩余”的字符。清单6 的输出如下所示:

4. 使用split()函数比较文本字符串

清单7 的comparestrings1.py说明了如何判断一个文本字符串中的单词是否出现在另一个文本字符串中。

  • 清单7 comparestrings1.py
text1 = 'a b c d'
text2 = 'a b c e d'
if(text2.find(text1) >= 0):
print('text1 is a substring of text2')
else:
print('text1 is not a substring of text2')
substr = true
for w in text1.split():
if(text2.find(w) == -1):
substr = false
break
if(substr == true):
print('every word in text1 is a word in text2')
else:
print('not every word in text1 is a word in text2')

清单7 首先初始化两个字符串变量text1和text2,然后通过条件逻辑判断字符串text2是否包含了text1(并输出相应打印信息)。

清单7 的后半部分通过一个循环遍历字符串text1中的每个单词,并判断其是否出现在text2中。如果发现有匹配失败的情况,就设置变量substr为false,并通过break语句跳出循环,提前终止for循环的执行。最后根据变量substr的值打印对应的信息。清单7 的输出如下所示:

05 用基础的for循环显示字符串中的字符

清单8 的stringchars1.py说明了如何打印一个文本字符串中的字符。

  • 清单8 stringchars1.py
text = 'abcdef'
for ch in text:
print('char:',ch,'ord value:',ord(ch))
print

清单8 的代码简单直接地通过一个for循环遍历字符串text并打印它的每个字符以及字符的ord值(ascii 码)。清单8 的输出如下所示:

06 join()函数

另一个去掉多余空格的方法是使用join()函数,代码示例如下所示:

split()函数将一个文本字符串“分割”为一系列的单词,同时去掉多余的空格。接下来join()函数使用一个空格作为分隔符将字符串text1中的单词连接在一起。上述代码的最后部分使用字符串xyz替换空格作为分隔符,执行相同的连接操作。上述代码的输出如下:

关于作者:奥斯瓦尔德·坎佩萨托(oswald campesato),专门研究深度学习、java、android和tensorflow。他是25本书的作者/合著者。

本文摘编自《机器学习入门:python语言实现》,经出版方授权发布。(isbn:9787111695240)

《机器学习入门:python语言实现》

推荐语:适读人群:机器学习及python初学者。本书旨在为读者提供与机器学习有关python3的基本编程概念。前4章快速介绍了python 3、numpy和pandas。第5章介绍了机器学习的基本概念。第6章主要介绍机器学习分类器,例如逻辑回归、knn、决策树、随机森林和svm。第7章介绍了自然语言处理和强化学习。本书还提供了基于keras的代码示例作为理论讨论的补充。此外还为正则表达式、keras和tensorflow 2提供了单独的附录。

阅读全文
返回顶部
网站地图