传智健康

项目介绍

​ 健康管理机构的业务系统

​ 传统的互联网项目(后端系统,前端微信网页)

开发人员应该需要的资料

​ 1.需求说明书PRD【含功能大纲,功能详情,流程图,性能需求】、产品原型图

​ 2.UI:原型图并非最终效果图,最终要过要以UI为准。所以如果有了也需要拿到

​ 3.与前端工作人员对接接口名等参数

开发过程

  • 需求分析:产品人员做,产出PRD(含功能大纲,功能详情,流程图,性能需求)、产品原型图

  • 设计(概设和详设): 架构师做,产出概设和详设(状态机,类图,时序图)

  • 编码 : 程序员,产出功能代码(源代码,功能的单元测试代码)

  • 测试 :测试人员,产出测试报告(测试用例[使用中的各种情况],功能测试报告,性能测试报告,安全测试报告,集成测试报告)

  • 运维 : 程序员,对功能进行升级维护

在这里插入图片描述

项目结构图

待解决问题

1.搞清楚Controller、RestController、ResponseBody的区别(已解决)

项目BUG汇总

1.报错:找不到父工程中的版本1.0-SNAPSHOT

原因:由于相互依赖,打包的时候找不到上一个依赖包

解决:首次打包顺序:domain–> 父工程

2.报错:控制层成员变量正常注入时空指针

原因:开启zk的时候 出现了线程阻塞

解决:重启zk,注意不要让光标停止。右键取消

3.报错: 业务层成员变量注入为null

​ 业务层的东西多半都是jar包 所以直接自动注入即可

4.报错:

Failed to write HTTP message: 				org.springframework.http.converter.HttpMessageNotWritableException: No converter found for return value of type: class com.wz.result.Result

​ 原因:返回结果不能正常转换为json

​ 解决: 需要json依赖包

  1. 业务层可以正常获得结果 在返回到控制层时报错 超时

    原因:网络波动与自己电脑有关

    解决: 在业务层和控制层都添加timeout的时长

  2. 动态sql语句报错:java.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1).

    原因:1)在动态sql中注释语句

    ​ 2)只能只用concat的方式进行拼接字符串

    解决: where code = #{value} or name like CONCAT(CONCAT(’%’, #{value}), ‘%’)

<select id="findAllCheckItem" resultType="CheckItem" parameterType="string">SELECT * FROM t_checkitem//注意:此处的value  必须与string的getvalue方法名一致,如果要使用其他的名字 那么要使用@param指定变量名<if test="value!=null and value.length>0">where  code = #{value} or name like CONCAT(CONCAT('%', #{value}), '%')</if>ORDER BY id DESC
</select>

7.sql错误,Duplicate entry ‘xxx’ for key ‘PRIMARY’

原因:在操作数据库的时候,同一数据的主键进行了增删操作 (同事务中)

解决:逻辑错误,检查逻辑或者sql语句是否与逻辑一致

8.前台状态码400 后台HTTP 转换失败

​ 原因:前台向后台传输的参数必须与后台@RequestBody的一致,否则报错

​ 解决: 传入后台所需的参数

9.前端415错误 ,不是application/json类型

​ 原因:依赖包错误导致

​ 解决:使用完整的json类型依赖包

10.在使用freemarker的hashmap进行存储的时候, 不能使用object存储实体类对象,会导致map.put不能封装实体类中的实体类

11.interval = window.setInterval(timer,100);方法时, 该调用器方法不可以为timer() 否则只执行一次!!

12.一切正常。设置过,也确认过权限被移除,但是还是可以正常操作被移除权限。

​ 原因:使用hasAuthority而不是hasPermission。

​ 解决:后台使用注解设置权限的时候 ,是使用hasAuthority而不是hasPermission。

@PreAuthorize("hasAuthority('CHECKITEM_EDIT')")

13.(接上一个bug)该用户没有该权限但是没有被拦截仍然可以使用的情况

​ 原因:在使用spring security安全框架的时候 web.xml配置文件不可以同时扫描,会导致权限不生效。

​ 解决:使用dispatcher扫描器直接扫描全部配置文件,且不可以在spring中使用import标签导入

项目注意事项汇总

1.父工程中指定了必定继承的依赖,那么子工程中不能再指定,否则报错。

2.web.xml中的标签是存在顺序的

3.dubbo注解扫包底层会自动扫描component及其子注解,故可以不使用spring扫包

​ 【建议加上spring扫包,因为如果还需要使用到其他spring注解会报错】

4.设置web.xml访问路径为/ 必须配置静态资源过滤

5.业务层的dao对象只能用autowared的方式自动注入,不能远程注入,否则为null

6.疑问: 为什么使用了ssm result对象还要new不用自动注入?

​ 并不是所有的类都要交给容器来管理,像这种频繁创建的类都交给容器 容器会裂开的。

为什么dao不分为三层架构?

答:重新分解一层占用网咯资源 没有必要

7.由于是使用的post方式,所以在方法的参数上 必须使用@RequestBody来自动注入

8.dao中的sql语句 $#的区别: #在编译的时候会加上‘ ’ 另一个不会,传什么值就会存入什么值 不加 ‘ ’ 【高频面试】

9.如果dao写入数据库时出现乱码,在jdbc的url末尾拼接‘ ?characterEncoding=utf8’

10.业务层中@Service和@Trasactional一起使用时,需要对@Service指定Interfaceclass或interfaceName 在zk中生成实体对象供访问

11.为什么在后端使用requestBody可以正常接续json数据? 因为在前端页面的contentType中指定的时是application/json 这一步注解底层帮我们指定了 所以可以

12.前端的绝大多数方法都是异步方法。

13.在使用JDBC配置文件时,必须在url项加上增强型后缀。

14.如果使用了父类框架进行远程调用,必须用该成员变量的set方法注入 否则不生效为null

15.在对mybatis进行查询时,查询的total为1 但是在mybatis中实际上查询的是0 只是这个0依然也是一条记录,所以total是1

16.校验规则三部曲

​ 1.输入过程校验

​ 2.提交表单校验

​ 3.后台校验 后台校验如果需要用到网络远程传输 如dubbo 那么写在控制层。其余情况可以些在业务层,可以方便打包复用。

  1. 每一张表都必须要有明确的字段含义!

18.redis中的值如果有过期时间,当过期之后,redis的key仍然是存在。只是拿不到这个key的值了。redis底层有一个200ms的定时清理器进行清理这些已经过期的key

19.在mybatis的插入sql语句中 useGenerate=true keyproperty=“表字段名” 可以取代selectKey来获取主键

项目解决技巧

1.如果遇到jar包冲突,可以选择删除对应jar包的updated文件(建议删除本地仓库中全部带有updated的文件)

2.在dubbo中使用事务,要在业务层的service注解中使用属性interfaceClass=类名.class定义,如果不定义就会去zk的注册中心中去找到代理对象,只有定义过才会在注册中心中有这样一个包名相同的对象

3.VUE内置的输出弹框 this.$message.error/success/info(" ") ;

4.前端代码post请求参数超过一个,可以在方法后面添加?以get的形式传输,后端使用多个参数接收,?后的参数不加@RequestBody 的json来接收

5.在百度搜索maven项目依赖包 以Maven开头 依赖包在后可以快速找到

6.在vue中 ,可以对{}类型的对象 使用[‘key’]的方式进行赋值。作为key存在, 有覆盖,无创建 这是一种js语法

    if(vali) { //校验规则let temp = [];  //存储临时变量this.checkitemIds.forEach(item => {  //变量被勾选的检查项temp[temp.length] = {'id': item}; //起使索引是0 每添加一个元素索引长度就+1});this.formData['checkItems'] =temp; //完成赋值// 只要是一个对象类型就可以使用[]进行赋值,有覆盖,无创建} //完成赋值 
// 只要是一个对象类型就可以使用[]进行赋值,有覆盖,无创建

7.使用freemarker

​ 注意事项:1.需要的占位符每一个循环变量都不能为空

​ 2.占位符符号不能写错

项目规范

1.所有的异常都由控制层统一接收处理,最好是封装一个类来统一返回

2.如果有字符串的信息,尽量使用静态final类来定义调用,而不是直接硬编码

3.三部曲验证,最后一步都在控制层进行控制,避免dubbo远程在业务层验证影响效率

源码分析

1.dubbo 扫包标签 在底层会对component注解进行加载,所以如果仅适用了component不需要使用spring扫包也是可以使用的 【component实际上是controller,service,repository的父类】

2.在父类中 想要对私有成员变量进行注入 AutoWare的支持在父类中进行注入

​ 但是使用dubbo的远程注入 是不可以的,因为源码有限制,只能以set方法开头的方法进行远程注入

故: 定义成员变量,使用起set方法实现注入

3.每次在使用ZK的时候都会生成 dubbo的节点,如果不指定interfaceName名字(全路径名)/interfaceClass(类名.class) 在java底层会…?

4.mybatis底层有两种取参数名的方式

@Param 和 //参数名 如果不使用注解 JVM在底层会首先尝试使用这个名字的.class文件 如果找到就可以使用 如果没有找到就会以arg0 arg1 等名字进行解析 能否找到与电脑有关。

​ 统一规范,在使用单个变量名的时候要使用注解的方式

5.PageHelper 分页插件的 start方法 底层是使用的threadLocal 共享内存区

​ 所以在查找方法的时候 才会去共享区拿到看似毫不相关的 当前页和每页大小

​ 然后会在mybatis中追加limit 关键字进行查询

第一阶段–后台开发

开发模块功能

1) 检查项/组管理模块

导入数据库和表单

		数据库创建时必须指定字符集为utf8mb4  作用:使用手机端时 支持emoj 四个字符

​ 使用PMD ,对每一个表的每一个字段的含义和使用操作做出说明备注(规范)

数据库表 varchar(32) 存储 32个字母 16个字符(2字节) 8个表情(4字节)

​ 导入实体类

​ 导入公共资源

​ 1.返回前端的状态类型对象

​ 2.返回前端的结果对象

​ 3.分页对象 【总数,当前页结果】

​ 4.按条件查询对象

​ 5.基础静态资源

PowerDesigner 制表设计

查看项目第一天PDF具体使用步骤

是一款ER实体关系图设计软件 简称PDM(数据库设计图表)

​ 可以方便的对系统进行分析设计 ,从而制作数据流程图,物理数据模型(数据库表设计),概念数据模型,面向对象模型。

1.制表过程

​ 创建表格要使用Mysql 5.0 否则 sql yog创建报错

​ code – 表示表名、字段名

