面试困惑
欢迎使用Markdown编辑器
我叫XX,XX年出生,来自XX,从事Java软件开发行业4年多了,在这4年里,我接触到了一些主流框架并有了深刻的理解,项目开发中,熟悉使用struts2、spring、hibernate、mybatis等并参与搭建过SSH/SSM/SpringMVC+Mybatis等框架。对springBoot也略有研究.关于前台的框架,使用过基于jquery的esayUI等。
也参与了项目数据库的选择以及对数据库的设计,选择合适的持久层框架,之前常用的数据库有关系型数据库oracle、 mysql,非关系数据库Mongodb、redis等,特别是redis除了使用外我也做过一些其他的研究,比如说它作为缓存技术的使用、nginx和tomcat以及redis的集群环境搭建等。
考虑到开发项目的高效性,也使用了一些常用的主流java技术,如webservice、httpclient、jsonp、dubbo+zookeeper等技术框架,还有POI导入导出技术、ECharts报表技术等。为了向相关人员定时发送通知,用到了Spring定时器和JavaMail邮件发送、短信发送技术,对项目进行测试使用junit技术。
使用过Eclipse、MyEclipse、Idea等开发工具,为了方便项目的打包部署,还用到了maven进行相关jar包的依赖管理,同时利用业余时间熟悉了Linux操作系统。也能熟练使用powerdesigner数据库建模等工具的一些基本操作。
几年开发,主要涉及的行业项目包括电子商务、OA办公平台等。
接下来我给您简单介绍一下我的上一个项目吧?
【项目一】欢乐购商城电商系统
1:项目简介
上个项目,我负责的是一个电商项目叫欢乐购购物商城,该商城是采用分布式架构部署的一个中小型网上购物商城系统。本系统分前台系统和后台管理系统。前台系统主要负责商城的页面的显示功能,这里采用的面向服务的方式,pc端手机端只负责显示页面,业务逻辑都在服务层实现,客户端调用服务端接口来实现显示功能。
2:分析
前台系统主要有: 积分商城、商品展示、商品信息搜索框、购物车、商品秒杀、订单查询、浏览记录、商品排行、客服服务、留言评论、商品品牌展示、会员注册及登录等;
后台系统主要有: 商品管理、用户管理、活动管理、订单管理、WMS(仓库管理系统)、财务管理、报表统计、系统管理、运营管理、店铺管理、支付管理、推广管理等
其实当时我主要负责的也挺多模块的,前台系统里面有购物车(redis)、商品信息搜索框(solr)、商品秒杀、留言评论(MongoDB);后台系统这一块我主要负责WMS(仓库管理)、商品管理模块、统计分析模块、推广管理模块、权限的管理、订单管理(拆单)、财务管理。
本系统前台界面设计采用的easyUI的设计,后台采用springMVC、spring、mybatis框架,maven管理的多模块项目,采用java语言编程。
我在项目中除了主要负责的购物车模块和订单模块之外,对其它模块也是有一定的了解的.接下来我给大家介绍一下.
3:具体实现
3.1:项目的搭建
这里采用maven多模块管理整个项目。优势两点:1、maven可以管理整个项目工程,方便热部署项目,项目发布方便。2、maven管理jar包具有很大的优势,可以自动下载所需的jar包,只需定义好版本即可,其他maven自动下载。
下面就是利用SSM框架来搭建工程了:利用框架搭建工程主要分两步:框架所依赖的jar包,框架的配置文件。弄清了这两点就好办了。框架主要分三层:mapper层(mybatis)(主要是与数据库交互)、service层(spring)(主要是负责调用dao/mapper层,实现业务逻辑的编写)、controller层(springMVC)(这里主要调用service层,根据jsp页面的内容,将jsp的内容传递到service层,然后将数据显示到jsp页面)。所以这里的配置文件也就有:spring将mybatis整合起来的spring-common.xml(配置数据源,与数据库的连接),另外配置了jdbc.properties(把链接数据库配置信息提取出来方便管理),spring-base.xml(将service的文件包引入工程,以及配置事务管理器),还有spring-mvc.xml(注解扫描,前端控制器,视图解析器),还有log4j.properties(日志记录)。
框架搭建完成后,利用mybatis的逆向工程(generator)生成各个表的model文件。
3.2具体的功能的实现逻辑
(1)后台系统功能实现
(这里主要讲商品的查询、添加)
其实对于功能模块的分析主要有三点:
从哪个数据表获取(主要mapper实现);页面传递是否有参数,页面的url是什么(controller实现);返回值是什么(即页面展示的格式是什么样子的,这个根据jsp使用的框架来决定,比如这里的easyUI,可以查询它的api文档,找到其返回值类型);
A、商品的查询逻辑分析:其实对于商品的查询主要就是从数据库中将所有商品查询出来。这简单的查询很简单,可是在页面分页显示出来这就是一个问题了。这里到了mybatis的分页插件pageHelper来实现。
传入参数:Easyui页面默认有page、rows参数传递。
返回值:easyui的格式即datagrid的格式,专门编写一个对应的pojo类放入专门工具类中使用,返回格式即这个pojo。
逻辑:mapper层:mapper层用mybatis的逆向工程
Service调用mapper的查询和分页实现逻辑。
Controller即将参数传递过去,url写好
B、商品添加:商品添加即将商品信息写入数据库,页面传递的内容当点击提交按钮时直接写入数据库,只需补全没有的字段即可。
这里涉及到商品的类目选择、上面的图片上传、商品的描述信息。
类目选择首先得将类目展示出来,这里使用的异步树的格式。查询api发现异步树的返回值的格式。主要思路是:根据parentId来查询类目表,默认从0开始,异步树有个特点,就是每次获取到的id,如果有子节点,会发送url再次请求,如果没有子节点则不发送请求,所以可以都遍历到所有节点。(这个是tree的特点,自动请求)
异步树的特点:从最顶层开始读取,先读顶层节点,如果是闭合状态,发送请求给服务器读取子节点,子节点的状态依赖于父节点,当展开一个封闭的节点时,如果节点没有加载子节点,它将会把节点的id的值作为http请求参数并命名为id,通过url发送到服务器上检索子节点。所以遍历一次后,如果父节点还是父节点(即存在子节点)则检索下面的子节点的内容,将子节点的id作为parentId来检索下面的节点。如果不是父节点了,则打开下面列表。也就是说这些实现都是 异步树自动实现的,我们只需要判断父节点的状态即可,下面的检索根据这个状态进行。
图片上传功能:因为商城的图片非常多,所以我们将这么多的图片保存在图片服务器中,然后将图片在服务器中的具体url写入数据库,供前台调用。前台获取到这个url既可获取到这个图片。这里图片上传到服务器的功能:先生成图片的名称,然后生成图片保存的格式,然后利用ftpUtil将图片上传到服务器,返回一个url链接。
(2)前台功能实现
首页大广告位的实现:这里是从数据库中获取广告位的图片,然后展示在页面。但是前台跟后台是不一样的端口,如何从前台访问后台呢,可以使用jsonp的形式。但是我们这里系统是采用面向服务的编程,所以采用rest风格调用后台接口,这里用的dubbo+zookeeper来调用接口。
(3)SSO单点登录系统:
这里是利用了sso的接口文档,即校验接口、注册、登录接口、根据token查询用户接口、安全退出接口。
这个的调用服务层是利用jsonp的形式访问的服务接口,实现跨域访问。客户端全部在jsp页面实现的。
具体流程:
当用户点击注册的时候,跳转到注册页面,即用户信息的保存功能。检验用户名是否存在、手机号和邮箱不能为空。
当用户点击登录按钮的时候,用户输入用户名和密码,检验用户名是否在数据库中存在,然后用户名密码是否正确。这里的密码是用了spring的MD5加密技术。当全部成功后,给用户颁发一个token令牌(利用uuid实现),然后将token存入到redis中(token的key是它生成的号,值是用户的名字),然后设置在redis的过期时间。这相当于用户的session。
然后将token写入cookie中,前台页面利用jsonp调用,根据cookie中的token的值,调用sso的根据token查询用户的服务,查看用户是否有效,如果有效则将用户返回前台页面,前台页面获取用户的用户名显示在首页,表示***已登陆。
这里的cookie是设置了共享域,即全部子系统都可以访问到cookie。
当用户登录其他子系统时,先从从cookie中获取token信息,根据token信息获取用户信息,判断用户信息是否有效,如果有效则放行,如果无效,则利用拦截器拦截跳转到登录页面。用户再次登录的时候刷新redis的时间,重新设置有效期。
(4)购物车功能:
将商品加入到购物车,当用户没有登录的时候,也可以将商品加入到购物车,是将商品信息加入到客户端浏览器的cookie当中,当用户点击加入购物车按钮的时候,会向后台提交一个请求把商品的ID和要加入的数量传递过去,首先获取到cookie当中购物车商品的信息,判断是否有商品,如果有,在根据商品ID和前台传入的商品ID进行比较,看是否有同一商品,如果有则直接在原有的数量少加上传递的数量即可,如果没有,则设置商品数量并将商品加入到list集合当中,然后把list集合转化为json数据放入cookie当中,并设置cookie的有效时间,
cookie数据是存在客户端浏览器上,cookie也可以存放一些信息,用到的时候直接从cookie当中取,可以减轻服务器的压力。
使用cookie的好处:1、实现简单 ,2、不需要占用服务端存储空间。
缺点:1、存储容量有限, 2、更换设备购车信息不能同步 3、Cookie禁用,不提供保存。
项目采用的是maven的多模块构建,各个模块之间调用就需要用到中间件,我们采用的是dubbo+zookeeper作为中间件,Dubbo是alibaba开源的分布式服务框架,它最大的优点可以使各层之间解耦,提高项目的拓展性,dubbo中有:Provider: 暴露服务的服务提供方。Consumer: 调用远程服务的服务消费方。Registry: 服务注册与发现的注册中心。Monitor: 统计服务的调用次数和调用时间的监控中心。Container: 服务运行容器。服务容器负责启动,加载,运行服务提供者,服务提供者在启动时,向注册中心注册自己提供的服务,注册中心采用的是zookeeper,需要在配置文件中配置服务,分别有服务注册者名称,服务提供者的地址,暴露的端口号,以及提供服务的接口和实现类,服务消费者在启动时,向注册中心订阅自己所需的服务,注册中心返回服务提供者地址列表给消费者,服务消费者根据地址列表找到对应的服务提供者完成相应的调用。
当用户登录账号之后,会将cookie当中购物车中的商品同步到该账号中,把cookie当中的商品信息传入到后台,与原有的购物车中商品信息进行比对,有相同的商品的话直接在原有的数量上加上cookie中该商品的数量,如果没有则直接加入,购物车中的信息可以存放在数据库中也可以放在redis缓存中,这里采用了redis缓存,因为用户可能会频繁的更新购物车信息,如果将购物车商品数据放在数据库中的话会增加数据库的压力,所以采用了redis缓存,redis是一个高性能的key/value分布式内存数据库,基于内存运行,还支持数据的持久化,redis不仅仅支持简单的key/value类型的数据,同时还提供了String、list、set、zset、hash等数据结构的存储,还支持数据的备份,主从同步等。
redis提供了两种持久化方式,一种是rdb,一种是aof:RDB方式是一种快照式的持久化方法,将某一时刻的数据持久化到磁盘中redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。对于RDB方式,redis会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行任何IO操作的,这样就确保了redis极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。。aof:AOF方式是将执行过的写指令记录下来,在数据恢复时按照丛前到后的顺序再将指令执行一遍。AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.默认的AOF持久化策略是每秒钟fsync一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,redis仍然可以保持很好的处理性能,即使redis故障,也只会丢失最近1秒钟的数据。如果在追加日志时,恰好遇到磁盘空间满、inode满或断电等情况导致日志写入不完整,也没有关系,redis提供了redis-check-aof工具,可以用来进行日志修复
rdb优点:1.RDB是一个单一的紧凑文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.2.RDB是一个紧凑的单一文件,方便传送,适用于灾难恢复.3.RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.4.与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
缺点:1.Redis意外宕机,可能会丢失几分钟的数据(取决于配置的save时间点)。RDB方式需要保存整个数据集,是一个比较繁重的工作,通常需要设置5分钟或者更久做一次完整的保存。2.RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续更久。
aof优点:1.使用AOF 会让Redis数据更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.2.AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.3.Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。4.AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析也很轻松
缺点:1.对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。2.根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间。
aof同步策略有三种,分别为always everysec no 重写机制相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢与rdb;Aof运行效率要慢与rdb,每秒同步策略效率较好,
在项目当中用jedis链接redis,配置IP和端口号,通过redis命令来操作完成相应的功能。
(5)订单模块:
订单的创建需要用户登录,这里用到了拦截器在springMVC中配置下拦截方式即可。
去购物车结算,判断是否登陆,使用拦截器拦截,实现HandlerInterceptor,从cookie中获取token,如果没有token,跳转到登陆页面,并拼接url传递到登陆页面,如果有token,通过token查询redis中有没有用户信息,如果没有,或过期,都返回登陆页面,否则,则登陆跳转到订单页面
1)订单创建逻辑:
当点击去购物车结算时,显示购物车的列表,当选中购物车的商品点击去结算的时候,显示商品的提交订单之前的一系列信息(也就是结算页):针对数据库三张表:订单基本信息表、订单明细表(购买的商品信息)、订单配送(收货人的地址电话信息)
传入参数:因为创建订单也就是向数据库中插入一系列的信息,而对应的是数据库中的三个表,所以根据页面的内容,传入的参数也就是三个pojo类,然后页面填写的+补全页面上在数据库中没有的字段。所以主要是对数据库中的三个表进行插入操作。服务接口是负责接收这三个pojo类,所以客户端要想办法将这三个pojo类传递过来。
根据接口文档,返回的是一个json格式的数据,即这三张表的数据是在一个json串中,所以这里要想办法将这三个表单独建立一个pojo来保存这个返回值。这样就将三个表放到了一个pojo类中
接下来就是数据的插入操作了,这个在service层实现:逐个表的插入数据库即可,然后返回一个订单号即订单的id。
controller层传递的就是这个pojo类,然后返回给客户端。
客户端也是将这个pojo类传递给服务接口,返回一个订单号给客户端。提交订单的时候显示订单提交成功页面时候,看下jsp页面显示哪些字段,然后用ModelMap传递给页面
2)拦截器配置使用:
mvc:interceptors
mvc:interceptor
<mvc:mapping path="/order/**"/>
去购物车结算,判断是否登陆,使用拦截器拦截,实现HandlerInterceptor,从cookie中获取token,如果没有token,跳转到登陆页面,并拼接url传递到登陆页面,如果有token,通过token查询用户信息,如果未登陆,或过期,都返回登陆页面,否则,则登陆跳转到订单页面 (6)秒杀系统 因为秒杀活动只是我们网站营销的一个附加活动,这个活动具有短时间、高并发的特点,如果和原有的网站部署在一起的话,必然会对现有的业务造成冲击,稍有不慎有可能会导致整个网站崩溃,所以我们会将这个模块独立部署。用户在秒杀开始前,为了保证不错过秒杀的机会,会不停的刷新浏览器页面,这样会不停的访问应用服务器、和数据库,从而对服务器和数据库造成一定的压力,所以我们不使用原来商品的详情页面,重新设计了秒杀商品的页面,并将页面静态化,这样用户的请求就不会经过应用服务。我们还需要租赁服务器宽带,然后再秒杀活动开始之前,用户只能浏览秒杀的商品不能购买,我们可以将购买按钮设置成灰色,无法点击,为了避免用户直接访问下单页面,我们可以在下单页面URL前加入由服务端生成的随机数作为参数,只有在秒杀活动开始时才会生成,这样即使是秒杀系统的开发者也无法在秒杀活动开始前访问下单页面。然后利用springMVC定时器来控制秒杀时间. (7)商品信息搜索框(solr): 我当时做商品信息查询搜索框的时候,因为我们是电商项目考虑到商品的数据量比较大,普通的搜索查询需要到数据库进行查询,加大了数据库的压力,所以我采用的是solr搜索引擎,solr是一个基于Lucene的全文搜索服务器,相比Lucene更高效、使用更便捷,在进行模糊匹配的时候,他可以 用来替代数据库中的like ,从而在匹配准确性以及性能进行大幅度的提高。在建立索引的时候我们通过在schema.xml配置IK分词器来完成中文分词。 从而实现了高亮显示关键词,分页,排序,多字段,多条件的高性能搜索。在从数据中取数据生成索引的时候,因为表中的数据量比较大,防止一次取出所导致内存溢出问题,我采用了分段批量提取的方式进行,除此之外我们对后续增加的数据根据优先级的不同采取不同的策略,对于那些需要及时显示的数据我们通过spring定时器 在短时间内(30分钟)进行增量索引的生成,对于那些不需要及时展示的数据,我们通过spring定时器在服务器相对空闲的时候(比如每天晚上凌晨)进行索引的重新生成。 此外我们为了提高solr搜索的性能对其进行了主从配置。 被动说: 1.我们solr使用的是solr4.7版本 2.通过修改schema.xml来添加要进行索引的字段以及增加ik分词器 3.通过solrj将数据库中的数据生成solr中的索引文件,注:solrj是java程序调用solr服务所用的jar包。 4.通过在solrconfig.xml中配置requestHandler name=“/Replication”来进行主从同步的配置,在从solr中通过masterUrl指明要从哪些主solr服务器中同步数据 (8)留言评论 评论这一块其实也挺重要的,他主要是指的顾客在网站上购买过该产品后,对该产品撰写的产品评论,主要内容其实就是购买过程和使用过程的体现,还有产品本身的评价,还有物流速度,服务态度等。其实整个电商平台很多模块主要是围绕着营销来运营的,好多用户现在就是买商品的同时,先会看一下商品评论。 商品评论这一块主要涉及到的内容有,属性集,产品和属性集关联,产品评论,另外就是和产品、产品sku关联,评论属性评分,产品评论和客户,评论回复,产品统计;另外还有就是标签(或称为话题),附件,匿名评论。 因为订单交易完成后需要评论,考虑到评论不断增加,后期评论数据比较大,所以评论这块我们采用了mongodb数据库,之所以采用mongodb是因为:MongoDB是NoSQL的非关系型数据库,易于扩展,可以进行分布式文件存储,适用于大数据量、高并发、弱事务的互联网应用,因此我在项目中使用它来存储电商产品详情页的评论信息(评论id,商品id,标题,评分,内容,评论人信息,评论的发布时间,评论标签组)并且为了提高可用性和高并发用了3台服务器做了mongodb的副本集,其中一台作为主节点,另外两台作为副本节点,这样在任何一台mongodb服务器宕机时就会自动进行故障转移,不会影响应用程序对mongodb的操作,为了减轻主节点的读写压力过大的问题,我还对mongodb副本集做了读写分离,使写操作在主节点进行,读取操作在副本节点进行。为了控制留言,我们留言的界面设置在了订单状态,只有状态为5,也就是交易成功收货后才能评论,并在评论成功后将订单状态改为6。 【项目二】OA办公系统 项目说明 :hroms人力资源外包管理系统 技术选型: 核心框架:Spring Boot 安全框架:Apache Shiro 1.3 视图框架:Spring MVC 4.3 持久层框架:MyBatis 3.3 数据库连接池:Druid 1.0 日志管理:SLF4J 1.7、Log4j 页面交互:Vue2.x 1:Shiro Shiro简介 apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。 主要功能 三个核心组件:Subject, SecurityManager 和 Realms. Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。 SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。 Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。 从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。 Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。 在项目中使用 1:导入坐标 shiro-core shiro-web shiro-spring三个jar包 2:在web.xml文件中添加shiroFilter shiro过滤器,DelegatingFilterProxy会从spring容器中找shiroFilter filter名字叫shiroFilter,拦截所有路径 3:自定义realm类 (1)继承 AuthorizingRealm (2)重写三个方法 getName() 获取当前realm的名 doGetAuthorizationInfo(PrincipalCollection principals) 授权 doGetAuthenticationInfo(AuthenticationToken token) 认证 4:创建 applicationContext-shiro.xml 配置文件 1)在spring中注入自定义的realm 2)在spring中注入securityManager 在securityManager中通过property引入自定义的realm类 3)在spring中注入定义的ShiroFilter id必须和web.xml中定义的 shiroFilter 一致 在ShiroFilter中通过property引入securityManager 定义登录方法的访问路径 定义没有授权的方法跳转的路径,通常是提示用户没有权限访问 定义拦截的规则 anon:匿名拦截器,即不需要登录即可访问;一般用于静态资源过滤; authc:表示需要认证(登录)才能使用; /** = authc表示所有的请求都会被shiroFilter拦截认证 logout:退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout” 5:在自定义realm中添加认证 1)从token中获取到用户名 2)通过用户名去数据库中查询对象 3)如果不存在则返回null 4)如果存在,则将信息存放在SimpleAuthenticationInfo(当前对象、查询的密码、当前realm的名) ,然后将info返回; 6:登录失败的异常信息 1>UnknownAccountException:代表账户不存在 2>IncorrectCredentialsException:代表密码错误 7:登出 logout:退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout” 8:授权 分析三种方式 1)编程式,缺点:必须进入请求方法中才能判断是否有权限,放弃 2)jsp标签方式, 缺点:虽然在页面上没有显式请求按钮,但是可以通过浏览器地址栏中输入请求访问, 放弃 3)注解方式:优点,可以在请求进入方法之前进行权限控制。 推荐 jsp标签+注解结合使用 jsp标签 首先tglib定义shiro的标签 登录之后 不在登录状态时 用户在没有RememberMe时 用户在RememberMe时 在有abc或者123角色时 拥有角色abc 没有角色abc 拥有权限资源abc 没有abc权限资源 显示用户身份名称 显示用户身份中的属性值 查询sql (1)通过用户id查询角色的sql select sn from role where id in (select role_id from user_role where user_id = #{id}) (2)通过用户id查询权限的sql select resource from permission where id in ( select permission_id from role_permission where role_id in( select id from role where id in ( select role_id from user_role where user_id = #{id} ))) MyRealm中的授权 获取当前对象getPrimaryPrincipal() 通过用户查询相对应的权限、角色 将权限和角色放入SimpleAuthorizationInfo中 9:缓存 授权完毕之后,每次访问都会调用授权的方法,查询数据库,我们可以将权限存放在缓存中,授权一次之后,再次查询就不会再次进入授权。 1)导入jar包 ehcache-core shiro-ehcache 2)配置缓存管理器 引入了shiro-ehcache.xml 3)securityManager中添加缓存管理器 4)添加 shiro-ehcache.xml 缓存的配置 清空缓存: 如果用户正常退出,缓存自动清空。 如果用户非正常退出,缓存自动清空。 如果修改了用户的权限,而用户不退出系统,修改的权限无法立即生效。 当用户权限修改后,用户再次登陆shiro会自动调用realm从数据库获取权限数据,如果在修改权限后想立即清除缓存则可以调用realm的 clearCache 方法清除缓存。 10:加密 1:先修改数据库中的密码为密文 使用md5加密,加上盐值,还有加密的次数,防止暴力破解 2:在配置文件中添加加密器 3:在自定义realm的bean中引入加密器 4:认证方法中添加盐值 11:shiro框架与springboot整合 1.Pom.xml中导入shiro-spring依赖。 2.在Application能扫描到的包下创建一个配置类(@Configuration),在该类中分别声明1.(@Bean)ShiroFilterFactoryBean(shiro过滤器工厂, filterChainDefinitionMap.put来写入需要被拦截的路径(key)及访问所需权限(value). 配置不被拦截的路径(util/**,anon), 登录路径shiroFilterFactoryBean.setLoginUrl(/login), 登录成功后跳转路径shiroFilterFactoryBean.setSuccessUrl(/index)等等 ), myShiroRealm(自定义的Realm类) hashedCredentialsMatcher凭证匹配器(散列方法,次数) securityManager(安全管理器) 开启shiro aop注解支持。 3.自定义myShiroRealm类。与Spring整合的写法一致,继承AuthorizingRealm抽象类,重载doGetAuthenticationInfo(),重写获取用户信息的方法(用token的username信息到数据库取出User对象,拿该对象的username,userpwd,solt,及该realm的name进行认证)以及获取用户权限的方法(将用户保存在数据库中的角色信息及权限信息加到用户信息中)。 【项目三】P2P网贷 我最近做了一个P2P网贷的项目。这个项目主要目的是针对个体(个人、企业或组织)和个体之间通过互联网平台实现的直接借贷。整个项目分为前台系统(用户访问平台)与后台管理系统两个项目。 前台项目主要涉及的模块:是债券模块(展示债券以及用户购买时生成订单)、出借模块、借款模块、推广模块、信息披露模块、用户管理模块(登录注册、个人中心)。判断如果为新用户还涉及到一个新手引导流程。 后台系统的模块:则分为用户管理模块,业务管理模块(债券的发布、上下架及调整、合同的POI导出),推广管理模块、统计管理模块(HighCharts报表完成用户登录及注册次数的统计、每日购买量的统计、资金统计等等)基本设置(前台信息披露模块中展示的公司基本信息)、财务管理(主要涉及到用户充值管理,线下充值,提现管理,用户信用管理,用户担保管理,不良债权转让管理,商城的退款管理,平台调账管理)等等。 我在项目中主要负责的是前台的债券模块、出借模块、借款模块、业务管理、财务管理模块。 2.1债券模块: 首先是将后台上架的债权信息展示给前台,购买流程为当用户点击购买某个债权时首先判断债券剩余的数量是否足够,如果足够则生成订单(此时订单状态为0未付款)并在库存中减去相应的数量,该订单如果在15分钟内未完成付款操作,则自动取消。生成订单后根据用户录入的银行卡信息调出相应的银行接口让用户进行付款(这里也可以添加新的银行卡)。用户这边付款后再通过银行接口返回的流水号查询是否付款成功。付款成功则将订单状态修改为1已付款,购买成功并通知用户,同时通知后台客服对订单做出处理。 如果两个用户同时购买了100份库存只有100的债权? 如果两个用户同时购买了100份库存只有100的债权。则只会有一个用户购买成功。因为此处使用RabbitMQ消息队列的原因。消息队列是根据日志信息从左到右执行的。所以即使是同时发出了生成订单的请求,在执行完左侧生成的订单消息之后,因为数据库中库存已经不够了,所以第二个订单生成是不会成功的。 业务管理模块中主要涉及的有债券管理,催收管理,合同管理,借款管理。 2.2 债券管理: 比如债券的发布、上下架及调整,当债权信息有了更新以后。在业务逻辑层直接调用前台项目中重新生成静态化页面(freemarker)的方法将之前的债券展示信息替换掉。替换成功后才会提交事务,避免前台展示的数据与后台数据库中的数据出现偏差。 催收管理模块:主要是根据用户还款的时间来及时给用户提醒。通过定时器来每天进行一次判断。比如说在距离还款还有一周的时候,调用短信接口(httpclient)来给用户发送提示短信进行通知,在还款当天再次提醒用户逾期将会产生违约金等。在逾期三天之后会提醒客服对客户进行催收以及对催收情况的统计。逾期一个月以上的用户可添加至黑名单。 订单生成后会自动添加到合同列表中。在合同管理中可以进行详情查看以及直接将合同导出为Word文档进行打印。 借款管理:首先用户选择相应的借款类型,在用户发出了借款申请后。首先是由审核部门对该用户信用级别(黑名单中的用户无法发出申请/信用等级越高的用户可申请的额度就越高,同时也根据抵押物来判断申请借款的金额)以及抵押物的一个审核。(此时默认状态为审核中),在审核通过后状态变更为已审核未发布,此时业务部门可以进行该借款的发布。发布以后前台用户就可以看到该信息并且借贷给该用户。当金额足够以后将状态变更为“已满标”。同时由财务部门将钱打给申请借款的用户。 2.3 财务管理: 我在这个模块中主要负责充值管理,线下充值,提现管理这几个模块。 充值管理与线下充值管理:主要是对用户充值到此平台上的金额的一个记录的展示。考虑到安全问题,在该平台中只能对它进行查询而不能进行更改操作。且在该用户余额进行购买债券或借出操作时会有一个审核。 提现管理:用户在前台系统发出提现申请后,该条信息就会在提现管理中展示出来(状态为:申请提现),首先由业务部门核实后更改状态为(已审核,未打款),然后由财务部门进行打款。将状态更改为已提现。 后台管理系统包括:会员管理,业务管理,系统管理,财务管理,统计管理,推广管理等主要模块 2.4会员管理: 是对会员信息统计和管理(包括个人信息,企业信息,机构信息),会员的认证管理,留言管理等。 会员认证管理:通过该功能新注册用户可以通过必要的用户认证后获得非0的借款信用额度而拥有有效的借款申请权限,在通过非必须、额外的用户认证来更进一步提高用户的借款信用额度,使用户可以在同一时间取得更大额度的借款。 必要的用户认证:主要包括:身份证认证,工作认证,收入认证,芝麻信用报告认证等。 额外的用户认证:主要包括:学历认证,房产认证,技术职称认证,购车证明等。 留言管理:主要是针对会员在“帮助中心”的留言,及时进行恢复。 2.5 业务管理: 是我们网贷的核心模块,主要有理财管理,借款管理,催收管理,合同管理等 2.6 理财管理: 有在线债券的管理和线上债券的转让管理。 2.7 借款管理: 有借款管理、个人借款意向管理和企业借款意向管理。借款管理中主要是负责对借款申请的审批(主要负责审查用户的借款类型和抵押物以及其他申请是否合理),并负责在前台展示借款信息的页面进行招标。招收到的资金已满的话,后台进行审核后,做放款处理。 2.8 催收管理: 代还款列表,催收记录,黑名单。 代还款列表展示的是借贷用户的信息,便于后台人员的统计和催收的通知,催收的实现使用的是定时器+Webservice来实现的,正常还款的用户通过使用定时器,在还款期限前三天通过调用Webservice短信接口,发送短信给用户,提醒用户还款。对于逾期3—7天用户,通过定时器实现线上的催收(发送短信,还款期限已逾期),对于逾期7天以上的用户,通过定时器通知后台管理人员,通过Poi技术导出相对应的逾期用户信息,通过线下催款的方式催收贷款。对于严重逾期的用户,线下催收的同时加入黑名单,不在提供服务给该用户。 2.9 系统管理: 主要有后台账号,系统日志,业务推广等,需要使用shiro权限框架. 后台账号主要分为业务员账号管理,管理员账号管理,用户账号管理等,在这模块中要实现登录用户的权限限制。 因为涉及到资金的安全,所以我们做了日志记录的统计,所有增删改的操作都要生成相应的日志,做一个日志的统计,方便责任到人。 业务推广板块主要是对一些活动的推广,发送邮件和站内推广信给用户。 2.10 财务管理: 主要有资金管理,资金明细等。 资金管理中包括:充值管理,线下充值管理,提现管理,放款管理,用户信用管理,用户担保管理等 资金的明细主要是对平台资金的流向做相应的统计,通过Poi导出到做线下的会议使用。 2.11 统计管理: 主要有用户统计,资金统计,业务统计,统计报表等(使用highcharts技术),主要用于业务的推广方式。 用户统计:主要是针对用户注册的方式的统计,方便后期的业务推广。 资金统计:是看平台的资金的流动情况和盈亏情况。 业务统计:平台业务情况的查看,以及业务后期的推广重心。 2.12 推广管理: 推广奖励,奖励金管理,活动管理等。你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法1 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G
合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。
如何改变文本的样式
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
插入链接与图片
链接: link.
图片:
带尺寸的图片:
居中的图片:
居中并且带尺寸的图片:
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
如何插入一段漂亮的代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
var foo = 'bar';
生成一个适合你的列表
- 项目
- 项目
- 项目
- 项目
- 项目1
- 项目2
- 项目3
- 计划任务
- 完成任务
创建一个表格
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
设定内容居中、居左、居右
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' | ‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" | “Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash | – is en-dash, — is em-dash |
创建一个自定义列表
-
Markdown
- Text-to- HTML conversion tool Authors
- John
- Luke
如何创建一个注脚
一个具有注脚的文本。2
注释也是必不可少的
Markdown将文本转换为 HTML。
KaTeX数学公式
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
新的甘特图功能,丰富你的文章
- 关于 甘特图 语法,参考 这儿,
UML 图表
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::
这将产生一个流程图。:
- 关于 Mermaid 语法,参考 这儿,
FLowchart流程图
我们依旧会支持flowchart的流程图:
- 关于 Flowchart流程图 语法,参考 这儿.
导出与导入
导出
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
导入
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