迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:maple开源软件地址:https://gitee.com/blind/maple开源软件介绍:Maple J2EE快速开发框架(MyBatis)Hibernate版请前往:http://git.oschina.net/blind/app 项目简介
欢迎进群交流 点击加入QQ群631511782模块说明
技术选型
环境要求
使用说明1. 启动说明* 项目路径:http://localhost:8080/maple/admin/index* 后台帐号密码:admin 123456* 项目maple-api模块依赖Redis服务,请先安装Redis客户端,不需要api模块可不用。* 项目有2个war包模块,请使用不同的端口运行启动。 maple-admin:是后台管理界面 maple-api:是api模块,实现了基于jwt和redis的token认证。一般应用于前后端分离的项目,如Android、IOS等客户终端调用的接口都来源于此模块,使用token进行身份认证。 * 数据库: 运行前请先创建数据库,数据库名:maple 导入SQL文件(maple.sql)进行导入数据后启动项目。 * 环境配置/打包: maple-admin 和 maple-api 模块下都包含3套环境配置,不同的环境请自行修改里面的参数。 说明: dev - 开发环境 test - 测试环境 pro - 生成环境 使用maven打包时,可以选择不同的环境配置文件,配置文件在打包(war)时起作用,本地开发时只需要修改最外层的配置文件 2. 基于Redis的身份认证模块使用说明依赖maple-auth模块,也可将该模块可以单独打成jar包再引用 使用Redis存储Token,在需要集成身份认证的项目的spring-mvc.xml文件中配置: <!-- 加载配置文件数据 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath*:config/redis.properties</value> <value>classpath*:config/token.properties</value> </list> </property> <property name="ignoreUnresolvablePlaceholders" value="true"/> </bean><!--授权认证配置 begin--> <!--通过Key获得对应用户的bean--> <bean id="userRepository" class="io.zhijian.app.authorization.resolver.UserRepository"/> <mvc:annotation-driven> <mvc:argument-resolvers> <!--配置注入登录用户的解析器--> <bean id="currentUserMethodArgumentResolver" class="io.zhijian.authorization.resolvers.CurrentUserMethodArgumentResolver"> <!--需要解析的用户类--> <property name="userModelClass" value="io.zhijian.system.model.response.UserResponse"/> <!--查询用户的bean--> <property name="userModelRepository" ref="userRepository"/> </bean> </mvc:argument-resolvers> </mvc:annotation-driven> <mvc:interceptors> <!--身份验证的拦截器--> <bean id="authorizationInterceptor" class="io.zhijian.authorization.interceptor.AuthorizationInterceptor"> <!--验证信息存储的Http头--> <property name="httpHeaderName" value="Authorization"/> <!--验证信息通用前缀,例如Bearer--> <property name="httpHeaderPrefix" value=""/> <!--验证失败时的错误信息--> <property name="unauthorizedErrorMessage" value="invalid token"/> <!--管理验证信息的bean--> <property name="manager" ref="tokenManager"/> <!--token验证器--> <property name="validator" ref="tokenValidator"/> </bean> </mvc:interceptors> <!--管理验证信息的bean--> <bean id="tokenValidator" class="io.zhijian.app.authorization.jwt.JwtTokenValidator"></bean> <!--Redis配置--> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!--最大连接数--> <property name="maxTotal" value="${redis.maxTotal}" /> <!--最大空闲连接数--> <property name="maxIdle" value="${redis.maxIdle}" /> <!--初始化连接数--> <property name="minIdle" value="${redis.minIdle}"/> <!--最大等待时间--> <property name="maxWaitMillis" value="${redis.maxWaitMillis}" /> <!--对拿到的connection进行validateObject校验--> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> <!--在进行returnObject对返回的connection进行validateObject校验--> <property name="testOnReturn" value="${redis.testOnReturn}" /> <!--定时对线程池中空闲的链接进行validateObject校验--> <property name="testWhileIdle" value="true" /> </bean> <!--Redis连接池--> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg index="0" ref="jedisPoolConfig"/> <constructor-arg index="1" value="${redis.host}"/> <constructor-arg index="2" value="${redis.port}" type="int"/> <constructor-arg index="3" value="${redis.timeout}" type="int"/> <constructor-arg index="4" value="${redis.password}"/> </bean> <!--管理验证信息的bean--> <bean id="tokenManager" class="io.zhijian.authorization.manager.impl.RedisTokenManager"> <!--Redis客户端连接池配置--> <property name="jedisPool" ref="jedisPool"/> <!--Token失效时间--> <property name="tokenExpireSeconds" value="${token.expire.seconds}"/> <!--一个用户是否可以绑定多个Token--> <property name="singleTokenWithUser" value="${single.token.with.user}"/> <!--在每次有效操作后刷新过期时间--> <property name="flushExpireAfterOperation" value="${flush.expire.after.operation}"/> </bean> <!--授权认证配置 end--> 添加配置文件redis.properties和token.properties #redis配置redis.host = 192.168.1.200redis.port = 6379redis.timeout = 100000redis.password = xxxxxxredis.minIdle=100redis.maxIdle=300redis.maxTotal=600redis.maxWaitMillis=1000redis.testOnBorrow=trueredis.testOnReturn=true #Token配置#1分钟 = 60000 毫秒(ms)#1小时 = 3600000 毫秒(ms)#1天 = 86400000 毫秒(ms)#7天 = 604800000 毫秒(ms)#base64加密字符串jwt.base64.secret = MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=jwt.refresh.base64.secret = MHNkamZsYWpkZmppMjM0MDk4amtkc2E4dTIwMzg0bGFmYXNkZjQ1NndlcnUwOTIzdWxh#jwt token过期时间,毫秒jwt.expires.second = 60000#refresh token过期时间jwt.refresh.expires.second = 604800000########################################################是否在每次有效操作后刷新token在redis中的过期时间,是=true,否=falseflush.expire.after.operation = true#是否一个用户单对应唯一一个Token,是=true,否=false#说明:如果是同一帐号多端登录设置为falsesingle.token.with.user = false#redis token过期时间,秒token.expire.seconds = 3600 配置具体参考maple-api模块中,spring-mvc.xml的配置 使用如下:需要身份验证的方法加上@Authorization注解即可,也可以直接在Controller类上加上该注解,这将会使该Controller中的所有方法都需要进行身份验证。 @Authorization @RequestMapping(value = "/user/get", method = RequestMethod.GET) @ResponseBody public UserResponse get(@CurrentUser UserResponse user) { return userService.get(user.getUsername()); } @CurrentUser注解可以获取当前登录用户的实例,拥有@CurrentUser参数的方法,可以没有@Authorization注解,此时如果请求未登录,该参数会为null,但是如果想要使用CurrentUserMethodArgumentResolver则必须配置AuthorizationInterceptor。 当前用户的实例获取和解析,在上面的配置文件里面已经配置了解析器,但是需要自行实现UserModelRepository。 鉴权失败,会统一返回401 HTTP状态码,注意这里是http状态码,也可以在配置文件自定义鉴权失败的http状态码,默认为401(unauthorized)。 3. 通用日志模块依赖maple-log模块,也可将该模块可以单独打成jar包再引用 在spring-context.xml中添加配置 <!-- 激活自动代理功能 --><aop:aspectj-autoproxy proxy-target-class="true" /><!-- 扫描切面包路径 --><bean id="logAspect" class="io.zhijian.log.aop.LogAspect"> <property name="logPoint"> <bean class="io.zhijian.system.service.impl.SystemLogService" /> </property></bean><aop:config> <aop:aspect ref="logAspect"> <aop:pointcut id="logPointCut" expression="@annotation(io.zhijian.log.annotation.Log)" /> <aop:around pointcut-ref="logPointCut" method="save" /> </aop:aspect></aop:config> SystemLogService实现了LogPoint类中的save方法,在该方法中实现日志的存储 具体参考maple-system模块中SystemLogService.java 4. 集成了Mybatis-plusMybatis-plus的使用请参考:https://git.oschina.net/baomidou/mybatis-plus 5. 代码生成器的使用maple-generator模块,使用mybatis-plus的代码生成器使用请参考:https://git.oschina.net/baomidou/mybatis-plus 6. 统一异常处理、响应结果、状态码的约定
如下: { "body": { "username": "admin" }, "code": 200, "message": "ok", "now": "2017-04-06 15:42:20"} code = 状态码message = 信息,有错误或异常时即为错误信息(客户端不应该直接显示该message,而应该自己根据code的业务标识判断,返回友好的提示给用户)now = 服务器当前时间body = 实际响应内容,有错误或异常时为null
全局业务异常类:ApplicationException,包含状态码,错误信息 程序所有的异常都通过AnnotationHandlerMethodExceptionResolver 来统一拦截处理成统一的响应结果了 没有使用boolean类型的标识,boolean类型的标识会带来歧义,统一约定好的状态码或许更好。
除了Token验证失败返回了HTTP状态码外,其他的异常、错误、逻辑判断返回的状态码都是自定义的 在base模块中的StatusCode定义了一些常用的状态码,可以直接使用。 但其他业务模块的状态码不应该定义在base模块中,也就是说base模块是不负责处理业务各个不同的业务模块,需要自行按照StatusCode中的规格定义,如system模块中的SystemError 业务模块的状态码约定: /* 错误码格式说明(示例:202001),1为系统级错误,2为业务逻辑错误 -------------------------------------------------------------------- 服务级错误(1为系统级错误) 服务模块代码(即业务模块标识) 具体错误代码 2 02 001 -------------------------------------------------------------------- */ //2 00 001 释义: 00 = System 业务模块标识,001为具体的错误代码约定:00 = system模块01 =02 =03 =04 =.... 开发人员应该统一规范和标准,约定如何定义各模块的状态码标识 主要功能/界面展示
感谢@ScienJus项目基于Redis的认证模块修改和集成了此项目https://github.com/ScienJus/spring-authorization-manager @baomidou mybatis 增强工具包,简化 CRUD 操作https://git.oschina.net/baomidou/mybatis-plus Jquery EasyUI Insdep主题https://www.insdep.com 交流点击加入QQ群631511782交流技术问题 ![]() |
2022-08-15
2022-08-17
2023-10-27
2022-09-23
2022-08-13
请发表评论