​ p --主键

​ identity – 主键自增

2.导出sql表

​ 设计时要指定好外键,但是在创数据库时 过滤掉

​ 1.菜单栏中 database

​ 2.create database

​ 3.option --> 取消勾选 外键

3.逆向工程

将建表文件解析为表图结构 显示到软件上

​ file —reverse --database

4.生成数据库报表文件

​ 生成一个网页版的整体表数据直观,可以在里面查看所有的表的结构或信息

report - report wizard

datagroup 新型软件 好用 需要破解

datafactory,压力测试软件。大量为数据库表生产数据

Element UI 前端设计

使用任何组件 都需要先创建对象

​ new Vue ({

​ el : “ ”

})

布局容器

布局容器总体布局规律图

在这里插入图片描述

​ 解析:

​ 在el - main中,会自动填充当行的剩余页面空间

​ 容器的属性 定义 每一个子标签都是一行

​ 如果想 aside跟main 保持在一行 需要使用container 存储在一起

​ 左右侧的 aside 以子标签的顺序作为左右的设置

    <!--导入以前的vue组件 可以生效--><link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"><script src="element-ui/vue.js"></script><!-- 引入ElementUI组件库 --><script src="element-ui/lib/index.js"></script><el-container><el-header>Header</el-header><el-container><!--在同一个容器中就可以左置--><el-aside width="200px">Aside</el-aside><el-container><el-main>Main</el-main><el-footer>Footer</el-footer></el-container><!--在同一个容器中就可以右置--><el-aside width="200px">Aside</el-aside></el-container>
</el-container>

下拉菜单

目标: 学习组件 关注 属性和类型

size

trigger

子标签中的 divided 可以在每个子选项中加分割线

<el-container><el-aside width="200px"><el-menu><el-submenu v-for="menu in menuList" :index="menu.path"><template slot="title"><i class="fa" :class="menu.icon"></i>{{menu.title}}</template><template v-for="child in menu.children"><el-menu-item :index="child.path"><a :href="child.linkUrl" target="right">{{child.title}}</a></el-menu-item></template></el-submenu></el-menu></el-aside><el-container><iframe name="right" class="el-main" src="ordersetting.html" width="100%" height="580px" frameborder="0"></iframe></el-container>
</el-container>
<script>new Vue({el: '#app',data:{menuList:[ //循环该菜单显示对应数据和跳转功能{"path": "1","title": "工作台","icon":"fa-dashboard","children": []},{"path": "2","title": "会员管理","icon":"fa-user-md","children": [{"path": "/2-1","title": "会员档案","linkUrl":"member.html","children":[]},{"path": "/2-2","title": "体检上传","children":[]},{"path": "/2-3","title": "会员统计","linkUrl":"all-item-list.html","children":[]},]},{"path": "3","title": "预约管理","icon":"fa-tty","children": [{"path": "/3-1","title": "预约列表","linkUrl":"ordersettinglist.html","children":[]},{"path": "/3-2","title": "预约设置","linkUrl":"ordersetting.html","children":[]},{"path": "/3-3","title": "套餐管理","linkUrl":"setmeal.html","children":[]},{"path": "/3-4","title": "检查组管理","linkUrl":"checkgroup.html","children":[]},{"path": "/3-5","title": "检查项管理","linkUrl":"checkitem.html","children":[]},]},{"path": "4","title": "健康评估","icon":"fa-stethoscope","children":[{"path": "/4-1","title": "中医体质辨识","linkUrl":"all-medical-list.html","children":[]},]},{"path": "5",     //菜单项所对应的路由路径"title": "统计分析",     //菜单项名称"icon":"fa-heartbeat","children":[//是否有子菜单,若没有,则为[]{"path": "/5-1","title": "工作量统计","linkUrl":"all-medical-list.html","children":[]}]}]}});$(function() {var wd = 200;$(".el-main").css('width', $('body').width() - wd + 'px');});
</script>

导航菜单

在官网中查看

message消息提示

在官网中查看更多

内置对象 this.$message 使用事件success/erorr/info/warning进行激活

此处以回调函数为例

axios.post("/跳转",this.formData).then((resp)=>{
//判断回调结果
//如果结果为true
if(resp.data.flag){
//给出提示,成功this.$message.success(resp.data.message) ;  //使用弹窗内置对象//重新刷新页面 显示检查项全部数据this.pagination.currentPage=1;this.findPage();
}else {//给出提示,错误this.$message.error(resp.data.message) ;
//重新刷新页面 显示检查项全部数据this.pagination.currentPage=1;this.findPage();
}
})

表格

Table组件功能

​ template slot-scope=“‘scope’ 作用域插槽 在子标签template中定义

//1.设置行固定 
//2.斑马纹 
//3.dataList变量进行双向绑定
<el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row> <el-table-column type="index" align="center" label="序号"></el-table-column><el-table-column prop="code" label="项目编码" align="center"></el-table-column><el-table-column prop="name" label="项目名称" align="center"></el-table-column><el-table-column label="适用性别" align="center"><template slot-scope="scope"><span>{{ scope.row.sex == '0' ? '不限' : scope.row.sex == '1' ? '男' : '女'}}</span></template></el-table-column><el-table-column prop="age" label="适用年龄" align="center"></el-table-column><el-table-column prop="remark" label="项目说明" align="center"></el-table-column><el-table-column label="操作" align="center"><template slot-scope="scope"><el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button><el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button></template></el-table-column>
</el-table>
  • 奇偶行不同颜色(斑马纹)stripe

  • 背景色的变更 :row-class-name=“tableRowClassName”

    //提供方法变更颜色
    tableRowClassName({row, rowIndex}) {if (rowIndex === 1) {return 'warning-row';} else if (rowIndex === 3) {return 'success-row';}return '';}}
    
  • 表头固定,设置表格的高度即可height=“250”

  • 列固定/冻结,在列上设置fixed,如果是右固定则是fixed=‘right’

  • 表格生成序号

    <el-table-column type="index" width="50"></el-table-column>  // type="index"
    
  • 表格列的单选 highlight-current-row

  • 表格的多选

    <el-table-column type="selection" width="55"> </el-table-column>// type="selection"
    
  • 表格按照列头排序,增加sortable即可

标签

在官网中查看

表单

表单的布局

​ 表单的校验

​ 1.实时校验

​ 2.提交校验

//在data大属性中定义校验规则
//在form表单中使规则生效<!--设置引用名,双向绑定formdata表单内容,指定规则--><el-form ref="dataEditForm" :model="formData"  label-position="right"  label-width="100px" :rules="rules">rules: {name: [{ required: true, message: '请输入活动名称', trigger: 'blur' },{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }],region: [{ required: true, message: '请选择活动区域', trigger: 'change' }]}    //进行输入校验的语法this.$refs['form'].validate(function(valid){});//清除校验this.$refs["dataAddForm"].resetFields();this.$refs["dataAddForm"].clearValidate();

​ 3.表单划分

​ 在表单中 可以分为24份 分开定义长度

<el-form ref="dataEditForm" :model="formData"  label-position="right"  label-width="100px" :rules="rules">//此行为一组,  使用列标签  span属性进行绑定  建议以24为整数进行划分<el-row><el-col :span="12">      <!--设置校验对象--><el-form-item label="编码" prop="code" ><el-input v-model="formData.code"/></el-form-item></el-col><el-col :span="12"><!--设置校验对象--><el-form-item label="名称" prop="name"><el-input v-model="formData.name"/></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="适用性别"><el-select v-model="formData.sex"><el-option label="不限" value="0"></el-option><el-option label="" value="1"></el-option><el-option label="" value="2"></el-option></el-select></el-form-item></el-col><el-col :span="12"><!--设置校验对象--><el-form-item label="助记码" prop="helpCode"><el-input v-model="formData.helpCode"/></el-form-item></el-col></el-row><el-row><el-col :span="24"><el-form-item label="说明"><el-input v-model="formData.remark" type="textarea"></el-input></el-form-item></el-col></el-row><el-row><el-col :span="24"><el-form-item label="注意事项"><el-input v-model="formData.attention" type="textarea"></el-input></el-form-item></el-col></el-row></el-form>

分页组件

  • sizes,每页多少条
  • total
  • prev
  • pager,快速点击的页码
  • next
  • jumper,跳转页
<div class="pagination-container"><el-paginationclass="pagiantion"  //内置类样式@current-change="handleCurrentChange" //点击分页时的激活方法:current-page="pagination.currentPage" //当前页:page-size="pagination.pageSize"	//每页大小layout="total, prev, pager, next, jumper"//可供点击的按钮:total="pagination.total"  				//总页数></el-pagination>
</div>//方法名字和内容自己定义
handleCurrentChange(currentPage) {this.pagination.currentPage=currentPage; //修改当前页this.pagination.queryString=null;//重置查询框内容this.findPage();//调用查询},

代码生成工具

作用:在DAO层进行代码生成,名字【mybatis-generator】(free mybatis插件已经集成有该图形化功能)

步骤:

​ 1.在build/plugins中导入依赖

​ 2.创建配置文件【在需要生成代码的项目中】

​ 3.连接到数据库

七牛云上传图片

图片服务器 有一个热点图片缓存 还可以再加一个CDN缓存 (很贵) 来形成一套图片响应体系架构

​ – 网页上传到自己服务器,服务器在转发到图片服务器,下次访问直接从图片服务器(七牛)获取

API使用:七牛云SDK帮助文档

使用详情:

1.在控制层配置文件上传对象和导入依赖

<!--文件上传组件-->
<bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="maxUploadSize" value="104857600" /><property name="maxInMemorySize" value="4096" /><property name="defaultEncoding" value="UTF-8"/>
</bean>
  <quartz.version>2.2.1</quartz.version><commons-fileupload.version>1.3.1</commons-fileupload.version>
<!-- 文件上传组件 -->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>${commons-fileupload.version}</version>
</dependency>
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>${quartz.version}</version>
</dependency>
<dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>${quartz.version}</version>
</dependency>
<dependency><groupId>com.sun.jersey</groupId><artifactId>jersey-client</artifactId><version>1.18.1</version>
</dependency>
<dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>7.2.0</version>
</dependency>

2.在页面添加两个必要方法,上传前校验,上传完成后显示的方法

 //文件上传成功后的钩子,response为服务端返回的值,file为当前上传的文件封装成的js对象handleAvatarSuccess(response, file) {   //此处的response是返回的result对象,直接可以.属性this.imageUrl=response.data;this.$message({type:response.flag?"success":"error",message:response.message,name:response.name});if(response.flag){//预览刚刚上传的文件this.imageUrl = "http://puco9aur6.bkt.clouddn.com/"+response.data; //为url赋值,绑定显示this.formData.img = response.data;//将文件名称赋值给模型数据,用于表单提交}},//上传图片之前执行beforeAvatarUpload(file) {console.log(file);   //打印file内容到控制台const isJPG = file.type === 'image/jpeg';     //图片格式为jpegconst isLt2M = file.size / 1024 / 1024 < 2;   //大小小于2Mif (!isJPG) {
this.$message.error('上传套餐图片只能是 JPG 格式!');}if (!isLt2M) {
this.$message.error('上传套餐图片大小不能超过 2MB!');}return isJPG && isLt2M;    },

3.上传组件各个变量的功能

action:每次只要有上传行为就会执行该后台操作

 <el-uploadclass="avatar-uploader"<!--通过上传前回调后,符合约束的文件上传的地址-->action="/setmeal/upload.do"<!--是否自动上传-->:auto-upload="true"<!--后端 接收此文件的参数名称 必须一致-->name="imgFile":show-file-list="false"<!--上传成功之后的回调函数-->:on-success="handleAvatarSuccess"<!--上传之前的回调-->:before-upload="beforeAvatarUpload"><!--图片上传成功之后,图片的预览效果--><img v-if="imageUrl" :src="imageUrl" class="avatar">   //如果上传图片成功,那么url有值 就会直接赋值<i v-else class="el-icon-plus avatar-uploader-icon"></i>//否则不显示,用对用设置的图片代替 此处是“+”
</el-upload>

4.后台文件上传控制层

//文件上传
@RequestMapping("/uploadFile")
public Result updoadFile(@RequestParam("imgFile") MultipartFile imgFile){String originalFilename = imgFile.getOriginalFilename();//原始文件名int index = originalFilename.lastIndexOf(".");  //获得.的索引String suffix = originalFilename.substring(index);  //按照索引截取  获得.jpgString fileName = UUID.randomUUID().toString() + suffix; //生成一个文件名拼接 .jpg//将图片保存到七牛云try{//调用工具类QiniuUtils.upload2Qiniu(imgFile.getBytes(),fileName);//文件上传成功后,需要将文件名称保存到redis中jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);return new Result(true, MessageConstant.PIC_UPLOAD_SUCCESS,fileName);}catch (Exception e){e.printStackTrace();return new Result(false,MessageConstant.PIC_UPLOAD_FAIL);}
}

5.点击确认提交表单后的业务层

成功插入数据库后,再使用流的方式提交到redis中进行缓存保存,主要是为了保存名字

        //创建结果对象Result result = new Result();//插入套餐int meal =mealDao.insertGroup(setmeal);//获得新增对象idInteger id = setmeal.getId();//判断是否插入成功//=0 表示插入失败if(meal==0){result.setFlag(false);result.setMessage(MessageConstant.EDIT_CHECKGROUP_FAIL);return  result;}//套餐插入成功则将对应的图片存入redis中,确认成功后才提交到redis中缓存保存jedisPool.getResource().sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES,setmeal.getImg());//自动注入过redispool

存储方案

方案一

	nginx  反向代理   一台简单的高性能服务器 偏向于静态资源部署 tomcat偏向于动态资源部署

​ 场景:企业网站自己需要使用的图片数据

方案二:

​ 开源分布式存储系统,如 Fastdfs (阿里开源)、HDFS

​ 场景:用户使用过程中上传的图片。头像,朋友圈图片等。

方案三:

​ 云存储。 如 七牛云,百度云 。费用高昂

​ 场景:大型项目,例京东淘宝。

鉴权

使用步骤:

1)上传

​ 1.获取本地服务器对象

​ 2.创建七牛云对象

​ 3.鉴权(仓库,仓库AKey、SKey)

​ 4.获得权限认证

​ 5.上传 (不指定key 默认以hash值作为文件名)

​ 6.解析上传结果

2)删除

