项目整体功能概述
- 本项目是基于SSM、RPC框架实现的旅游后台管理系统,可对*行、跟团游、套餐游等进行相关的CRUD操作,有着用户角色的权限控制、运营数据的统计分析、文件的上传下载、数据导入、百度地图定位公司地址等功能。
一.SSM
1.springMVC
概述MVC与三层架构的关系:
(1) Model:数据模型层
用于处理数据,进行业务逻辑判断,数据库存取。其分为两类:
一类称为数据承载 Bean:实体类,专门用户承载业务数据的,如 本项目中的旅游订单Order、旅游会员User 等。
一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理用户提交请求的。
其中在service层中需要的配置
-(1)配置事务管理器transactionManager
-(2)开启事务控制的注解,其中配置proxy-target-class="true",其作用是使用cglib代理方式为Service类创建代理对象。那为什么需要用cglib的代理方式呢?
因为Dubbo需要将Service发布为服务,配置文件扫描的包为com.luochenggui.service,假如默认使用jdk的动态代理,创建的代理对象完整类名为com.sun.proxy.$Proxy35,导致Dubbo在进行包匹配时没有成功,服务发布失败,所以要求必须使用cglib创建代理对象
另外需要在Service注解中加入interfaceClass属性,否则会导致发布的服务接口为SpringProxy,而不是我们定义的Service接口
-(3)jedisPoolConfig相关参数配置与jedisPool
-(4)spring整合dubbo的相关配置,指定发布服务的名称、暴露服务的接口(一般在服务提供者一方配置,可以指定使用的协议名称和端口号)、指定服务注册中心的地址、批量扫描,发布服务
-(5)最后在web.xml中配置ContextLoaderListener,当web容器启动的时候,自动加载spring容器
(2) view:视图层
为用户提供使用界面,与用户直接进行交互。本项目所用到的技术为:
- vue,其核心是数据驱动、组件化
使用该框架能够使我们专注于View 层。省去了操作DOM的过程,只需要改变数据。Vue会通过Dircetives指令,对DOM做一层封装,当数据发生改变会通知指令去修改对应的DOM,数据驱动DOM变化,DOM是数据的一种自然映射。 - ElementUI,是一套基于VUE2.0的桌面端组件库。本项目的后台就是使用它来构建页面。
(3) controller:控制层
控制器,用于将用户请求转发给相应的 Model 进行处理,并根据 Model 的计算结果向用户提供相应响应。
其中在controller层中需要的配置
- 配置mvc的注解驱动:mvc:annotation-driven
- 配置文件上传组件multipartResolver
- spring整合dubbo的相关配置,指定服务的名称、指定服务注册中心地址、批量扫描、是否检查服务提供方。
- 在web.xml中配置dispatchservlet,这是springmvc的核心控制器,当web容器启动的时候,会自动加载springmvc.xml。配置字符过滤器解决请求乱码问题。
2.spring
作为管理组件,管理整个应用中所有 Bean 的生命周期行为。
即整个应用中所有对象的创建、初始化、销毁,及对象间关联关系的维护,均由 Spring 进行管理。
- IOC控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。而IOC容器,就是 IOC 思想的一个落地的产品实现。
- 面向切面编程AOP
(1)使用jdk动态代理,创建接口实现类的对象,增强类的方法
(2)使用CGLIB动态代理,继承父类方法,创建子类的代理对象,增强类的方法
3.mybatis
(1) 使用Druid连接池配置数据源
(2)使用pagehelper作为分页插件
(3)使用sqlsessionfactory来执行SQL语句
在这个bean中将数据源、分页插件的配置、给包取别名配置进来
(4)扫描mapper接口生成代理对象
二.dubbo远程过程调用
Apache Dubbo是一款高性能的Java RPC框架。Dubbo提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
1.Dubbo各节点之间的调用关系
节点 | 角色描述 |
---|---|
Consumer | 调用远程服务的服务消费方 |
Provider | 暴露服务的服务提供方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
- (1)Container负责启动,加载,运行服务提供者
- (2)Provider在启动时,向注册中心注册自己提供的服务
- (3)Consumer在启动时,向注册中心订阅自己所需的服务
- (4)注册中心Registry返回Provider的地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
- (5)Consumer从Provider地址列表中,基于负载均衡算法(随机、轮询、一致性hash、主备master-slave)选一台提供者进行调用,如果调用失败,再选另一台调用
- (6)Consumer和Provider在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心Registry
2.服务注册中心Zookeeper
在上面的调用关系可以看出,Registry(服务注册中心)在其中起着至关重要的作用,Dubbo官方推荐使用Zookeeper作为服务注册中心。那如何防止Zookeeper单点故障?Zookeeper其实是支持集群模式的,可以配置Zookeeper集群来达到Zookeeper服务的高可用,防止出现单点故障
三.fileupload文件上传
在 SpringMVC 的配置文件中加入 multipart 类型数据的解析器
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定文件上传的最大值为100MB,10*1024*1024 -->
<property name="maxUploadSize" value="104857600" />
<!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
<property name="maxInMemorySize" value="4096" />
<!-- 设定默认编码 -->
<property name="defaultEncoding" value="UTF-8"/>
</bean>
利用MultipartFile接口中的方法,getOriginalFilename()方法获取文件的原始名,再对原始名进行字符串操作,使用UUID随机产生文件名称,防止同名覆盖。getBytes()方法获取文件的字节数组。将两个参数传到七牛云文件上传的方法,执行上传。
四.quartz-scheduler任务调度
Quartz是Job scheduling(作业调度)领域的一个开源项目,Quartz既可以单独使用也可以跟spring框架整合使用,在实际开发中一般会使用后者。使用Quartz可以开发一个或者多个定时任务,每个定时任务可以单独指定执行的时间,例如每隔1小时执行一次、每个月第一天上午10点执行一次、每个月最后一天下午5点执行一次等。
1.Quartz整合spring
<!--注册自定义Job-->
<bean id="clearImgJob" class="com.atguigu.job.ClearImgJob"/>
<!--注册JobDetail,作用:负责通过反射调用指定的Job-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--注入目标对象-->
<property name="targetObject" ref="clearImgJob"/>
<!--注入目标方法-->
<property name="targetMethod" value="clearImg"/>
</bean>
<!--注册一个触发器,指定任务的触发时间-->
<bean id="clearImgTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--注入jobDetail-->
<property name="jobDetail" ref="jobDetail"/>
<!-- 指定触发的时间,基于Cron表达式(0 0 2 * * ?表示凌晨2点执行) -->
<property name="cronExpression">
<value>0 0 2 * * ?</value>
</property>
</bean>
<!--注册一个统一的调度工厂,通过这个调度工厂调度任务-->
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!--注入多个触发器-->
<property name="triggers">
<ref bean="clearImgTrigger"/>
</property>
</bean>
在定时任务的方法里,先用sdiff()方法计算Redis中两个集合的差集,获取垃圾图片名称,在调用七牛云中删除文件的方法,完成定时删除垃圾图片。
2.cron表达式
五.七牛云服务平台(图片上传)
图片上传整体流程如下:
图片上传的具体方法可以参照官网提供的API文档https://developer.qiniu.com/kodo/sdk/1239/java
七牛云操作对象存储服务。
六.POI报表(EXCEL)
Apache POI 该链接提供相关操作excel表的api。如导出Excel,导入Excel到数据库中。在本项目中,有两个模块的功能需要用到Excel操作:
(1)从excel中读取预约设置信息,批量导入到数据库,controller层实现方法:使用poi工具类解析excel文件,读取里面的内容,即POIUtils.readExcel(excelFile),然后将对应表格中的数据,用相应实体类进行封装。
(2)将旅游的整体运营统计数据导出,controller层实现方法:
- 先获得Excel模板文件绝对路径temlateRealPath
- 读取模板文件创建Excel表格对象:new XSSFWorkbook(new FileInputStream(new File(temlateRealPath)));
- 逐行逐列写入数据:
读行:XSSFRow row = sheet.getRow(2);
读列:row.getCell(5).setCellValue(reportDate) - 通过输出流进行文件下载,设置下载的数据类型(excel类型,以及下载形式(通过附件的形式下载)
七.redis
配置
在service层,controller层(web层),定时任务的jobs层都需要配置jedisPoolConfig相关参数配置与jedisPool
前面我们已经完成了文件上传,将图片存储在了七牛云服务器中。但是这个过程存在一个问题,就是如果用户只上传了图片而没有最终保存套餐信息到我们的数据库,这时我们上传的图片就变为了垃圾图片。对于这些垃圾图片我们需要定时清理来释放磁盘空间。这就需要我们能够区分出来哪些是垃圾图片,哪些不是垃圾图片。如何实现呢?
方案就是利用redis来保存图片名称,具体做法为:
1、当用户上传图片后,将图片名称保存到redis的一个Set集合中,例如集合名称为 setmealPicResources
2、当用户添加套餐后,将图片名称保存到redis的另一个Set集合中,例如集合名称为setmealPicDbResources
3、用sdiff()方法计算 setmealPicResources集合与 setmealPicDbResources集合的差值,结果就是垃圾图片的名称集合,清理这些图片即可
八.spring security安全框架
- 配置spring-security.xml
1:定义哪些链接可以放行
2:定义哪些链接不可以放行,即需要有角色、权限才可以放行
3:认证管理,定义登录账号名和密码,并授予访问的角色、权限 - 在Controller的方法上加入权限控制注解:@PreAuthorize("hasAuthority(\'TRAVELITEM_EDIT\')")
九.图形报表ECharts
(1) 概述:
- ECharts缩写来自Enterprise Charts,商业级数据图表,是百度的一个开源的使用JavaScript实现的数据可视化工具。可绘制柱状图、折线图、饼图等各种用于数据展示的效果图
(2) 使用方法
- 使用ECharts展示图表效果,关键点在于确定此图表所需的数据格式,然后按照此数据格式提供数据就可以了,我们无须关注效果是如何渲染出来的。在实际应用中,我们要展示的数据往往存储在数据库中,所以我们可以发送ajax请求获取数据库中的数据并转为图表所需的数据即可。
这一步对我们List、Map等集合容器的使用,以及如何从数据库查询响应的数据,并把数据封装到合适的集合容器中去,就有了更高的要求。
例:
十.阿里云短信发送
用于用户注册时,进行发送验证码进行短信验证