首页 文章 精选 留言 我的

精选列表

搜索[Spring Framework],共10000篇文章
优秀的个人博客,低调大师

Sa-plus v1.26.0 更新,基于 Spring Boot 的快速开发框架

项目介绍 Sa-plus 是一个基于 SpringBoot 架构的快速开发框架,内置代码生成器。 框架集成 JavaWeb 开发常见功能:文件上传、角色授权、全局异常处理、redis 控制台、API 日志统计、全局配置、跨域处理等等,让你不再为项目的基础设施劳神费心! 内置代码生成器,高自动化代码生成:普通 input、多行文本域、富文本、枚举按钮、日期控件、图片上传、音频上传、视频上传、 多图上传、树形表格、聚合外键...... 你只需写上简单的表注释,即可直接生成:Java 代码、后台管理页面、接口文档等,使项目中80%的代码做到自动化,省时省力 代码清晰明了,方便二次修改,另可自定义代码生成模板,根据自己的代码风格灵活扩展 更新日志 本次更新版本 v1.26.0 主要包括以下内容: 优化:优化前端样式,删除不必要的size="mini"配置 修复:修复部分页面表单校验抛出异常未能处理的情况 重构:重构代码生成器,更简洁的代码结构 升级:升级表单封装,增加日期、时间、slot等多种适配 升级:部分依赖升级至最新版本 更换:更换logo 升级:升级在线演示版本 项目地址:https://gitee.com/click33/sa-plus 截图预览 更多信息详见官网文档

优秀的个人博客,低调大师

Spring Boot 无侵入式 实现RESTful API接口统一JSON格式返回

