微服务实战笔记-学成在线-day04

知识点:

  1. freemarker
  2. GridFS
  3. springBoot + vue 实现文件上传下载

freemarker

简单介绍

freemarker是一种类似于jsp的免费的java模板引擎,他可以基于模板和数据生成数据(可以是html,email,world,excel等等)

类似于freemarker的模板引擎还有jsp,Thymeleaf,Velocity等

数据模型

数据模型在java中可以是基本类型,也可以是List,Map,Pojo等复杂类型

模板

通过数据模型和模板一起生成最终的文件

下面提供一个官方的样例:

数据模型:
在这里插入图片描述
模板:
在这里插入图片描述

输出文件:

在这里插入图片描述

freemarker在springBoot环境中的配置文件

spring:

​ freemarker:

​ cache: false #关闭模板缓存

​ settings:

​ template_update_delay: 0 #检查模板更新延迟时间,设置为0表示立即检查

核心指令

  1. ${name} 从数据模型中获取name属性,name可以是pojo的属性,也可以是map中的一个key

    Hello World! Hello ${name}!
  2. List 指令 语法 <#list lst as l >

    _index:得到循环的下标,使用方法是在stu后边加"_index",它的值是从0开始

     <table>
         <tr>
             <td>序号</td>
             <td>姓名</td>
             <td>年龄</td>
             <td>钱包</td>
         </tr>
         <#list stus as stu>
         <tr>
             <#--stu_index 为内置属性,代表当前循环下标 -->
             <td>${stu_index + 1}</td>
             <td>${stu.name}</td>
             <td>${stu.age}</td>
             <td>${stu.mondy}</td>
         </tr>
         </#list>
     </table>
     ```
    
    
    
    
    
    
  3. 遍历map中的数据

​ freemarker没有提供直接遍历map的指令,但是可以通过list指令遍历map.keys来实现对map的遍历

<table>
    <tr>
        <td>序号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>钱包</td>
    </tr>
    <#list stuMap?keys as k>
        <tr>
        <td>${k_index + 1}</td>
        <td>${stuMap[k].name}</td>
        <td>${stuMap[k].age}</td>
        <td >${stuMap[k].mondy}</td>
        </tr>
    </#list>
</table>
  1. if指令 <#if >
<table>
    <tr>
        <td>姓名</td>
        <td>年龄</td>
        <td>钱包</td>
    </tr>
    <#list stus as stu>
    <tr>
        <td 
            <#if stu.name =='小明'>style="background:red;"</#if>
    	>${stu.name}</td>
        <td>${stu.age}</td>
        <td >${stu.mondy}</td>
    </tr>
    </#list>
</table>
  1. 判断是否为空 <#if stus??>

    <#if stus??>
        <#list stus as stu>
        ......
        </#list>
    </#if>
    
  2. 空值处理 ,当数据为空的时候给与默认值

    缺失变量默认值使用 “!” 使用!要以指定一个默认值,当变量为空时显示默认值。

    例:${name!’’}表示如果name为空显示空字符串。

    如果是嵌套对象则建议使用()括起来。

    例: ${(stu.bestFriend.name)!’’}表示,如果stu或bestFriend或name为空默认显示空字符串。

  3. 内建函数

    内建函数是freemarker提供的一些函数 语法格式为 变量 + ? + 函数名称

    • 获取集合的大小 ${集合名?size}

    • 日期格式化

      • 显示年月日: ${today?date}
      • 显示时分秒:${today?time}
      • 显示日期+时间:${today?datetime}
      • 自定义格式化: ${today?string(“yyyy年MM月”)}
    • 内建函数c

      map.put(“point”, 102920122);
      point是数字型,使用${point}会显示这个数字的值,不并每三位使用逗号分隔。
      如果不想显示为每三位分隔的数字,可以使用c函数将数字型转成字符串输出
      ${point?c}

      没加c之前的输出 102,920,122

      加了之后的输出 102920122

    • 将json字符串转成对象(定义一个常量,assign标签)

      <#assign text="{‘bank’:‘工商银行’,‘account’:‘10101920201920212’}" />
      <#assign data=text?eval />
      开户行: d a t a . b a n k 账 号 : {data.bank} 账号: data.bank{data.account}

    脱离spring单独使用freemarker

    基于模板文件生成文件
    //基于模板生成静态化文件
    @Test
    public void testGenerateHtml() throws IOException, TemplateException {
    //创建配置类
    Configuration configuration=new Configuration(Configuration.getVersion());
    //设置模板路径
    String classpath = this.getClass().getResource("/").getPath();
    configuration.setDirectoryForTemplateLoading(new File(classpath + "/templates/"));
    //设置字符集
    configuration.setDefaultEncoding("utf‐8");
    //加载模板
    Template template = configuration.getTemplate("test1.ftl");
    //数据模型
    Map<String,Object> map = new HashMap<>();
    map.put("name"
    ,
    "黑马程序员");
    //静态化
    String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
    //静态化内容
    System.out.println(content);
    InputStream inputStream = IOUtils.toInputStream(content);
    //输出文件
    FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.html"));
    int copy = IOUtils.copy(inputStream, fileOutputStream);
    }
    
    基于字符串生成
    //基于模板字符串生成静态化文件
    @Test
    public void testGenerateHtmlByString() throws IOException, TemplateException {
    //创建配置类
    Configuration configuration=new Configuration(Configuration.getVersion());
    //模板内容,这里测试时使用简单的字符串作为模板
    String templateString=
    "" +
    "<html>\n" +
    " <head></head>\n" +
    " <body>\n" +
    " 名称:${name}\n" +
    " </body>\n" +
    "</html>";
    //模板加载器
    StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
    stringTemplateLoader.putTemplate("template"
    ,templateString);
    configuration.setTemplateLoader(stringTemplateLoader);
    //得到模板
    Template template = configuration.getTemplate("template"
    ,
    "utf‐8");
    //数据模型
    Map<String,Object> map = new HashMap<>();
    map.put("name"
    ,
    "黑马程序员");
    //静态化
    String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
    //静态化内容
    System.out.println(content);
    InputStream inputStream = IOUtils.toInputStream(content);
    //输出文件
    FileOutputStream fileOutputStream = new FileOutputStream(new File("d:/test1.html"));
    IOUtils.copy(inputStream, fileOutputStream);
    }
    

GridFS

GridFS简介

GridFS是MongoDB提供的用于持久化存储文件的模块,CMS使用MongoDB存储数据,使用GridFS可以快速集成开发。
它的工作原理是:
在GridFS存储文件是将文件分块存储,文件会按照256KB的大小分割成多个块进行存储,GridFS使用两个集合(collection)存储文件,一个集合是chunks, 用于存储文件的二进制数据;一个集合是files,用于存储文件的元数据信息(文件名称、块大小、上传时间等信息)。从GridFS中读取文件要对文件的各各块进行组装、合并。
详细参考:https://docs.mongodb.com/manual/core/gridfs/

存文件
// 需要使用spring中的gridFsTemplate
@Test
public void testGridFs() throws FileNotFoundException {
    //要存储的文件
    File file = new File("d:/index_banner.html");
    //定义输入流
    FileInputStream inputStram = new FileInputStream(file);
    //向GridFS存储文件 
    ObjectId objectId = = gridFsTemplate.store(inputStram,
    "轮播图测试文件01", "");
    //得到文件ID
    String fileId = objectId.toString();
    System.out.println(file);
}
取文件

取文件比存文件麻烦一点,首先需要配置GridFSBucket,这个对象的作用是用于打开下载流

配置类

@Configuration
public class MongoConfig {
    @Value("${spring.data.mongodb.database}")
    String db;
    @Bean
    public GridFSBucket getGridFSBucket(MongoClient mongoClient){
        MongoDatabase database = mongoClient.getDatabase(db);
        GridFSBucket bucket = GridFSBuckets.create(database);
        return bucket;
    }
}

测试类

@SpringBootTest
@RunWith(SpringRunner.class)
public class GridFsTest {
    @Autowired
    GridFsTemplate gridFsTemplate;
    @Autowired
    GridFSBucket gridFSBucket;
    @Test
    public void queryFile() throws IOException {
        String fileId = "5b9c54e264c614237c271a99";
        //根据id查询文件
        GridFSFile gridFSFile =    gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
        //打开下载流对象
        GridFSDownloadStream gridFSDownloadStream =
        gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
        //创建gridFsResource,用于获取流对象
        GridFsResource gridFsResource = new GridFsResource(gridFSFile,gridFSDownloadStream);
        //获取流中的数据
        String s = IOUtils.toString(gridFsResource.getInputStream(),"UTF‐8");
        System.out.println(s);
	}
}

springBoot + vue 实现文件上传下载

在这里插入图片描述

后台代码


@RequestMapping("/template")
@Controller
public class CmsTemplateFileController extends BaseController implements CmsTemplateFileControllerApi {

    @Autowired
    private CmsTemplateService cmsTemplateService;

    @Override
    @PostMapping("/uploadTemplate/{id}")
    @ResponseBody
    public ResponseResult uploadTemplate(@PathVariable("id") String templateId, @RequestParam("file") MultipartFile file) {
    	// 调用上一个知识点的内容将文档信息存储到GridFS中
        return cmsTemplateService.uploadTemplate(templateId, file);
    }

    @Override
    @GetMapping("/downTemplate/{id}")
    public void downTemplate(@PathVariable("id") String templateId,@RequestParam("fileName") String fileName) {
        QueryResult<String> result = cmsTemplateService.queryTemplate(templateId);
        List<String> list = result.getList();
        if (list.size() > 0) {
            String templateFileContent = list.get(0);
            try {
                response.setHeader("content-type", "application/octet-stream");
                // 设置charset=GBK 保证下载的文件名显示不乱码
                response.setContentType("application/octet-stream;charset=GBK");
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"), "iso-8859-1"));
                IOUtils.write(templateFileContent,response.getOutputStream(),"utf-8");
                response.getOutputStream().flush();
            } catch (IOException e) {
                ExceptionCast.cast(CmsCode.CMS_TEMPLATE_FILE_DOWN_FAILD);
            }
        }
    }

}

前端代码

 <!-- template部分关键代码 -->
<el-table-column label="模板" width="160">
 <template slot-scope="page">
    <el-upload
      :limit="1"
      ref="upload"
      accept=".ftl"
      :action="uploadUrl + page.row.templateId"
      :on-success="uploadSuccess"
      style="float:left;" :show-file-list="false" >
      <el-button
        size="small" type="text">上传
      </el-button>
    </el-upload>
    <el-button v-if="page.row.templateFileId" size="small" 
    	type="text" style="float:left;margin-left:10px;"
               @click="downTemplate(page.row)">下载
    </el-button>
  </template>
</el-table-column>


 		//script 部分关键代码
     // 加载文件信息到右侧文本框内
      changeRow: function (newRow, oldRow) {
        if (newRow) {
          cmsApi.template_queryFile(newRow.templateId).then(res => {
            if (res.list && res.list.length) {
              this.fileContent = res.list[0]
            } else {
              this.fileContent = ''
            }
          })
        } else {
          this.fileContent = ''
        }
      },
      // 上传之前的处理
      uploadSuccess: function (res) {
        if(res.success){
          this.$message.success('上传成功!')
        }else if(res.message){
          this.$message.error(res.message)
        }else{
          this.$message.error("上传失败")
        }
      },
      // 下载模板
      downTemplate(template) {
        cmsApi.template_downloadFile(template.templateId, template.templateName);
      }

		// cmsApi 中与文件上传下载有关的api
		export const template_uploadFile_URL = () =>{
		  return apiUrl+'/cms/template/uploadTemplate/'
		};
		// 查询文件内容
		export const template_queryFile = (id) =>{
		  return http.requestGet(apiUrl+'/cms/template/queryTemplate/'+id)
		};
		// 文件下载
		export const template_downloadFile = (id,fileName) =>{
		  // 需要注意的是这一并不是通过http.requestGet 去调用get请求,
		  // 而是通过 window.location.href的方式
		  // 否则下载的文件不会直接保存到本地,
		  // 除了这种方式以外还可以用window.open(url) 去解决这个问题
		  let url = apiUrl+'/cms/template/downTemplate/'+id+'?fileName='+fileName+'.ftl'
		  //window.location.href = url
		  window.open(url)
		};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值