​ 1.获取本地服务器对象

​ 2.创建七牛云对象

​ 3.鉴权(仓库,仓库AKey、SKey)

​ 4.指定删除文件名

​ 5.传输指令

​ 6.解析结果

定时器Quartz

期间需要由Redis提供缓存服务支持

Quartz定义: 开源的分布式定时任务调度框架

在这里插入图片描述

创建自定义job定时器类,创建需要执行的逻辑方法

配置文件

​ 1.定时器类加入spring容器

​ 2.配置指定需要使用的方法(必须public,否则可能无法调用)

​ 3.创建触发器

​ 4.创建触发器调度工厂

使用

​ 1.导包(依赖spring包)

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz</artifactId><version>2.2.1</version></dependency><dependency><groupId>org.quartz-scheduler</groupId><artifactId>quartz-jobs</artifactId><version>2.2.1</version></dependency>
</dependencies>

​ 2.编写job的实现逻辑,打为war包使用

/*** 自定义任务,定时清理垃圾图片*/
public class ClearImgJob {@Autowiredprivate JedisPool jedisPool;//清理图片public void clearImg(){System.out.println("定时清理垃圾图片");Set<String> set = jedisPool.getResource().sdiff(RedisConstant.SETMEAL_PIC_RESOURCES, RedisConstant.SETMEAL_PIC_DB_RESOURCES);if(set != null){for (String fileName : set) {System.out.println("定时清理垃圾图片: " + fileName);//根据图片名称从七牛云服务器删除文件QiniuUtils.deleteFileFromQiniu(fileName);//从redis集合中删除图片名称jedisPool.getResource().srem(RedisConstant.SETMEAL_PIC_RESOURCES,fileName);}}}
}

​ 3.配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 注册自定义Job --><bean id="jobDemo" class="com.itheima.jobs.JobDemo"></bean><!-- 注册JobDetail,作用是负责通过反射调用指定的Job --><bean id="jobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><!-- 注入目标对象 --><property name="targetObject" ref="jobDemo"/><!-- 注入目标方法 --><property name="targetMethod" value="run"/></bean><!-- 注册一个触发器,指定任务触发的时间 --><bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><!-- 注入JobDetail --><property name="jobDetail" ref="jobDetail"/><!-- 指定触发的时间,基于Cron表达式 --><property name="cronExpression"><value>0/10 * * * * ?</value></property></bean><!-- 注册一个统一的调度工厂,通过这个调度工厂调度任务 --><bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><!-- 注入多个触发器 --><property name="triggers"><list><ref bean="myTrigger"/></list></property></bean>
</beans>

Cron表达式

七个位置 最后一位可以没有 空格分割

例如: 每十秒执行一次 0/10 * * * * * ?

​ 每天凌晨2点执行一次 0 0 2 * *?

​ 每天早上3-5,每隔5分钟执行一次 0 0/5 3-5 * * ?

名字是否必须允许值特殊字符
0-59, - * /
0-59
0-23
1-31
0-11
1-7 或 SUN-SAT
空 或 1970-2099

Apache POI上传文件

​ 可以操作所有微软办公自动软件,只是更多的是用来操作excel表格

​ 作用:批量数据上传/导出

入门案例

注意:1. 读取单元格时 如果类型不一致 报错

​ 2.获取数据

​ 获取行 (获取行数/单元格数时,为去除表头所以行索引 从1开始且普通for循环遍历时<=,单元格索引从0开始)

​ 获取单元格 (注: 如果单元格赋值后删除那么也会被读取,值为“ ”)

​ 3. flush() 将内存中的缓存区数据 强制刷新到磁盘中存储

4.Excel07版之后压缩时,是以xml文件存储 用SXSSworkbook(不占内存,不支持公式)

XSSFworkbook 把excel读入内存并组织结构树(占内存,但是支持excel的公式计算)

导包(此处包仅支持excel)

<!--poi-->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId>
</dependency>

读取数据

//获得poi对象,将文件读入内存
XSSFWorkbook sheets = new XSSFWorkbook("D:\\poi.xlsx");//获取sheet页  getSheeAt / getSheetName
//获取第一张表格
XSSFSheet sheet = sheets.getSheetAt(0);//循环每一行
for (Row row : sheet) {//循环每一行的每一格for (Cell cell : row) {//转换读取的数据类型为stringcell.setCellType(Cell.CELL_TYPE_STRING);//获取该单元格信息String value = cell.getStringCellValue();//输出System.out.print(value);}
}

写出数据

//创建poi对象
XSSFWorkbook workbook = new XSSFWorkbook();//创建工作表
XSSFSheet sheet = workbook.createSheet("表");//创建第一行
XSSFRow row = sheet.createRow(0);//创建对该行单元格
XSSFCell cell = row.createCell(0);//对该行赋值
cell.setCellValue("aa11");//创建第一行
XSSFCell cell_1 = row.createCell(1);//对该行赋值
cell_1.setCellValue("bb11");//创建输出流
FileOutputStream out = new FileOutputStream("D:\\testPOI.xlsx");//将内存中的excel写出`
workbook.write(out);//刷新内存
out.flush();//关流
out.close();//关闭excel
workbook.close();

工具类

