在项目中应用
进行认证和授权需要前面课程中提到的权限模型涉及的7张表支撑,因为用户信息、权限信息、菜单信息、角色信息、关联信息等都保存在这7张表中,也就是这些表中的数据是进行认证和授权的依据。所以在真正进行认证和授权之前需要对这些数据进行管理,即需要开发如下一些功能:
1、权限数据管理(增删改查)
2、菜单数据管理(增删改查)
3、角色数据管理(增删改查、角色关联权限、角色关联菜单)
4、用户数据管理(增删改查、用户关联角色)
导入Spring Security环境
第一步:在health_parent父工程的pom.xml中导入Spring Security的maven坐标
第二步:在health_backend工程的web.xml文件中配置用于整合Spring Security框架的过滤器DelegatingFilterProxy
实现认证和授权
第一步:在health_backend工程中按照Spring Security框架要求提供SpringSecurityUserService,并且实现UserDetailsService接口
第二步:创建UserService服务接口、服务实现类、Dao接口、Mapper映射文件等
第三步:修改health_backend工程中的springmvc.xml文件,修改dubbo批量扫描的包路径
第四步:在health_backend工程中提供spring-security.xml配置文件
第五步:在springmvc.xml文件中引入spring-security.xml文件
<!--设置在页面可以通过iframe访问受保护的页面,默认为不允许访问-->
<security:frame-options policy="SAMEORIGIN"></security:frame-options>
显示用户名
第一步:在main.html页面中修改,定义username模型数据基于VUE的数据绑定展示用户名,发送ajax请求获取username
第二步:创建UserController并提供getUsername方法
注意此处的User对象是使用到框架提供的User对象,框架通过session获得模型数据的信息
@RestController
@RequestMapping("/user")
public class UserController {
//获取当前登录用户的用户名
@RequestMapping("/getUsername")
public Result getUsername()throws Exception{
try{
org.springframework.security.core.userdetails.User user =
(org.springframework.security.core.userdetails.User)
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return new Result(true, MessageConstant.GET_USERNAME_SUCCESS,user.getUsername());
}catch (Exception e){
return new Result(false, MessageConstant.GET_USERNAME_FAIL);
}
}
}
用户退出
第一步:在main.html中提供的退出菜单上加入超链接
第二步:在spring-security.xml文件中配置
Echarts图表
动态显示图标的x轴为具体的yyyy-MM格式
导入ECharts库
第一步:将echarts.js文件复制到health_backend工程的plugins目录下
第二步:在report_member.html页面引入echarts.js文件
<script src="../plugins/echarts/echarts.js"></script>
参照官方实例导入折线图
<div class="box">
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="chart1" style="height:600px;"></div>
</div>
// 基于准备好的dom,初始化echarts实例
var myChart1 = echarts.init(document.getElementById('chart1'));
//发送ajax请求获取动态数据
axios.get("/report/getMemberReport.do").then((res)=>{
myChart1.setOption(
{
title: {
text: '会员数量'
},
tooltip: {},
legend: {
data:['会员数量']
},
xAxis: {
data: res.data.data.months
},
yAxis: {
type:'value'
},
series: [{
name: '会员数量',
type: 'line',
data: res.data.data.memberCount
}]
});
});
</script>
后台代码
controller
/**
* 统计报表
*/
@RestController
@RequestMapping("/report")
public class ReportController {
@Reference
private MemberService memberService;
/**
* 会员数量统计
* @return
*/
@RequestMapping("/getMemberReport")
public Result getMemberReport(){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH,-12);//获得当前日期之前12个月的日期
List<String> list = new ArrayList<>();
for(int i=0;i<12;i++){
calendar.add(Calendar.MONTH,1);
list.add(new SimpleDateFormat("yyyy.MM").format(calendar.getTime()));
}
Map<String,Object> map = new HashMap<>();
map.put("months",list);
List<Integer> memberCount = memberService.findMemberCountByMonth(list);
map.put("memberCount",memberCount);
return new Result(true, MessageConstant.GET_MEMBER_NUMBER_REPORT_SUCCESS,map);
}
}
注意Mapper文件中的转义字符
在mysql8.0中上述sql查询语句会显示日期出错,更改查询方式
'%Y.%m'不等于'%Y-%m'
图形报表
导入饼形图步骤
1.设置一个div
2.导入官方文档的option
3.明确Contrller响应的数据格式
4.书写controller
//套餐预定占比饼形图
@RequestMapping("/getSetmealReport")
public Result getSetmealReport(){
//模拟数据测试什么样的java对象转为饼形图所需的json数据格式
Map<String,Object> data = new HashMap<>();
try{
List<Map<String,Object>> setmealCount = setmealService.findSetmealCount();
data.put("setmealCount",setmealCount);
//遍历集合中的map得到名称
List<String> setmealNames = new ArrayList<>();
for(Map<String,Object> map : setmealCount){
String name = (String) map.get("name");//套餐名称
setmealNames.add(name);
}
data.put("setmealNames",setmealNames);
return new Result(true, MessageConstant.GET_SETMEAL_COUNT_REPORT_SUCCESS,data);
}catch (Exception e){
e.printStackTrace();
return new Result(false, MessageConstant.GET_SETMEAL_COUNT_REPORT_FAIL);
}
}
后续完善service,ServiceImpl,Dao,Mapper文件
POI报表
前端代码
定义模型数据
定义数据模型,通过VUE的数据绑定展示数据
Controller返回的数据格式应该如下
{
"data":{
"todayVisitsNumber":0,
"reportDate":"2019-04-25",
"todayNewMember":0,
"thisWeekVisitsNumber":0,
"thisMonthNewMember":2,
"thisWeekNewMember":0,
"totalMember":10,
"thisMonthOrderNumber":2,
"thisMonthVisitsNumber":0,
"todayOrderNumber":0,
"thisWeekOrderNumber":0,
"hotSetmeal":[
{"proportion":0.4545,"name":"粉红珍爱(女)升级TM12项筛查体检套餐","setmeal_count":5},
{"proportion":0.1818,"name":"阳光爸妈升级肿瘤12项筛查体检套餐","setmeal_count":2},
{"proportion":0.1818,"name":"珍爱高端升级肿瘤12项筛查","setmeal_count":2},
{"proportion":0.0909,"name":"孕前检查套餐","setmeal_count":1}
],
},
"flag":true,
"message":"获取运营统计数据成功"
}
在Controller类中调用Service,Service的实现类
public Map<String, Object> getBusinessReportData() throws Exception {
//获得当前日期
String today = DateUtils.parseDate2String(DateUtils.getToday());
//获得本周一的日期
String monday = DateUtils.parseDate2String(DateUtils.getThisWeekMonday());
//获得本月第一天的日期
String firstDay4ThisMonth = DateUtils.parseDate2String(DateUtils.getFirstDay4ThisMonth());
//本日新增会员数
Integer todayNewMember = memberDao.findMemberCountByDate(today);
//总会员数
Integer totalMember = memberDao.findMemberTotalCount();
//本周新增会员数
Integer thisWeekNewMember = memberDao.findMemberCountAfterDate(monday);
//本月新增会员数
Integer thisMonthNewMember = memberDao.findMemberCountAfterDate(firstDay4ThisMonth);
//热门套餐(取前4)
List<Map> hotSetmeal = orderDao.findHotSetmeal();
//报表产生日期
Map<String,Object> result = new HashMap<>();
result.put("reportDate",today);
result.put("todayNewMember",todayNewMember);
result.put("totalMember",totalMember);
result.put("thisWeekNewMember",thisWeekNewMember);
result.put("thisMonthNewMember",thisMonthNewMember);
result.put("hotSetmeal",hotSetmeal);
return result;
}
补充相关的Dao和Mapper文件
报表导出
上面的Excel效果可以看到,表格比较复杂,涉及到合并单元格、字体、字号、字体加粗、对齐方式等的设置。如果通过POI编程的方式来设置这些效果代码会非常繁琐。
在企业实际开发中,对于这种比较复杂的表格导出一般会提前设计一个Excel模板文件,在这个模板文件中提前将表格的结构和样式设置好,程序只需要读取这个文件并在文件中的相应位置写入具体的值就可以了。
前端代码
<div class="excelTitle" >
<el-button @click="exportExcel">导出Excel</el-button>运营数据统计
</div>
methods:{
exportExcel(){
window.location.href = '/report/exportBusinessReport.do';
}
}
后端代码
try{
Map<String,Object> result = reportService.getBusinessReportData();
//取出返回结果数据,准备将报表数据写入到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");
List<Map> hotSetmeal = (List<Map>) result.get("hotSetmeal");
//获得Excel模板文件绝对路径
String filepath = request.getSession().getServletContext().getRealPath("template") + File.separator + "report_template.xlsx";
//基于提供的Excel模板文件在内存中创建一个Excel表格对象
XSSFWorkbook excel = new XSSFWorkbook(new FileInputStream(new File(filepath)));
//读取第一个工作表
XSSFSheet sheet = excel.getSheetAt(0);
//获得第三行的第六个单元格
XSSFRow row = sheet.getRow(2);
XSSFCell cell = row.getCell(5);
cell.setCellValue(reportDate);//日期在Excel中对应的单元格位置
row = sheet.getRow(4);
row.getCell(5).setCellValue(todayNewMember);//新增会员数(本日)
row.getCell(7).setCellValue(totalMember);//总会员数
row = sheet.getRow(5);
row.getCell(5).setCellValue(thisWeekNewMember);//本周新增会员数
row.getCell(7).setCellValue(thisMonthNewMember);//本月新增会员数
int rowNum = 12;
for(Map map : hotSetmeal){//热门套餐
String name = (String) map.get("name");
Long setmeal_count = (Long) map.get("setmeal_count");
BigDecimal proportion = (BigDecimal) map.get("proportion");
row = sheet.getRow(rowNum ++);
row.getCell(4).setCellValue(name);//套餐名称
row.getCell(5).setCellValue(setmeal_count);//预约数量
row.getCell(6).setCellValue(proportion.doubleValue());//占比
}
//通过输出流进行文件下载,基于浏览器作为客户端下载
ServletOutputStream 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){
return new Result(true,MessageConstant.GET_BUSINESS_REPORT_FAIL);
}