首页 文章 精选 留言 我的

精选列表

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

🔥 SpringBoot 怎么办?Solon v2.8.4 实在太快了!

Solon 框架! Java “纯血国产”应用开发框架。开放原子开源基金会,孵化项目。从零开始构建(非 java-ee 架构),有灵活的接口规范与开放生态。 追求: 更快、更小、更简单 提倡: 克制、简洁、高效、开放、生态 有什么特点? 特点 描述 更高的计算性价比 并发高 2~ 3 倍;内存省 50% 更快的开发效率 内核小,入门快;启动可快到 10 倍 更好的生产与部署体验 打包最多缩小 90% 更大的兼容范围 非 java-ee 架构;同时支持 java8 ~ java22 入门探索视频(早期用户录制): 最近更新了什么? 新增 solon.net.httputils 插件 添加 BeanWarp::rawClz,优化 BeanWrapLifecycle 的检测方式(避免 LifecycleBean 重复注册) 添加 CloudBreakerException 异常类,用于 CloudBreakerInterceptor 添加 CloudStatusException 异常类,用于 Cloud 触发的 4xx 状态异常 添加 Router 移除控制器的接口 添加 openapi2 支持 action 返回接口类型 简化 Router 注册控制器的方式 优化 solon.boot.websocket 适配,在重启时端口不能立即复用的问题 优化 List[Bean] 注入,支持排序 优化 AppContext::beanShapeRegister 改为实例检测(之前为类型检测) 调整 429 状态改由 CloudBreakerException 发出(访问量过大时) 调整 415 状态改由 StatusException 发出(Consumes 不匹配) 调整 用 solon.net.httputils 替换 solon.test 里的 HttpUtils(统一代码) 调整@Consumes@Produces作用域,支持加在类上 调整 solon-rpc 快捷包去掉 hessian 依赖(如有需要手动引入) 调整 CloudBreakerInterceptor 融断时改为 CloudBreakerException(之前为直接设定 429 状态),更方便过滤和拦截 修复@Consumes@Produces在 solon.docs 里无效的问题 fury 升为 0.5.1 liteflow 升为 2.12.1 socket.d 升为 2.5.7 folkmq 升为 1.7.2 smartsocket 升为 1.5.44 smarthttp 升为 1.4.3 undertow 升为 2.2.32.Final 项目仓库地址? gitee:https://gitee.com/noear/solon github:https://github.com/noear/solon 官网? https://solon.noear.org

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

Springboot 2.x 如何解决重复提交 (本地锁的实践)