判断该单元格是什么类型的方法可用,其他慎用

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;public class POIUtils {private final static String xls = "xls";private final static String xlsx = "xlsx";private final static String DATE_FORMAT = "yyyy/MM/dd";/*** 读入excel文件,解析后返回* @param file* @throws IOException*///获取该excel文件的每一行数据public static List<String[]> readExcel(MultipartFile file) throws IOException {//检查文件checkFile(file);int a = 0;//去除重复线,忽略//获得Workbook工作薄对象Workbook workbook = getWorkBook(file);//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回List<String[]> list = new ArrayList<String[]>();//getWorkBook方法可能返回nullif(workbook != null){//遍历有几张表(表索引从0开始)for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){//依次获得每一张表Sheet sheet = workbook.getSheetAt(sheetNum);//判断该表为null直接进入下一次循环if(sheet == null){continue;}int a1= 0;//去除重复线,忽略//获得当前sheet的开始行int firstRowNum  = sheet.getFirstRowNum();//获得当前sheet的结束行int lastRowNum = sheet.getLastRowNum();//循环除了第一行的所有行(因为有表头,且行索引从1开始)for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){//获得当前行Row row = sheet.getRow(rowNum);//判断该行为null直接进入下一次循环if(row == null){continue;}//获得当前行的第一个单元格(规则按照getLastCellNum方法实现)int firstCellNum = row.getFirstCellNum();//获得当前行的列数//getLastCellNum:获得该行的最后列数(修改过,后来重置为null的单元格也算一列)//getPhysicalNumberOfCells : 获得该行的物理列数(目前有值的最后一列单元格)//short lastCellNum = row.getLastCellNum();//获取当前行实际上有多少单元格int lastCellNum = row.getPhysicalNumberOfCells();int a3 = 0;//去除重复线,忽略//将实际单元格个数存入String[] cells = new String[row.getPhysicalNumberOfCells()];//循环当前行for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){Cell cell = row.getCell(cellNum);//获得当前这个单元格的对象cells[cellNum] = getCellValue(cell);//判断该对象是那种类型的值,转换后存入数组}list.add(cells);//将数组结果加入集合}}workbook.close();}return list;}//校验文件是否合法public static void checkFile(MultipartFile file) throws IOException{//判断文件是否存在if(null == file){throw new FileNotFoundException("文件不存在!");}//获得文件名String fileName = file.getOriginalFilename();//判断文件是否是excel文件if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){throw new IOException(fileName + "不是excel文件");}}//判断是以哪一种格式结尾的,返回对应的数据类型对象public static Workbook getWorkBook(MultipartFile file) {//获得文件名String fileName = file.getOriginalFilename();//创建Workbook工作薄对象,表示整个excelWorkbook workbook = null;try {//获取excel文件的io流InputStream is = file.getInputStream();//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象if(fileName.endsWith(xls)){//2003workbook = new HSSFWorkbook(is);}else if(fileName.endsWith(xlsx)){//2007workbook = new XSSFWorkbook(is);}} catch (IOException e) {e.printStackTrace();}return workbook;}//判断该单元格是什么类型 可用,其他慎用public static String getCellValue(Cell cell){//判断是都为空String cellValue = "";if(cell == null){return cellValue;}//如果当前单元格内容为日期类型,需要特殊处理CellStyle cellStyle = cell.getCellStyle();String dataFormatString = cell.getCellStyle().getDataFormatString();if(dataFormatString.equals("m/d/yy")){//月日年-->年月日cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue());return cellValue;}//把数字当成String来读,避免出现1读成1.0的情况if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){cell.setCellType(Cell.CELL_TYPE_STRING);}//判断数据的类型switch (cell.getCellType()){case Cell.CELL_TYPE_NUMERIC: //数字cellValue = String.valueOf(cell.getNumericCellValue());break;case Cell.CELL_TYPE_STRING: //字符串cellValue = String.valueOf(cell.getStringCellValue());break;case Cell.CELL_TYPE_BOOLEAN: //BooleancellValue = String.valueOf(cell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA: //公式cellValue = String.valueOf(cell.getCellFormula());break;case Cell.CELL_TYPE_BLANK: //空值cellValue = "";break;case Cell.CELL_TYPE_ERROR: //故障cellValue = "非法字符";break;default:cellValue = "未知类型";break;}return cellValue;}
}

文件上传vue

<!--文件上传到后端,直接进行逻辑判断保存操作-->
<!--上传前会执行beforeUpload方法,为true才会访问该后端-->
<el-upload action="/ordersetting/uploadFile"  //调用后端control的方法name="imgFile"					  //前端后端名字必须一致且用@RequestParam("imgFile")注解接收:show-file-list="false"			  :on-success="handleSuccess"		  //action后端方法执行成功后的回调函数:before-upload="beforeUpload"	  //上传前的回调函数(用户选择图片后的逻辑校验回调函数)><el-button type="primary">上传文件</el-button>
</el-upload>

业务层插入操作

@Override
//添加上传文件,批量操作
public Result add(List<OrderSetting> list) {//先删除,后插入,如有异常直接返回批量失败try {orderSettingDao.deleteOrderSetting(list);  //删除,如果遇到该list是没有的 不会出错,影响行数0orderSettingDao.insertOrderSetting(list);   //插入return new Result(true,MessageConstant.IMPORT_ORDERSETTING_SUCCESS);} catch (Exception e) {e.printStackTrace();return new Result(true,MessageConstant.IMPORT_ORDERSETTING_FAIL);}
}

日历

前端解析代码和数据库中的字段不一致的时候 可以用map进行封装返回 因为没有直接可用的pojo,偷懒。

批量添加数据

预约设置

//内置方法,转换日期格式
this.formatDate(day.getFullYear(),day.getMonth()+1,day.getDate())

第二阶段–移动端开发

套餐级联查询

ResultMap多级联查询

当封装的POJO中,有自定义POJO类型级联查询字段与pojp不一致,需要使用resultMap进行映射封装

mybatis官网查询帮助文档:https://mybatis.org/mybatis-3/zh/index.html

​ 两种方式

​ 1.纯代码解析查询sql resultType 循环查询多次 影响性能?

​ 解析:每一次循环都要进行查询,此查询是简单sql连接语句

//根据套餐ID查询套餐详情(套餐基本信息、套餐对应的检查组信息、检查组对应的检查项信息)public Setmeal findById2(int id) {Setmeal setmeal = setmealDao.findById(id);if(setmeal!=null) {// select b.* from t_setmeal_checkgroup a LEFT JOIN t_checkgroup b on a.checkgroup_id=b.id where a.setmeal_id=#{id}List<CheckGroup> checkGroups = checkGroupDao.findBySetmealId(id);for(CheckGroup group : checkGroups){// select b.* from t_checkgroup_checkitem a LEFT JOIN t_checkitem b on a.checkitem_id=b.id where a.checkgroup_id=#{id}List<CheckItem> checkItems = checkItemDao.finByGroupId(group.getId());group.setCheckItems(checkItems);}setmeal.setCheckGroups(checkGroups);}}

​ 2.级联关联 resultMap

​ resultMap特性:

​ 1) 对pojo进行一一映射 javatype和jdbctype的使用场景?

​ 2)继承特性

注意:

​ 1)在做前端页面的时候,不能使用table标签,因为页面刷新,会等到所有table数据读取完成才会统一显示,所以用div、li、等标签来替换。避免网络卡顿,数据过大时,打开网页时白一片

1.页面刷新开始异步调用访问数据