前言 现在我们做项目基本上中大型项目都是选择前后端分离,前后端分离已经成了一个趋势了,所以总这样·我们就要和前端约定统一的api 接口返回json 格式, 这样我们需要封装一个统一通用全局 模版api返回格式,下次再写项目时候直接拿来用就可以了 约定JSON格式 一般我们和前端约定json格式是这样的 { "code": 200, "message": "成功", "data": { } } code: 返回状态码 message: 返回信息的描述 data: 返回值 封装java bean 定义状态枚举 package cn.soboys.core.ret; import lombok.Data; import lombok.Getter; /** * @author kenx * @version 1.0 * @date 2021/6/17 15:35 * 响应码枚举,对应HTTP状态码 */ @Getter public enum ResultCode { SUCCESS(200, "成功"),//成功 //FAIL(400, "失败"),//失败 BAD_REQUEST(400, "Bad Request"), UNAUTHORIZED(401, "认证失败"),//未认证 NOT_FOUND(404, "接口不存在"),//接口不存在 INTERNAL_SERVER_ERROR(500, "系统繁忙"),//服务器内部错误 METHOD_NOT_ALLOWED(405,"方法不被允许"), /*参数错误:1001-1999*/ PARAMS_IS_INVALID(1001, "参数无效"), PARAMS_IS_BLANK(1002, "参数为空"); /*用户错误2001-2999*/ private Integer code; private String message; ResultCode(int code, String message) { this.code = code; this.message = message; } } 定义返回状态码,和信息一一对应,我们可以约定xxx~xxx 为什么错误码,防止后期错误码重复,使用混乱不清楚, 定义返回体结果体 package cn.soboys.core.ret; import lombok.Data; import java.io.Serializable; /** * @author kenx * @version 1.0 * @date 2021/6/17 15:47 * 统一API响应结果格式封装 */ @Data public class Result<T> implements Serializable { private static final long serialVersionUID = 6308315887056661996L; private Integer code; private String message; private T data; public Result setResult(ResultCode resultCode) { this.code = resultCode.getCode(); this.message = resultCode.getMessage(); return this; } public Result setResult(ResultCode resultCode,T data) { this.code = resultCode.getCode(); this.message = resultCode.getMessage(); this.setData(data); return this; } } code,和message都从定义的状态枚举中获取 这里有两个需要注意地方我的数据类型T data返回的是泛型类型而不是object类型而且我的结果累实现了Serializable接口 我看到网上有很多返回object,最后返回泛型因为泛型效率要高于object,object需要强制类型转换,还有最后实现了Serializable接口因为通过流bytes传输方式web传输,速率更块 定义返回结果方法 一般业务返回要么是 success成功,要么就是failure失败,所以我们需要单独定义两个返回实体对象方法, package cn.soboys.core.ret; /** * @author kenx * @version 1.0 * @date 2021/6/17 16:30 * 响应结果返回封装 */ public class ResultResponse { private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS"; // 只返回状态 public static Result success() { return new Result() .setResult(ResultCode.SUCCESS); } // 成功返回数据 public static Result success(Object data) { return new Result() .setResult(ResultCode.SUCCESS, data); } // 失败 public static Result failure(ResultCode resultCode) { return new Result() .setResult(resultCode); } // 失败 public static Result failure(ResultCode resultCode, Object data) { return new Result() .setResult(resultCode, data); } } 注意这里我定义的是静态工具方法,因为使用构造方法进行创建对象调用太麻烦了, 我们使用静态方法来就直接类调用很方便 这样我们就可以在controller中很方便返回统一api格式了 package cn.soboys.mallapi.controller; import cn.soboys.core.ret.Result; import cn.soboys.core.ret.ResultResponse; import cn.soboys.mallapi.bean.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author kenx * @version 1.0 * @date 2021/7/2 20:28 */ @RestController //默认全部返回json @RequestMapping("/user") public class UserController { @GetMapping("/list") public Result getUserInfo(){ User u=new User(); u.setUserId("21"); u.setUsername("kenx"); u.setPassword("224r2"); return ResultResponse.success(u); } } 返回结果符合我们预期json格式 但是这个代码还可以优化,不够完善,比如,每次controller中所有的方法的返回必须都是要Result类型,我们想返回其他类型格式怎么半,还有就是不够语义化,其他开发人员看你方法根本就不知道具体返回什么信息 如果改成这个样子就完美了如 @GetMapping("/list") public User getUserInfo() { User u = new User(); u.setUserId("21"); u.setUsername("kenx"); u.setPassword("224r2"); return u; } 其他开发人员一看就知道具体是返回什么数据。但这个格式要怎么去统一出来? 其实我们可以这么去优化,通过SpringBoot提供的ResponseBodyAdvice进行统一响应处理 自定义注解@ResponseResult来拦截有此controller注解类的代表需要统一返回json格式,没有就安照原来返回 package cn.soboys.core.ret; import java.lang.annotation.*; /** * @author kenx * @version 1.0 * @date 2021/6/17 16:43 * 统一包装接口返回的值 Result */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ResponseResult { } 定义请求拦截器通过反射获取到有此注解的HandlerMethod设置包装拦截标志 package cn.soboys.core.ret; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; /** * @author kenx * @version 1.0 * @date 2021/6/17 17:10 * 请求拦截 */ public class ResponseResultInterceptor implements HandlerInterceptor { //标记名称 public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //请求方法 if (handler instanceof HandlerMethod) { final HandlerMethod handlerMethod = (HandlerMethod) handler; final Class<?> clazz = handlerMethod.getBeanType(); final Method method = handlerMethod.getMethod(); //判断是否在对象上加了注解 if (clazz.isAnnotationPresent(ResponseResult.class)) { //设置此请求返回体需要包装,往下传递,在ResponseBodyAdvice接口进行判断 request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class)); //方法体上是否有注解 } else if (method.isAnnotationPresent(ResponseResult.class)) { //设置此请求返回体需要包装,往下传递,在ResponseBodyAdvice接口进行判断 request.setAttribute(RESPONSE_RESULT_ANN, clazz.getAnnotation(ResponseResult.class)); } } return true; } } 实现ResponseBodyAdvice<Object> 接口自定义json返回解析器根据包装拦截标志判断是否需要自定义返回类型返回类型 package cn.soboys.core.ret; import cn.soboys.core.utils.HttpContextUtil; import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import javax.servlet.http.HttpServletRequest; /** * @author kenx * @version 1.0 * @date 2021/6/17 16:47 * 全局统一响应返回体处理 */ @Slf4j @ControllerAdvice public class ResponseResultHandler implements ResponseBodyAdvice<Object> { public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN"; /** * @param methodParameter * @param aClass * @return 此处如果返回false , 则不执行当前Advice的业务 * 是否请求包含了包装注解 标记,没有直接返回不需要重写返回体, */ @Override public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { HttpServletRequest request = HttpContextUtil.getRequest(); //判断请求是否有包装标志 ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN); return responseResultAnn == null ? false : true; } /** * @param body * @param methodParameter * @param mediaType * @param aClass * @param serverHttpRequest * @param serverHttpResponse * @return 处理响应的具体业务方法 */ @Override public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { if (body instanceof Result) { return body; } else if (body instanceof String) { return JSON.toJSONString(ResultResponse.success(body)); } else { return ResultResponse.success(body); } } } 注意这里string类型返回要单独json序列化返回一下,不然会报转换异常 这样我们就可以在controler中返回任意类型,了不用每次都必须返回 Result 如 package cn.soboys.mallapi.controller; import cn.soboys.core.ret.ResponseResult; import cn.soboys.core.ret.Result; import cn.soboys.core.ret.ResultResponse; import cn.soboys.mallapi.bean.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author kenx * @version 1.0 * @date 2021/7/2 20:28 */ @RestController //默认全部返回json @RequestMapping("/user") @ResponseResult public class UserController { @GetMapping("/list") public User getUserInfo() { User u = new User(); u.setUserId("21"); u.setUsername("kenx"); u.setPassword("224r2"); return u; } @GetMapping("/test") public String test() { return "ok"; } @GetMapping("/test2") public Result test1(){ return ResultResponse.success(); } } 这里还有一个问题?正常情况返回成功的话是统一json 格式,但是返回失败,或者异常了,怎么统一返回错误json 格式,sprinboot有自己的错误格式? 请参考我上一篇,SpringBoot优雅的全局异常处理 扫码关注公众号猿人生了解更多好文

优秀的个人博客,低调大师

学 Java 必学 Spring,学 C# 离不开 Furion,v2.7.0 发布

让 .NET 开发更简单,更通用,更流行。 版本序言 经过上百次版本的迭代改进,Furion 日渐稳定完善,使用者也是指数增长,目前总增速保持在每天 15K 的下载量,QQ 交流群也超过 6400+ 人,每天的增速保持在30/天。 以后再有人问:“你们 C# 有什么拿得出手的框架不?“,可以自豪的回答:”Furion“。 本期亮点 1、框架启动内存占用由 136M 下降到了 86M,并提供了更精确的 GC 回收控制。 2、支持 EFCore 完整的 `SQL` 执行日志输出 3、`Scoped` 支持同步异步作用域写法 本期更新 新特性 [新增] 工作单元特性,支持静态类强制性开启共享事务#I3S9N8 [新增]EFCore执行sql模式打印日志#I3SE8X [新增] 远程请求支持默认HttpClient配置#I3SI17 突破性变化 [调整]Scoped.CreateUnitOfWork名称为Scoped.CreateUow#I3SJPU [调整]JWTEncryption.Validate返回值,支持返回TokenValidationResult#I3S2ND 问题修复 [修复]Scoped系列方法异步出现Task is cancel情况#I3SJF6 [修复]Mysql数据库的ToPagedList方法返回的结果进行遍历出现MySqlConnection is aleady use问题#I3SJQ3 [修复]tool/cli.psl没有包含项目名称#I3S1T6 其他更改 [优化]框架底层性能,大大减少内存占用和溢出情况,启动内存从之前136M下将到86M [调整] 更新部分列UpdateIncludeNowAsync具有二义性#I3RW9Q 文档变化 [更新] 4.2.9 的示例代码文档,方法没有放在 class 中#I3S9T5 问答答疑 [答疑] 默认MasterDbContextLocator不随自定义的参数生成#I3SDBB 不做实现 [废弃] 添加令牌桶限流算法#I3SCDV [废弃] 定时任务立即执行需求#I3SF4A 框架特点 全新面貌:基于.NET5/6平台,没有历史包袱 极易入门:只需要一个Inject()即可完成配置 极速开发:内置丰富的企业应用开发功能 极少依赖:框架只依赖两个第三方包 极其灵活:轻松面对多变复杂的需求 极易维护:采用独特的架构思想,只为长久维护设计 完整文档:提供完善的开发文档 功能模块图 文档概括图 贡献者画像 文档地址 国内文档:https://dotnetchina.gitee.io/furion 国外文档:https://furion.pro 项目地址 Gitee:https://gitee.com/dotnetchina/Furion GitHub:https://github.com/monksoul/Furion Docker:https://hub.docker.com/r/monksoul/furion Nuget:https://www.nuget.org/packages/Furion Furion遵循Apache-2.0开源协议,欢迎大家提交PR或Issue。喜欢可以给个Star。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册