有没有遇到过这种情况:网页响应很慢,提交一次表单后发现没反应,然后你就疯狂点击提交按钮(12306就经常被这样怒怼),如果做过防重复提交还好,否则那是什么级别的灾难就不好说了。。。 本文主要是应用 自定义注解、 spring AOP、· Guava Cache 生成一种本地锁,来达到的防重复提交效果,由于是基于内存的缓存,所以这种实现方式并不适用于分布式服务 Guava是什么? guava包是google嫌弃JAVA自带的类库不好用,自行研发的一套工具包,对JDK工具做了很好的拓展。例如:并发[Concurrency]、缓存[Caches]、 函数式风格[Functional idioms]、 字符串处理[Strings]等等。 一、引入Guava包依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>21.0</version> </dependency> 二、自定义LocalLock注解 自定义一个LocalLock注解用于需要防止重复提交的方法上 /** * 锁的注解 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface LocalLock { /** * @author fly */ String key() default ""; } 注解定义好以后就需要做AOP拦截器切面的具体实现,在 interceptor() 方法上采用的是 Around(环绕增强) ,所有带 LocalLock 注解的都将被切面处理; 既然是缓存,那紧跟的属性一定要有过期时间,通过expireAfterWrite 设置缓存的过期时间,maximumSize设置缓存的个数。 通过在内存中查询key是否存在来判断是否让再次提交,和Redis的setNX方法是一个原理。 那么这个注解该怎么用呢? @Aspect @Configuration public class LockMethodInterceptor { private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder() // 最大缓存 100 个 .maximumSize(1000) // 设置写缓存后 5 秒钟过期 .expireAfterWrite(5, TimeUnit.SECONDS) .build(); @Around("execution(public * *(..)) && @annotation(com.battcn.annotation.LocalLock)") public Object interceptor(ProceedingJoinPoint pjp) { MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); LocalLock localLock = method.getAnnotation(LocalLock.class); String key = getKey(localLock.key(), pjp.getArgs()); if (!StringUtils.isEmpty(key)) { if (CACHES.getIfPresent(key) != null) { throw new RuntimeException("请勿重复请求"); } // 如果是第一次请求,就将 key 当前对象压入缓存中 CACHES.put(key, key); } try { return pjp.proceed(); } catch (Throwable throwable) { throw new RuntimeException("服务器异常"); } finally { // TODO 为了演示效果,这里就不调用 CACHES.invalidate(key); 代码了 } } /** * key 的生成策略,如果想灵活可以写成接口与实现类的方式(TODO 后续讲解) * * @param keyExpress 表达式 * @param args 参数 * @return 生成的key */ private String getKey(String keyExpress, Object[] args) { for (int i = 0; i < args.length; i++) { keyExpress = keyExpress.replace("arg[" + i + "]", args[i].toString()); } return keyExpress; } } 控制层的实现 我们将注解加在控制层方法上,key = "city:arg[0] key自己定义,arg[0]这个匹配规则表示替换成第一个参数。那么就实现city:token在一定时间内不可以重复提交了 @RestController @RequestMapping("/city") public class BookController { @LocalLock(key = "city:arg[0]") @GetMapping public String query(@RequestParam String token) { return "ok- " + token; } } 测试 接下来我们就测试一下,我用的是postman 第一请求正常响应 紧接着请求第二次,返回结果“重复提交”,显然我们实现成功了 整理了几百本各类技术电子书,送给小伙伴们。关注公号回复【666】自行领取。和一些小伙伴们建了一个技术交流群,一起探讨技术、分享技术资料,旨在共同学习进步,如果感兴趣就加入我们吧! 无论你是刚入行、还是已经有几年经验的程序员,相信这份面试提纲都会给你不少助力,长按二维码关注 『 程序员内点事 』 ,回复 『 offer 』 自行领取,祝大家 offer 拿到手软

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

Springboot过滤器和拦截器详解及使用场景

一、过滤器和拦截器的区别 1、过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。 2、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。 3、过滤器的实现基于回调函数。而拦截器(代理模式)的实现基于反射 4、Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。 5、Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。 6、Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。 过滤器和拦截器非常相似,但是它们有很大的区别 最简单明了的区别就是**过滤器可以修改request,而拦截器不能 过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境 拦截器可以调用IOC容器中的各种依赖,而过滤器不能 过滤器只能在请求的前后使用,而拦截器可以详细到每个方法** 区别很多,大家可以去查下 总的来说 过滤器就是筛选出你要的东西,比如requeset中你要的那部分 拦截器在做安全方面用的比较多,比如终止一些流程 网上有一张图片很不错,这里拷过来给大家看一下 过滤器(Filter) :可以拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息。 拦截器(Interceptor):可以拿到你请求的控制器和方法,却拿不到请求方法的参数。 切片(Aspect): 可以拿到方法的参数,但是却拿不到http请求和响应的对象 二、过滤器 两种方式: 1、使用spring boot提供的FilterRegistrationBean注册Filter 2、使用原生servlet注解定义Filter 两种方式的本质都是一样的,都是去FilterRegistrationBean注册自定义Filter 方式一: (使用spring boot提供的FilterRegistrationBean注册Filter ) ①、先定义Filter: package com.corwien.filter; import javax.servlet.*; import java.io.IOException; public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // do something 处理request 或response // doFilter()方法中的servletRequest参数的类型是ServletRequest,需要转换为HttpServletRequest类型方便调用某些方法 System.out.println("filter1"); // 调用filter链中的下一个filter HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String ip = request.getRemoteAddr(); String url = request.getRequestURL().toString(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date d = new Date(); String date = sdf.format(d); System.out.printf("%s %s 访问了 %s%n", date, ip, url); filterChain.doFilter(request, response); } @Override public void destroy() { } } ②、注册自定义Filter @Configuration public class FilterConfig { @Bean public FilterRegistrationBean registrationBean() { ** FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new** **MyFilter());** filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } } 方式一的①②步骤可以用下面这段代码代替: @Configuration public class FilterConfig { @Bean public **FilterRegistrationBean** registFilter() { **FilterRegistrationBean registration** **= new FilterRegistrationBean(); registration.setFilter(new** **LogCostFilter());** registration.addUrlPatterns("/*"); registration.setName("LogCostFilter"); registration.setOrder(1); return registration; } } public class LogCostFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { long start = System.currentTimeMillis(); filterChain.doFilter(servletRequest,servletResponse); System.out.println("Execute cost="+(System.currentTimeMillis()-start)); } @Override public void destroy() { } 方式二:(使用原生servlet注解定义Filter) // 注入spring容器 @Component // 定义filterName 和过滤的url @WebFilter(filterName = "my2Filter" ,urlPatterns = "/*") public class My2Filter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter2"); } @Override public void destroy() { } } 这里直接用@WebFilter就可以进行配置,同样,可以设置url匹配模式,过滤器名称等。这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在启动类中加另外一个注解:@ServletComponetScan,指定扫描的包。 三、拦截器的配置 实现拦截器可以通过继承HandlerInterceptorAdapter类也可以通过实现HandlerInterceptor这个接口。另外,如果preHandle方法return true,则继续后续处理。 首先我们实现拦截器类: public class LogCostInterceptor implements HandlerInterceptor { long start = System.currentTimeMillis(); @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { start = System.currentTimeMillis(); return true; } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("Interceptor cost="+(System.currentTimeMillis()-start)); } @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } } 我们还需要实现HandlerInterceptor这个接口,这个接口包括三个方法,preHandle是请求执行前执行的,postHandler是请求结束执行的,但只有preHandle方法返回true的时候才会执行,afterCompletion是视图渲染完成后才执行,同样需要preHandle返回true,该方法通常用于清理资源等工作。除了实现上面的接口外,我们还需对其进行配置: @Configuration public class InterceptorConfig extends WebMvcConfigurerAdapter { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogCostInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } } 这里我们继承了WebMVCConfigurerAdapter,这里我们重写了addInterceptors这个方法,进行拦截器的配置,主要配置项就两个,一个是指定拦截器,第二个是指定拦截的URL。 坑坑坑: 拦截器不生效常见问题: 1)是否有加@Configuration 2)拦截路径是否有问题**和* 3)拦截器最后路径一定要 “/**”, 如果是目录的话则是/*/ 总结一下:创建拦截器需要两步: 1、自定义拦截器 2、注册拦截器 四、应用场景 拦截器是在DispatcherServlet这个servlet中执行的,因此所有的请求最先进入Filter,最后离开Filter。其顺序如下。 Filter->Interceptor.preHandle->Handler->Interceptor.postHandle->Interceptor.afterCompletion->Filter 拦截器应用场景 拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括: 登录验证,判断用户是否登录。 权限验证,判断用户是否有权限访问资源,如校验token 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。 处理cookie、本地化、国际化、主题等。 性能监控,监控请求处理时长等。 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现) 过滤器应用场景 1)过滤敏感词汇(防止sql注入) 2)设置字符编码 3)URL级别的权限访问控制 4)压缩响应信息 看完三件事❤️ 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙: 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。 关注公众号 『java烂猪皮』,不定期分享原创知识。 同时可以期待后续文章ing🚀 作者:Corwien 出处: https://segmentfault.com/a/1190000037755221

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册