window.location.toString() 重点语句,获取当前网址的字符串信息

 mounted(){//获取到网址的字符串信息// http://localhost:81/pages/setmeal_detail.html?id=5&name=wzvar page = window.location.toString();//按照?进行切分var target = page.split("?");//切分之后的[1]就是?之后的信息// id=5&name=wz//获得[1],按照&进行切分,获得一个数组var arr = target[1].split("&");//遍历数组id=5 、name=wzfor(let i = 0 ;i < arr.length;i++){//每一个值都要按照=进行切分 获得数组 [0]id  [1]5let num = arr[i].split("=");//判断[0]是否是id  如果是那么返回[1]的结果if(num[0]=id){//只要进入页面就发送异步请求查询该套餐的所有信息显示到页面axios.post("/setmeal/getAllInfoById?id=" + num[1]).then((response) => {if(response.data.flag){this.setmeal = response.data.data[0];this.imgUrl = 'http://qekirsm87.bkt.clouddn.com/' + this.setmeal.img;}});}}

2.业务层的开始调用dao,返回一个套餐对象

//前端页面-查询所有检查组和检查项
@Override
public Result getCheckGroupsAndCheckItems(String id) {//调用dao级联查询Setmeal setmeal = mealDao.getCheckGroupsAndCheckItemsInMeal(id);if(setmeals!=null){return new Result(true,MessageConstant.GET_SETMEAL_LIST_SUCCESS,setmeals);}//返回结果return new Result(false,MessageConstant.GET_SETMEAL_LIST_FAIL);
}

3.套餐的dao

​ 解析:1.由getCheckGroupsAndCheckItemsInMeal方法进入,开始查询该套餐信息。查询结果封装进getMeal的resultMap

​ 2.由于继承关系,所以可以完整的把所有字段封装进Setmeal对象

​ 3.执行级联查询字段checkGroups

<mapper namespace="com.wz.dao.MealDao"><!--套餐查询的结果集,检查组由继承完成--><resultMap id="baseMealResultMap" type="Setmeal"><id column="id" property="id"/><result column="name" property="name"/><result column="code" property="code"/><result column="helpCode" property="helpCode"/><result column="sex" property="sex"/><result column="age" property="age"/><result column="price" property="price"/><result column="remark" property="remark"/><result column="attention" property="attention"/><result column="img" property="img"/></resultMap><!--该套餐查询结果的检查组级联查询--><resultMap id="getMeal" type="SetMeal" extends="baseMealResultMap"><!--由于是集合类型,使用collection--><collectionproperty="checkGroups"ofType="CheckGroup"column="id"select="com.wz.dao.CheckGroupDao.findCheckGroupAndItemByGroupId"/></resultMap><!--前端页面,查询该套餐的所有检查项和组--><select id="getCheckGroupsAndCheckItemsInMeal" resultMap="getMeal">select * from t_setmeal where id=#{id}</select>
</mapper>

4.检查组的dao

​ 解析:1.由上层调用,在findCheckGroupAndItemByGroupId方法进入,开始查询该检查组信息。

​ 查询结果封装进getGroup的resultMap。

​ 2.由于继承关系,所以可以完整的把所有字段封装进CheckGroup对象

​ 3.执行级联查询字段checkItems,此处是一个list集合,但是底层会将每一个元素单独进行调用下一层sql语句

<mapper namespace="com.wz.dao.CheckGroupDao"><!--检查组的映射配置--><resultMap id="baseGroupResultMap" type="CheckGroup"><id column="id" property="id"/><result column="name" property="name"/><result column="code" property="code"/><result column="helpCode" property="helpCode"/><result column="sex" property="sex"/><result column="remark" property="remark"/><result column="attention" property="attention"/></resultMap><!--该检查组级联查询检查项的设置,此处是存放的是一个集合id,会依次向下调用--><!--所以会id=5封装一个CheckItem,id=6封装一个CheckItem--><resultMap id="getGroup" type="CheckGroup" extends="baseGroupResultMap"><collectionproperty="checkItems"ofType="CheckItem"column="id"select="com.wz.dao.CheckItemDao.findItemByGroupId"/></resultMap><!--前端,级联查询检查组--><select id="findCheckGroupAndItemByGroupId" resultMap="getGroup">SELECT * FROM t_checkgroup WHERE id IN (SELECT checkgroup_id FROM t_setmeal_checkgroup WHERE setmeal_id =#{id})</select></mapper>

5.检查项的dao

​ 解析:1.由上层调用,在findItemByGroupId方法进入,开始查询每一个检查项信息。

​ 查询结果封装进自己的resultType的CheckItem。由于上层是list集合所以会变成一个个元素存取

​ 2.至此查询完毕,实现页面模型的多json嵌套结构

	setmeal:{img:"",name:"",checkGroups:[{name:"",code:"",checkItems:[{name:"",code:""}]}]}
<!--前端,级联查询检查项-->
<select id="findItemByGroupId" resultType="CheckItem">SELECT * FROM t_checkitem WHERE id IN (SELECT checkitem_id FROM t_checkgroup_checkitem WHERE checkgroup_id=#{id})
</select>

短信发送

	阿里云短信服务==观看代码实现==

FreeMarker静态页面

官网:http://freemarker.foofun.cn/ 查询帮助文档

​ 作用:使网页可以更快响应,在进行增删改操作后,生成一个静态页面以后续直接调用

​ 定义:java语言开发的模板引擎

​ 场景 : 页面静态化生成(将一个动态数据加载的页面生成为html的过程,称为静态化)

​ 如:合同模板、邮件模板

​ 组成: template 基本模板

​ model 模板需要使用的数据

入门案例

1.导包

<!--FreeMarker-->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.30</version>
</dependencml

​ 2.准备模板(该模板文件要以.ftl结尾)

<html>
<head><title>Welcome!</title>
</head>
<body><h1>Welcome ${user}!</h1><p>Our latest product:<#-- 我是一个注解 --><h1>GOAWAY ${user}!</h1><a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>

3.代码

此处放置在d盘,正常下是放在web的ftl文件下

//      Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);Configuration cfg = new Configuration(Configuration.getVersion()); //创建freemarker对象cfg.setDirectoryForTemplateLoading(new File("D:\\te"));//指定模板位置cfg.setDefaultEncoding("UTF-8"); //指定生成模板的编码Template temp = cfg.getTemplate("ts.ftl"); //指定模板文件名//模板只能以json格式接收//创建map1Map root = new HashMap();root.put("user", "Blank");//由于模板中存在对象数据,存入对象//方式一:Map latest = new HashMap();root.put("latestProduct", latest);latest.put("url", "https://www.baidu.com");latest.put("name", "百度一下啊");//方式二:root.put("latestProduct",new User("https://www.baidu.com","百度一下啊"));// 通过一个文件输出流,就可以写到相应的文件中,此处用的是绝对路径FileWriter out = new FileWriter("D:\\te\\test.html");temp.process(root, out); //生成test.html文件out.close();  //关流,不然会引起内存泄漏

FreeMarker指令

所有指令都是以#开始

  • assign

    • 在模板页面中定义一个变量
    • 使用:在调试模板时使用,可以定义对象或者字符串,优先级高于后端传入的变量数据
<html>
<head><title>Welcome!</title>
</head>
<body><h1>Welcome ${user}!</h1><!-- 使用指令定义变量 --><#assign shit="大牛"><h1>GOAWAY ${shit}!</h1><#assign info={"mobile":"13812345678",'address':'北京市昌平区'} >电话:${info.mobile} 地址:${info.address}<p>Our latest prodct:<#-- 我是一个注解 --><a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
  • include

    • 包含其他的模板文件进入主模板文件
    • 使用:在java中的设置模板所在路径开始找其他路径的模板文件,包含进主模板中
<html>
<head><title>Welcome!</title>
</head>
<body><h1>Welcome ${user}!</h1><#assign shit="大牛"><h1>GOAWAY ${shit}!</h1><!-- 在java代码中指定文件存放的是位置找到该文件。并载入其内容 --><#include "he.ftl">  
</body>
</html>
  • if

    • 判断条件,可以在Java中定义变量,也可以使用assign定义。

    • 使用: 可以使用if else elseif /if 传入的判断值在java中的map的key来定义

      <html>
      <head><title>Welcome!</title>
      </head>
      <body>	<!-- 此success在Map中定义,如果没有定义则报错 --><!-- 同时存在,以assign为准 --><#if success=1>条件1成立..<#elseif success=2>条件2成立..<#else>条件不成立..</#if>
      </body>
      </html>
      
  • list

    • 遍历集合,java需要使用list集合来存储map
    • list else 如果list为空执行 else
    • list … as …
   HashMap<Object, Object> map = new HashMap<>();//模板只能以json格式接收ArrayList<Map> goods = new ArrayList<>();Map root1 = new HashMap();root1.put("name","sa");root1.put("price","23");Map root2 = new HashMap();root2.put("name","sa");root2.put("price","23");Map root3 = new HashMap();root3.put("name","sa");root3.put("price","23");//存入goods.add(root1);goods.add(root2);goods.add(root3);map.put("goods",goods);// 通过一个文件输出流,就可以写到相应的文件中,此处用的是绝对路径FileWriter out = new FileWriter("D:\\te\\test.html");temp.process(map, out);

ftl文件list输出格式 以as作为遍历每一个

<#list goods as good>
商品名称: ${good.name} 价格:${good.price}<br>
</#list>
  • 内置函数

    • 此处只对日期做出示例 官方文档中查询
    • 使用时 要在变量后使用 ?函数名
<html>
<head><title>Welcome!</title>
</head>
<body> 
date:仅日期部分,没有一天当中的时间部分。
time:仅一天当中的时间部分,没有日期部分。
datetime:日期和时间都在${openingTime?time}<br>
${openingTime?date}<br>
${openingTime?datetime}<br>//结果
22:17:37   
2020-8-10
2020-8-10 22:17:37</body>
</html>

生成静态页面

时机: 在任何本体或者子项发生改变的时候生成一次静态页面,静态页面是是使用代码后台直接生成的,不需要使用异步调用!

注意事项:

​ 1.指定输出的模板存储位置

​ 2.代码中自动注入对象为FreeMarkerConfigurer

@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;//注入freemarker映射工厂

​ 3.模板中的访问地址要与代码中地址保持一致。且是指定磁盘绝对路径

​ 4.生成的主页面信息文件都是在后端代码生成的,前端做逻辑处理。比如跳转页面等

​ 5.模板要以.ftl结尾

​ 6.各个参数的定义

    //spring中定义,代码中注入FreeMarkerConfigurerConfiguration configuration = freeMarkerConfigurer.getConfiguration();cfg.setDirectoryForTemplateLoading(new File("D:\\te"));//指定模板位置cfg.setDefaultEncoding("UTF-8"); //spring中定义,转换的页面编码格式Template temp = cfg.getTemplate("ts.ftl"); //java中定义指定模板位置中的哪个ftl模板文件//java中定义,配合外部配置文件字符串拼接FileWriter out = new FileWriter("输出路径+文件名字+.html");temp.process(map数据, out); //java中定义,传入数据生成到指定位置

步骤:

1.导包(此处最新版)

<!--FreeMarker-->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.30</version>
</dependencml

2.生成套餐模板

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="../img/asset-favico.ico"><title>预约</title><link rel="stylesheet" href="../css/page-health-order.css" />
</head>
<body data-spy="scroll" data-target="#myNavbar" data-offset="150">
<div class="app" id="app"><!-- 页面头部 --><div class="top-header"><span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span><span class="center">传智健康</span><span class="f-right"><i class="icon-more"></i></span></div><!-- 页面内容 --><div class="contentBox"><div class="list-column1"><ul class="list"><li class="list-item"><#--循环集合--><#list setmealList as setmeal><#--点击链接跳转到检查组详情页面--><a class="link-page" href="/yemian/setmeal_detail_${setmeal.id}.html?id=${setmeal.id}"><#--<a class="link-page" href="/yemian/setmeal_detail_${setmeal.id}.html">--><img class="img-object f-left" src="http://qekirsm87.bkt.clouddn.com/${setmeal.img}" alt=""><div class="item-body"><h4 class="ellipsis item-title">${setmeal.name}</h4><p class="ellipsis-more item-desc">${setmeal.remark}</p><p class="item-keywords"><span><#if setmeal.sex == '0'>性别不限<#else><#if setmeal.sex == '1'>男<#else></#if></#if></span><span>${setmeal.age}</span></p></div></a></#list></li></ul></div></div>
</div>
<script>var vue = new Vue({el:'#app',data:{setmealList:[]}});
</body>

3.生成检查组模板

1.json格式回传(推荐)

​ 此处使用的fastjson依赖包。不推荐使用

​ 修改为freemarker语法,vue自动双向绑定到页面中且内存占用小!!

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="../img/asset-favico.ico"><title>预约详情</title><link rel="stylesheet" href="../css/page-health-orderDetail.css" /><script src="../plugins/vue/vue.js"></script><script src="../plugins/vue/axios-0.18.0.js"></script><script src="../plugins/healthmobile.js"></script><script>var id = getUrlParam("id");</script></head>
<body data-spy="scroll" data-target="#myNavbar" data-offset="150">
<div id="app" class="app"><!-- 页面头部 --><div class="top-header"><span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span><span class="center">传智健康</span><span class="f-right"><i class="icon-more"></i></span></div><!-- 页面内容 --><div class="contentBox"><div class="card"><div class="project-img"><img :src="imgUrl" width="100%" height="100%" /></div><div class="project-text"><h4 class="tit">{{setmeal.name}}</h4><p class="subtit">{{setmeal.remark}}</p><p class="keywords"><span>{{setmeal.sex == '0' ? '性别不限' : setmeal.sex == '1' ? '男':'女'}}</span><span>{{setmeal.age}}</span></p></div><!--<div class="project-know"><a href="orderNotice.html" class="link-page"><i class="icon-ask-circle"><span class="path1"></span><span class="path2"></span></i><span class="word">预约须知</span><span class="arrow"><i class="icon-rit-arrow"></i></span></a></div>--></div><div class="table-listbox"><div class="box-title"><i class="icon-zhen"><span class="path1"></span><span class="path2"></span></i><span>套餐详情</span></div><div class="box-table"><div class="table-title"><div class="tit-item flex2">项目名称</div><div class="tit-item  flex3">项目内容</div><div class="tit-item  flex3">项目解读</div></div><div class="table-content"><ul class="table-list"><li class="table-item" v-for="checkgroup in setmeal.checkGroups"><div class="item flex2">{{checkgroup.name}}</div><div class="item flex3"><label v-for="checkitem in checkgroup.checkItems">{{checkitem.name}}</label></div><div class="item flex3">{{checkgroup.remark}}</div></li></ul></div><div class="box-button"><a @click="toOrderInfo()" class="order-btn">立即预约</a></div></div></div></div>
</div>
<script>var vue = new Vue({el:'#app',data:{imgUrl:null,//套餐对应的图片链接//使用json格式回传的时候,只需要在此处修改为freemarker语法,vue自动双向绑定到页面中且内存占用小!!setmeal:${key}   	},methods:{toOrderInfo(){window.location.href = "/pages/orderInfo.html?id=" + id;}},});
</script>
</body>
2.常规回传

(占位符都使用freemarker语法)

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no,minimal-ui"><meta name="description" content=""><meta name="author" content=""><link rel="icon" href="../img/asset-favico.ico"><title>预约详情</title><link rel="stylesheet" href="../css/page-health-orderDetail.css" /><script src="../plugins/vue/vue.js"></script><script src="../plugins/vue/axios-0.18.0.js"></script><script src="../plugins/healthmobile.js"></script><script>var id = getUrlParam("id");</script>
</head>
<body data-spy="scroll" data-target="#myNavbar" data-offset="150">
<div id="app" class="app"><!-- 页面头部 --><div class="top-header"><span class="f-left"><i class="icon-back" onclick="history.go(-1)"></i></span><span class="center">传智健康</span><span class="f-right"><i class="icon-more"></i></span></div><!-- 页面内容 --><div class="contentBox"><div class="card"><div class="project-img"><img :src="imgUrl" width="100%" height="100%" /></div><div class="project-text"><h4 class="tit">${setmeal.name}</h4><p class="subtit">${setmeal.remark}</p><p class="keywords"><span><#if setmeal.sex == '0'>性别不限<#else><#if setmeal.sex == '1'>男<#else></#if></#if></span><span>${setmeal.age}</span></p></div></div><div class="table-listbox"><div class="box-title"><i class="icon-zhen"><span class="path1"></span><span class="path2"></span></i><span>套餐详情</span></div><div class="box-table"><div class="table-title"><div class="tit-item flex2">项目名称</div><div class="tit-item  flex3">项目内容</div><div class="tit-item  flex3">项目解读</div></div><div class="table-content"><ul class="table-list"><#list setmeal.checkGroups as checkgroup><li class="table-item"><div class="item flex2">${checkgroup.name}</div><div class="item flex3"><#list checkgroup.checkItems as checkitem><label>${checkitem.name}</label></#list></div><div class="item flex3">${checkgroup.remark}</div></li></#list></ul></div><div class="box-button"><a @click="toOrderInfo()" class="order-btn">立即预约</a></div></div></div></div>
</div>
<script>var vue = new Vue({el:'#app',data:{imgUrl:null,//套餐对应的图片链接setmeal:{}},methods:{toOrderInfo(){window.location.href = "/pages/orderInfo.html?id=" + id;}}});
</script>
</body>

4.工具类

作用:在增删改操作完成之后直接执行方法,方法内部进行查询生成模板。前端自动访问模板。

 //生成模板方法public void makeTemplate(String templateFileName, String pageName, Map data) throws Exception {//通过工厂获得对象Configuration configuration = freeMarkerConfigurer.getConfiguration();//指定模板Template template = configuration.getTemplate(templateFileName);//创建输出流FileWriter fileWriter = new FileWriter(new File(outputpath+"/"+pageName));//输出模板template.process(data,fileWriter);//关流fileWriter.close();}-----------------------------详细页面---------------------------------------------------------------------
-----------------------------详细页面---------------------------------------------------------------------
-----------------------------详细页面---------------------------------------------------------------------//生成详细页面方法public void makeStaticDetailPage(List<Setmeal> list) throws Exception {//定义模板名字
//      String templateName = "setmeal_detail.ftl";String templateName = "setmeal_detailForSmall.ftl"; //使用map回传的模板//循环集合for(Setmeal setmeal : list){//定义生成的文件名,文件末尾按照该套餐id结尾。方便前端使用循环时好查找String detailPageName = "setmeal_detail_"+String.valueOf(setmeal.getId()+".html");//级联查询所有子集合,获得结果List<Setmeal> s = mealDao.getCheckGroupsAndCheckItemsInMeal(String.valueOf(setmeal.getId()));//获取查询出来的套餐对象Setmeal smeal = s.get(0);//创建mapHashMap<String, String> map = new HashMap<>();String s1 = JSON.toJSONString(smeal);//存入集合
//          map.put("setmeal",smeal);map.put("key",s1); //使用map的模板时。回传json格式//调用基本模板方法生成静态页面makeTemplate(templateName,detailPageName,map);}-----------------------------套餐页面---------------------------------------------------------------------
-----------------------------套餐页面---------------------------------------------------------------------
-----------------------------套餐页面---------------------------------------------------------------------//生成套餐页面方法//生成套餐页面,异常上抛,谁调用谁处理public void makeStaticPage(List<Setmeal> list) throws Exception {//定义数据HashMap<String, List<Setmeal>> map = new HashMap<>();//存入mapmap.put("setmealList",list);//定义模板名字String templateName = "m.ftl";//定义生成的文件名String mealPageName = "mealPage.html";//调用基本模板方法,生成一个网页输出到指定位置makeTemplate(templateName,mealPageName,map);}

5.配置文件

​ 1.在业务层中spring容器中配置freemarkerConfig

<!--配置freemarker模板对象-->
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><!--指定模板文件所在目录,外部不可访问--><property name="templateLoaderPath" value="/WEB-INF/ftl/" /><!--指定字符集--><property name="defaultEncoding" value="UTF-8" />
</bean>

​ 2.创建地址的外部文件

outputPath=F:/ideaProject/project/projectHEALTH/mobile/src/main/webapp/yemian //项目中webapp在磁盘中的绝对路径

6.修改初始访问接口

在index中修改跳转首个跳转位为模板网页

确认预约

datepicker 日期控件 安卓

身份证验证 后端是连接的公安局的服务器获取的身份证? 身份证是有一套验证规则的

此处的提交前校验为什么不能交给vue的校验 后端访问人数少

前端页面怎么在失去焦点的基础上再验证正则? async-validator

提供一个通用的查询条件,返回list集合,模板

<!--动态条件查询-->
<select id="findByCondition" parameterType="com.itheima.pojo.Order" resultMap="baseResultMap">select * from t_order<where><if test="id != null">and id = #{id}</if><if test="memberId != null">and member_id = #{memberId}</if><if test="orderDate != null">and orderDate = #{orderDate}</if><if test="orderType != null">and orderType = #{orderType}</if><if test="orderStatus != null">and orderStatus = #{orderStatus}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if></where>
</select>

权限控制(RBAC)

cookie为什么要设置路径为/ 这样不是所有路径都会携带该cookie? 常规操作 所有的页面都需要验证

拦截规则/**拦截所有请求,以前使用的/ * 安全框架独有

使用注解,认证之后这个就可以访问其他方法,是使用value字符串内存中定义的吗

配置form和loginout标签,如果还有其他的自定义的页面也是要放行的,怎么弄?

<security:http security="none" pattern="/pages/a.html"></security:http>

如何从spring中跳转到service页面

<security:authentication-provider  user-service-ref="logical">

spring security 框架支持功能:

登录:自动生成登录网址,供输入密码账户。

认证:框架底层通过暗号网址自动与指定方式的结果进行对接。

鉴权:按照给定的方式进行判断权限

退出:框架底层通过暗号网址自动注销所有权限功能

site: spring.io 关键字 按照网站的关键字查询

注意事项

​ 1.access和exception要一致

​ 2.配置用户时,password 的{noop}表示是否配置明暗文

​ 3.使用form标签,表单提交必须为post,否则404

​ 4.如果遇到ifram嵌套网页 视为不安全 需要在http标签中配置security:header标签

工程定义:war包,非继承父工程

web 中

/ 不拦截 jsp

/ 均不拦截*

*.do 只拦截.do结尾的请求

步骤

pom.xml

1.导入依赖包

一般情况下都需要依赖spring,此处未给出

<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId>
</dependency>
<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-taglibs</artifactId>
</dependency>

web.xml

2.配置delegatingFilterproxy委派过滤器

delegatingFilterproxy 类 作用:整合三方框架 含shrio

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><filter><!--DelegatingFilterProxy用于整合第三方框架整合Spring Security时过滤器的名称必须为springSecurityFilterChain,否则会抛出NoSuchBeanDefinitionException异常--><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/*</url-pattern></servlet-mapping>
</web-app>

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xmlns:context="http://www.springframework.org/schema/context"xmlns:security="http://www.springframework.org/schema/security"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security.xsd"><!--扫包--><context:component-scan base-package="com.wz"/><!--放行静态页面--><mvc:default-servlet-handler/><!--扫描spring框架的注解--><mvc:annotation-driven/><!-- 配置第二层拦截器 --><!--1.配置可以直接访问的地址--><!--<security:http security="none" pattern="/pages/a.html"></security:http>--><!--2.配置需要拦截的地址--><!--由于有权限验证,所以如果没有就自动跳转到框架登录页面--><security:http auto-config="true" use-expressions="true"><!-- 访问下列网页时需要带有该角色 --><security:intercept-url pattern="/user/**" access="hasRole('ROLE_ADMIN')" /><security:intercept-url pattern="/TT/**" access="hasRole('ROLE_GOOD')" /><security:intercept-url pattern="/pages/**" access="isAuthenticated()" /><!--匿名访问--><!--<security:intercept-url pattern="/pages/**" access="isAnonymous()" />--><!--自定义登录页面--><!--因为设置了自定义页面,所以要使用拦截调用器来授权--><security:form-loginlogin-page="/login.html"username-parameter="account"password-parameter="password"login-processing-url="/hhhh"default-target-url="/index.html"authentication-failure-url="/login.html"></security:form-login><!--关闭自定义表单的过滤器,不关闭所有请求被拦截--><security:csrf disabled="true"></security:csrf><!--退出登录,注销所有权限信息--><security:logout logout-url="/logout"logout-success-url="/login.html"invalidate-session="true"/></security:http><!--配置第三层拦截器,主要用于权限的逻辑控制和分配--><security:authentication-manager><!-- 定义拦截调用器 --><!--<security:authentication-provider  user-service-ref="logical">--><security:authentication-provider ><!-- 配置一个具体的用户数据写死,只要满足name,pwd就给指定权限 --><security:user-service><!--{noop}表示使用明文--><security:user name="admin1" password="{noop}123" authorities="ROLE_ADMIN"/></security:user-service><!--指定密码进行加密的对象,底层自行加密--><!--在暗号地址中进行密码验证处理。密码正确则赋予权限--><!--<security:password-encoder ref="passwordEncoder"></security:password-encoder>--></security:authentication-provider></security:authentication-manager><!--开启注解方式权限控制--><security:global-method-security pre-post-annotations="enabled" /><!-- 定义bean,用于逻辑分配 --><bean id="logical" class="com.wz.LogicalService"></bean><!--配置密码加密对象--><bean id="passwordEncoder"class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/><!--<dubbo:application name="dubbo_controller" />--><!--&lt;!&ndash;指定服务注册中心地址&ndash;&gt;--><!--<dubbo:registry address="zookeeper://localhost:2181"/>--><!--&lt;!&ndash;批量扫描&ndash;&gt;--><!--<dubbo:annotation package="com.wz" />-->
</beans>

项目权限整改

此处的注解只能使用一种权限,如果想要多种如何写? json不可以 使用 and 连接多个权限

1.联合查询所有权限来降低数据库的性能消耗,否则如果权限和角色越多,访问数据库的查询次数越多。如果联合查询则仅一次就可以查询所有

优化方案:

​ 1.mian页面优化显示用户的名字

​ 2.显示对应的权限操作按钮,有删除就显示删除

​ 3.如果删除失败就给出提示,权限不足(2/3 选其一)

文件导出

升级自学POI : easypoi工具包、 easy excel阿里对poi性能优化项目

每次使用 创建一个对象?

方式一:

直接导出一个模板

window.location.href = '/report/BusinessReport.xlsx';  //导出在服务器中某区域存储的模板文件

方式二:

此处统一都不使用ajax,因为使用的话需要将流封装为 sjon回传

访问后台,生成数据,再通过流的方式导出

package com.wz.analysis;import com.alibaba.dubbo.config.annotation.Reference;
import com.interfaces.Analysis;import com.wz.result.MessageConstant;
import com.wz.result.Result;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/report")
public class MemberAnalysis {@Referenceprivate Analysis analysis;//调用方法获取过去一年每月新增人数@RequestMapping("/showMemberReport")public Map showMemberReport(){Map map = analysis.checkMemberCountByMonths();return map;}//调用方法获取过去一年每月新增人数@RequestMapping("/showMealReport")public Map showMealReport(){//调用方法获取每个套餐的预约数量Map map = analysis.checkMealReservation();return map;}//调用方法获取报表数据@RequestMapping("/showReport")public Result showReport(){try{Map<String,Object> data = analysis.checkReportInfo();return new Result(true,MessageConstant.GET_BUSINESS_REPORT_SUCCESS,data);}catch (Exception e){return new Result(false,MessageConstant.GET_BUSINESS_REPORT_FAIL);}}//导出报表@RequestMapping("/exportBusinessReport")public Result exportBusinessReport(HttpServletRequest request, HttpServletResponse response) throws Exception {try {//读入模板文件String filePath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx";//获取文件工作簿对象XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream(new File(filePath)));////获取数据Map<String, Object> result = analysis.checkReportInfo();//取出返回结果数据,准备将报表数据写入到Excel文件中String reportDate = (String) result.get("reportDate");Integer todayNewMember = (Integer) result.get("todayNewMember");Integer totalMember = (Integer) result.get("totalMember");Integer thisWeekNewMember = (Integer) result.get("thisWeekNewMember");Integer thisMonthNewMember = (Integer) result.get("thisMonthNewMember");Integer todayOrderNumber = (Integer) result.get("todayOrderNumber");Integer thisWeekOrderNumber = (Integer) result.get("thisWeekOrderNumber");Integer thisMonthOrderNumber = (Integer) result.get("thisMonthOrderNumber");Integer todayVisitsNumber = (Integer) result.get("todayVisitsNumber");Integer thisWeekVisitsNumber = (Integer) result.get("thisWeekVisitsNumber");Integer thisMonthVisitsNumber = (Integer) result.get("thisMonthVisitsNumber");List<Map> hotSetmeal = (List<Map>) result.get("hotSetmeal");//XSSFSheet sheet = excel.getSheetAt(0);// 获取公有都是行和多少列int rowNum = sheet.getLastRowNum();  //获取所有行for (int i = 0; i <=rowNum ; i++) {XSSFRow row = sheet.getRow(i);  //获取单行对象if(row!=null){int colNum = row.getLastCellNum();  //获取该行的最后一个单元格。含被使用过的单元格for (int j = 0; j < colNum; j++) {XSSFCell cell = row.getCell(j);   //获取每一个单元格对象if(cell!=null){XSSFCellStyle cellStyle = cell.getCellStyle();  //获得样式对象// 红底是FFFF0000// 绿底是FF00B050if(cellStyle.getFillForegroundColorColor()!=null) {  //判断是否有颜色String color = cellStyle.getFillForegroundColorColor().getARGBHex(); //获取颜色号数System.out.println(cell.getStringCellValue()+"\t:"+color+"\t"+result.get(cell.getStringCellValue()));if("FFFF0000".equals(color)||"FFFFFF00".equals(color)){  //判断是否为指定颜色,此处颜色为大红色,绿色String [] name = cell.getStringCellValue().split(":");   //分割单元格,以此判断是否已经到达热门板块cellStyle.setFillForegroundColor(new XSSFColor(Color.YELLOW)); //填充新样式if(name.length==2) {//判断分割后的结果是否真的到达热门板块Map map = (Map) result.get(name[0]); //key,此处的key为hotSetmealcell.setCellValue("" + map.get(name[1])); //value}else{//模板中每个需要填写的单元格的值都是result查询结果的keycell.setCellValue("" + result.get(cell.getStringCellValue()));}}}}}}}//使用输出流进行表格下载,基于浏览器作为客户端下载OutputStream out = response.getOutputStream();response.setContentType("application/vnd.ms-excel");//代表的是Excel文件类型response.setHeader("content-Disposition", "attachment;filename=report.xlsx");//指定以附件形式进行下载excel.write(out);out.flush();out.close();
//            excel.close();return null;}catch (Exception e){e.printStackTrace();return new Result(false,MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);}}
}

JasperReport模拟设计器

​ 注意:1.使用表单的时候 由于指定过数据源,所以可以显示数据

​ 但是如果在程序中执行,那么是没有办法关闭的。会有问题,所以不用

​ 2.在生成边框时,为了没有间隙。要对每个区域进行缩小至上一个区域的下标线

​ 3.中文不能正常显示,要使用华文宋体且加入布丁文件与jrxml模板同级

以后都尽量不使用feilds功能制作报表?

输出流 ateBytes 。tostring

XX.class. -->

getResource(“ ”) 拿同包下文件

getResource(“/ ”)拿class文件下的文件

getClassLoader.getResource(“ ”)

getClassLoader.getResource(“ /”)

入门案例

    @Testpublic void show() throws Exception {//定义模板位置String jrxmlPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jrxml";//定义虚拟输出位置和名字String jasperPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jasper";JasperCompileManager.compileReportToFile(jrxmlPath,jasperPath);  //编译模板//定义头数据Map paramters = new HashMap();paramters.put("reportDate","2019-10-10");paramters.put("company","itcast");//定义模板主数据List<Map> list = new ArrayList();HashMap<Object, Object> map1 = new HashMap<>();map1.put("name","xiaoming");map1.put("address","beijing");map1.put("email","xiaoming@itcast.cn");Map map2 = new HashMap();map2.put("name","xiaoli");map2.put("address","nanjing");map2.put("email","xiaoli@itcast.cn");list.add(map1);list.add(map2);//填充数据,使用javaBean类   JasperPrint jasperPrint =JasperFillManager.fillReport(jasperPath,paramters,new JRBeanCollectionDataSource(list));//定义输出文件位置String pdfPath = "D:\\test.pdf";JasperExportManager.exportReportToPdfFile(jasperPrint,pdfPath); //导出}
}

Color.YELLOW)); //填充新样式
if(name.length==2) {//判断分割后的结果是否真的到达热门板块
Map map = (Map) result.get(name[0]); //key,此处的key为hotSetmeal
cell.setCellValue("" + map.get(name[1])); //value
}else{
//模板中每个需要填写的单元格的值都是result查询结果的key
cell.setCellValue("" + result.get(cell.getStringCellValue()));
}
}
}
}
}
}
}

        //使用输出流进行表格下载,基于浏览器作为客户端下载OutputStream out = response.getOutputStream();response.setContentType("application/vnd.ms-excel");//代表的是Excel文件类型response.setHeader("content-Disposition", "attachment;filename=report.xlsx");//指定以附件形式进行下载excel.write(out);out.flush();out.close();

// excel.close();
return null;
}catch (Exception e){
e.printStackTrace();
return new Result(false,MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);
}
}
}

## JasperReport模拟设计器​		注意:1.使用表单的时候 由于指定过数据源,所以可以显示数据​					但是如果在程序中执行,那么是没有办法关闭的。会有问题,所以不用​					2.在生成边框时,为了没有间隙。要对每个区域进行缩小至上一个区域的下标线​					3.中文不能正常显示,要使用华文宋体且加入布丁文件与jrxml模板同级==以后都尽量不使用feilds功能制作报表?==输出流 ateBytes 。tostringXX.class. -->getResource(“ ”) 拿同包下文件getResource(“/ ”)拿class文件下的文件getClassLoader.getResource(“ ”)getClassLoader.getResource(“ /”)入门案例```java@Testpublic void show() throws Exception {//定义模板位置String jrxmlPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jrxml";//定义虚拟输出位置和名字String jasperPath ="F:\\ideaProject\\project\\projectHEALTH\\controller\\src\\main\\resources\\demo.jasper";JasperCompileManager.compileReportToFile(jrxmlPath,jasperPath);  //编译模板//定义头数据Map paramters = new HashMap();paramters.put("reportDate","2019-10-10");paramters.put("company","itcast");//定义模板主数据List<Map> list = new ArrayList();HashMap<Object, Object> map1 = new HashMap<>();map1.put("name","xiaoming");map1.put("address","beijing");map1.put("email","xiaoming@itcast.cn");Map map2 = new HashMap();map2.put("name","xiaoli");map2.put("address","nanjing");map2.put("email","xiaoli@itcast.cn");list.add(map1);list.add(map2);//填充数据,使用javaBean类   JasperPrint jasperPrint =JasperFillManager.fillReport(jasperPath,paramters,new JRBeanCollectionDataSource(list));//定义输出文件位置String pdfPath = "D:\\test.pdf";JasperExportManager.exportReportToPdfFile(jasperPrint,pdfPath); //导出}
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 什么是高速通道?

    什么是高速通道&#xff1f; 更新时间&#xff1a;2019-12-30 14:28:40 编辑我的收藏 本页目录 组成部分优势专线连接和VPN连接对比 阿里云高速通道&#xff08;Express Connect&#xff09;可在本地数据中心和云上专有网络间建立高速、稳定、安全的私网通信。高速通道的专…...

    2024/4/7 13:51:06
  2. 云服务器 ECS > 安全 > 安全组 > 添加安全组规则

    添加安全组规则 更新时间&#xff1a;2020-07-01 16:03:49 编辑我的收藏 本页目录 前提条件背景信息操作步骤执行结果后续步骤相关文档 您可以通过添加安全组规则&#xff0c;允许或禁止安全组内的ECS实例对公网或私网的访问。 前提条件 添加安全组规则之前&#xff0c;请…...

    2024/4/10 0:30:02
  3. 大数据分析Python中spaCy文本分类使用教程

    文本是极其丰富的信息源。人们每分钟都会发送数亿封新电子邮件和短信。确实有大量的文本数据等待挖掘见解。但是&#xff0c;想要从所有文本数据中收集含义的数据科学家面临着一个挑战&#xff1a;由于它以非结构化形式存在&#xff0c;因此难以分析和处理。 在大数据分析Pytho…...

    2024/4/7 20:16:22
  4. xshell远程连接自己的vmware虚拟机中的ubuntu

    首先用ifconfig看自己的ip地址&#xff0c; 然后检查自己的ssh是否打开&#xff1a; 输入ps -e | grep ssh 后&#xff0c;是否出现sshd&#xff0c;什么都没有出现说明没有安装。 安装方法&#xff1a;sudo apt-get install openssh-server 注&#xff1a;自己…...

    2024/4/19 3:18:28
  5. 标题您的主机不满足在启用 Hyper-V 或 Device/Credential Guard 的情况下运行 VMware Workstation 的最低要求

    标题您的主机不满足在启用 Hyper-V 或 Device/Credential Guard 的情况下运行 VMware Workstation 的最低要求 电脑为win10 家庭中文版&#xff0c;家庭版是没有gpedit.msc的&#xff0c;所以按照网上大多数的解决方案是行不通的 错误提示&#xff1a;您的主机不满足在启用 H…...

    2024/4/12 11:18:48
  6. Clion linux开发环境搭建

    clion 下载 安装 https://download.jetbrains.8686c.com/cpp/CLion-2019.3.tar.gz linux开发环境搭建 sudo apt-get install build-essential clion 配置 File->Setting->Build,Execution,Deployment 项目刷新 项目文件夹右键->Reload Cmake Project...

    2024/4/10 3:47:13
  7. hadoop集群时间校准ntp服务

    通过yum install ntp安装通过 cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 设置集群在同一时区通过命令 ntpdate -u 0.cn.pool.ntp.org设置校准的服务器设置开启自启vim /etc/ntp.conf 添加 server 0.cn.pool.ntp.org # centos给我们设置了几个时间校准的服务,但是国…...

    2024/4/13 20:53:36
  8. 【面经】寒冬中的一年半前端跳槽

    面试内容 小米-小米应用商店&#xff08;过&#xff09; 一面 小米的面试官给人的感觉很亲切很真诚&#xff0c;是一个体验很不错的面试。 css实现图片自适应宽高讲flex&#xff0c;手写出flex常用的属性&#xff0c;并且讲出作用BFC是什么项目里面的前端鉴权是怎么实现的&…...

    2024/4/7 15:46:01
  9. web前端面试题对答篇:谈谈你对Promise的理解

    回答这个问题时&#xff0c;个人不建议单纯的从Promise的细节知识点答起&#xff0c;因为这个问题的本质是拥有一定宏观性的&#xff0c;如果仅仅回复一些知识点恐怕是满足不了面试官胃口的。 当然&#xff0c;如果这个问题回答不到点上&#xff0c;那么后续面试官极有可能会抛…...

    2024/4/7 17:38:31
  10. 你可能还没有听过“奶嘴理论”这个词,但是你可能已经被它毁了

    你在忙碌了一天之后&#xff0c;无论是学习还是工作&#xff0c;拖着有点麻木的双腿回到家里&#xff0c;坐在沙发上感觉自己都被掏空了。这时候总有一个思维想要问自己&#xff0c;为什么我会这么累&#xff1f;为什么我这么辛苦还是这么穷&#xff1f;我什么时候才能实现财富…...

    2024/4/7 16:40:48
  11. Mac音频编辑软件——NCH WavePad for Mac

    NCH WavePad for Mac适用于Mac&#xff0c;功能齐全&#xff0c;是专业的音频和音乐编辑器&#xff0c;&#xff0c;你可以使用WavePad Mac破解版剪切&#xff0c;复制和粘贴录音部分&#xff0c;然后添加效果&#xff0c;如回声&#xff0c;放大和降噪。 NCH WavePad for Mac功…...

    2024/4/18 10:14:48
  12. 【云周刊】第172期:阿里云总裁胡晓明:“自主研发、共生共存、不碰数据是我们的三条生命线“...

    本期头条 **阿里云总裁胡晓明&#xff1a;"自主研发、共生共存、不碰数据是我们的三条生命线" ** ** ** 5月23日&#xff0c;在云栖大会武汉峰会上&#xff0c;阿里云总裁胡晓明系统阐述了这家公司坚守的三条生命线。 -坚持自主研发之路&#xff0c;"拿来主义…...

    2024/4/7 14:15:28
  13. 《深入理解计算机系统》--前言

    《深入理解计算机系统》--前言目标主要内容方法术语翻译准备知识目录1.计算机系统漫游2.信息的表示和处理3.程序的机器级表示4.处理器体系结构5.优化程序性能6.存储器层次结构7.链接8.异常控制流9.虚拟内存10.系统级I/O11.网络编程12.并发编程目标 了解程序在计算机系统上的实…...

    2024/4/6 7:01:58
  14. Android权限

    名称权限值及说明访问登记属性android.permission.ACCESS_CHECKIN_PROPERTIES &#xff0c;读取或写入登记check-in数据库属性表的权限获取错略位置android.permission.ACCESS_COARSE_LOCATION&#xff0c;通过WiFi或移动基站的方式获取用户错略的经纬度信息&#xff0c;定位精…...

    2024/4/17 17:59:53
  15. 信息发布系统模块功能定义简述

    信息发布系统共有&#xff1a;用户管理、资源管理、设备管理、模块管理、节目管理、任务管理、统计分析、角色管理和系统管理九个模块。 一、用戶管理 1、用戶的基本信息 用戶名 手機號 密碼 公司名稱 地址 企業認證相關信息&#xff08;营业執照&#xff0c;納稅稅號&…...

    2024/4/13 20:59:15
  16. 一文缕顺Serdes的前前后后

    一文缕顺Serdes的前前后后 原创 神采逸逸 发表于 微信公众号&#xff1a;非主流EE 之 华山派 &#xff08;微信公众号ID: SerdesWorld&#xff09; 本文借用 ‘包容链’ 的逻辑来展开描述。 Serdes应当属于一种 数据传输的接口技术&#xff0c;一般用在高速传输的场合。 谈…...

    2024/4/8 18:14:02
  17. 刚去面试Spring Cloud 问了我35个问题,全部分享出来!

    ❝对于目前来说&#xff0c;微服务已经是程序员必会的技能之一了。Spring Cloud 作为一个优质的微服务框架&#xff0c;已经被很多公司使用。以下小编给大家整理35道Spring Cloud 的知识点&#xff0c;或者说是面试题都不冲突。后续还会继续更新⛽️❞ 1.什么是SpringCloud? …...

    2024/4/8 13:30:57
  18. tomcat 乱码解决

    在 tomcat / conf 目录下&#xff0c;设置 logging.properties &#xff0c;增加参数 java.util.logging.ConsoleHandler.encoding GBK...

    2024/4/8 4:21:32
  19. ceph pg Troubleshoting

    Troubleshoting pg stuck placement group pg 显示 degraded 和 peering 状态很正常&#xff0c;这些信息一般表明对失败的恢复过程采取的正常行动。但是&#xff0c;如果 pg 长时间处于这种状态&#xff0c;表明可能问题很严重。 inactive&#xff1a;pg 太长时间没有 acti…...

    2024/4/14 19:06:08
  20. Golang基础(new函数)

    一.new函数 在上一小节中学习了指针,每次创建一个指针必须在额外创建一个变量,操作比较麻烦. 可以通过new函数直接创建一个类型的指针 变量名:new(Type) 使用new函数创建的指针已有指向,可以使用*指针对象进行赋值. func main() {a : new(int)fmt.Println(a) //输出:指针地址…...

    2024/4/10 19:20:38

最新文章

  1. 机器学习笔记——浅析L2,1范数正则化的线性回归

    前言 嘻嘻&#xff0c;刚开始搓逾期了快两周的线性回归实验报告&#xff0c;为了让报告稍微不那么平淡不得不啃论文。 本文从最基本的线性回归开始&#xff0c;对比不同正则化方法的特点和作用&#xff0c;推广到多任务问题并引出L2,1范数正则化&#xff0c;卑微小采购尝试去…...

    2024/4/20 19:34:39
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. __dirname 在ES模块中的使用

    前言 ECMAScript模块是 JavaScript 的新标准格式。在Node.js中越来越多的库逐渐从从CommonJS转移到ES模块 注&#xff1a;这里是指“真”ES 模块并不是指代码中 Node.js 中使用 import 写法但是实际被 tsc 转成 commonJS 的形式 但是Node.js ES 开发中此前有一个棘手的问题是获…...

    2024/4/17 8:07:25
  4. 多态--下

    文章目录 概念多态如何实现的指向谁调谁&#xff1f;例子分析 含有虚函数类的大小是多少&#xff1f;虚函数地址虚表地址多继承的子类的大小怎么计算&#xff1f;练习题虚函数和虚继承 概念 优先使用组合、而不是继承; 继承会破坏父类的封装、因为子类也可以调用到父类的函数;…...

    2024/4/16 22:07:08
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/4/19 19:02:10
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/4/20 15:00:23
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/4/19 11:33:34
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/4/19 11:52:08
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/4/20 9:42:32
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/4/20 7:01:14
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/4/19 11:52:49
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/4/19 18:52:15
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/4/19 23:08:02
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/4/20 0:22:23
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/4/19 23:04:54
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/4/20 1:12:38
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/4/19 3:53:57
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/4/19 19:50:16
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/4/20 1:43:00
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/4/20 13:55:02
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/4/19 23:35:17
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/4/19 10:00:05
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/4/20 6:45:17
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/4/20 3:28:04
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57