精华内容
下载资源
问答
  • IDEA查找接口实现类及快速实现接口

    万次阅读 2018-08-28 18:30:28
    查找接口的实现类: IDEA 风格 ctrl + alt +B   IDEA快速实现接口快捷方式 ALT +INSERT  

    查找接口的实现类:

    IDEA 风格 ctrl + alt +B

     

    IDEA快速实现接口快捷方式

    ALT +INSERT

     

    展开全文
  • Spring Boot + Token 实现接口幂等性 | 防止表单重复提交 一、概念 幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如: 订单接口, 不能多次创建订单 支付接口, 重复支付...

    Spring Boot + Token 实现接口幂等性 | 防止表单重复提交

    一、概念

    幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如:

    • 订单接口, 不能多次创建订单

    • 支付接口, 重复支付同一笔订单只能扣一次钱

    • 支付宝回调接口, 可能会多次回调, 必须处理重复回调

    • 普通表单提交接口, 因为网络超时等原因多次点击提交, 只能成功一次 等等

    二、常见解决方案

    1. 唯一索引 -- 防止新增脏数据

    2. token机制 -- 防止页面重复提交

    3. 悲观锁 -- 获取数据的时候加锁(锁表或锁行)

    4. 乐观锁 -- 基于版本号version实现, 在更新数据那一刻校验数据

    5. 分布式锁 -- redis(jedis、redisson)或zookeeper实现

    6. 状态机 -- 状态变更, 更新数据时判断状态

    三、本文实现

    本文采用第2种方式实现, 即通过token机制实现接口幂等性校验。(假如是分布式环境,可以考虑将生成的token由JVM内存(session)转移到redis等,可参考:https://mp.weixin.qq.com/s/v_iyZVd5ldixnhaxkdSArA)

    四、实现思路

    为保证幂等性,每一次请求(创建订单)接口都生成一个新的唯一标识 token, 并将此 token存入session, 同时返回token给其前端,下次请求(下单)接口时, 将此 token放到header或者作为请求参数带过来, 后端(下单)接口判断当前session中的token与前端传递过来的token是否相等:

    • 当前session中是否存在此token

    • 前端请求参数中是否携带有token

    • 如果都存在, 并且相等,正常处理业务逻辑, 并从session中删除此 token, 那么, 如果是重复请求, 由于 token已被删除, 则不能通过校验, 返回 请勿重复操作提示

    • 如果不存在, 说明参数不合法或者是重复请求, 返回提示即可

    集群环境采用token加redis(redis单线程)

    单JVM环境采用token加redis或token加jvm内存

    五、项目简介

    • SpringBoot

    • Thymeleaf (Spring Boot 推荐使用 Thymeleaf 来代替 JSP)

    • 自定义注解@Token注解 + 拦截器对请求进行拦截

    • 继承WebMvcConfigurationSupport ,在其中配置拦截器

    六、项目实战

    1、先创建一个SpringBoot工程,并引入Thymeleaf 视图模板依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>

    2、自定义注解@Token ,只需要在具体的请求接口方法添加即可。

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Token {
    
        /**
         * 是否创建新的token
         */
        boolean generate() default false;
        /**
         * 是否移除token
         */
        boolean remove() default false;
    }

    3、创建拦截器,并且继承 HandlerInterceptorAdapter ,或者实现 HandlerInterceptor 接口,建议使用HandlerInterceptorAdapter,因为可以按需进行方法的覆盖,不用实现所有方法。

    /**
     * @description: 表单提交--token拦截器
     * @author: xianhao_gan
     * @date: 2019/08/16
     **/
    @Slf4j
    public class TokenInterceptor extends HandlerInterceptorAdapter {
    
        /** The Constant TOKEN. 放在session中的token */
        private static final String TOKEN = "token";
    
        /**
         * 拦截处理程序的执行。在HandlerMapping之后调用,确定适当的处理程序对象,但是在HandlerAdapter调用处理程序之前调用。
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                                 Object handler) throws Exception {
            if (handler instanceof HandlerMethod) {
                Method method = ((HandlerMethod) handler).getMethod();
                Token tokenAnnotation = method.getAnnotation(Token.class);
                if (tokenAnnotation != null) {
                    HttpSession session = request.getSession();
    
                    // 创建新的表单提交令牌token,防止表单重复提交
                    boolean isGenerate = tokenAnnotation.generate();
                    if (isGenerate) {
                        String formToken = UUID.randomUUID().toString();
                        session.setAttribute(TOKEN, formToken);
                        log.info("创建表单提交令牌成功,token:" + formToken);
                        return true;
                    }
    
                    // 删除token令牌
                    boolean isRemove = tokenAnnotation.remove();
                    if (isRemove) {
                        if (isRepeatSubmit(request)) {
                            log.warn("表单不能重复提交:" + request.getRequestURL());
                            return false;
                        }
                        session.removeAttribute(TOKEN);
                    }
                }
            } else {
                return super.preHandle(request, response, handler);
            }
            return true;
        }
    }

    其中,我们只需要覆写preHandle方法即可。

    说明:

    • preHandle 方法会在请求处理之前进行调用(Controller方法调用之前)
    • postHandle 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
    • afterCompletion 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)

    isRepeatSubmit校验token方法如下:

        /**
         * 表单是否重复提交校验
         * @param request
         * @return
         */
        private boolean isRepeatSubmit(HttpServletRequest request) {
            //session中token
            String token = (String) request.getSession().getAttribute(TOKEN);
            if (StringUtils.isEmpty(token)) {
                return true;
            }
            //请求头中获取token
            String reqToken = request.getHeader(TOKEN);
            if (StringUtils.isEmpty(reqToken)) {
                //请求参数request中获取token
                reqToken = request.getParameter(TOKEN);
                if (StringUtils.isEmpty(reqToken)) {
                    return true;
                }
            }
            //对比session与前端传递过来的token是否相等
            if (!token.equals(reqToken)) {
                return true;
            }
            return false;
        }

    4、配置拦截器

    5、新增OrderController 控制器,分别提供创建订单(跳转订单)、提交订单(下单)两个http接口。

    并且在创建订单接口方法加上注解@Token(generate = true)

    在提交订单接口方法加上注解@Token(remove = true)

    package com.stwen.token.controller;
    
    import com.stwen.token.annotation.Token;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * @description: 订单控制器
     * @author: xianhao_gan
     * @date: 2019/08/16
     **/
    @Controller
    @RequestMapping("/order")
    @Slf4j
    public class OrderController {
    
        @RequestMapping("/")
        public String index(){
            return "index";
        }
    
        /**
         * 跳转订单详情页面--下单
         * @param request
         * @param response
         * @return
         */
        @RequestMapping("/detail")
        @Token(generate = true)
        public String orderPage(HttpServletRequest request, HttpServletResponse response){
    
            //TODO 调用具体业务逻辑-生成订单
    
            log.info("打开订单详情...");
            return "order_detail";
        }
    
        /**
         * 提交订单
         * @param request
         * @param response
         * @return
         */
        @RequestMapping("/submit")
        @Token(remove = true)
        public String orderSubmit(HttpServletRequest request, HttpServletResponse response){
    
            //TODO 调用具体业务逻辑--提交订单
    
            log.info("hello,订单提交成功。");
            return "success";
        }
    
    }
    

    注意:在接口方法中可以具体调用自己的业务逻辑,但是需要考虑异常情况:在你处理具体业务逻辑时发生异常,比如创建订单-跳转订单接口业务逻辑发生异常,但是拦截器 preHandle 方法已经创建好了token放在session中,这时就需要手动删除session中的token,或者实现一个切面@Aspect,在@AfterThrowing 中捕获异常时,清除session中token等。

    6、新增3个html测试页面:index.html 、order_detail.html、success.html

    由 index.html 跳转到 order_detail.html 时,会被拦截创建一个token,返回放到input 隐藏域,当点击提交时,会把该token一并带过去。提交订单成功,将返回success 成功页面。

    7、测试

    运行项目,配置的是8080 端口,访问:localhost:8080/ 显示首页,点击如下,便会跳转到订单详情-下单

    如下,打开开发者模式(F12)查看隐藏域已经返回了一个token

    点击上面的“提交”,成功

    后台控制台显示如下:

    当重复提交同一个表单时将会提示,不可以重复提交。

    展开全文
  • java 实现接口

    千次阅读 2018-06-30 10:11:19
    6.2 实现接口 1 类实现接口 在Java语言中,接口由类来实现以便使用接口中的方法。 一个类需要类声明中使用关键字implements声明该类实现个或多个接口。 如果实现多个接口,用逗号隔开接口名,例如A类实现Pintable...

    6.2 实现接口

        1 类实现接口

          在Java语言中,接口由类来实现以便使用接口中的方法。 一个类需要类声明中使用关键字implements声明该类实现个或多个接口。 如果实现多个接口,用逗号隔开接口名,例如A类实现Pintable和Addable接口。

    classA implements Printable,Addable

          再如,Animal 的Dog子类实现Eatable和Sleepable接口。

    classDog extends Aninal implements Eatable,Sleepable

        2.重写接口中的方法

          如果一个非抽象类实现了某个接口,那么这个类必须重写这个接口中的所有方法。需要注意的是,由于接口中的方法定是public abstract 方法,所以类在重写接口方法时不仅要去掉abstract 修饰符、给出方法体,而且方法的访问权限一定要明显地用public来修饰(否则就降低了访问权限,这是不允许的).实现接口的非抽象类实现了该接口中的方法,即给出了方法的具体行为功能。用户也可以自定义接口,一个Java源文件可以由类和接口组成。

          下面的例子1中包含China类、Japan类和Compuable接口,而且China类和Japan类都实现了Computable接口。

    Computable.java

    public interface Computable{
    	int MAX=46;
    	int f(int x);
    }

    China.java

    class China implements Computable{ //China类实现Computable接口
    	int number;
    	public int f(int x){       //不要忘记publie关键宇
    		int sum=0;
    		for(int i=0;i<=x;i++){
    			sum=sum+i;
    		}
    		return  sum;
    	}
    }

    Japan.java

    class Japan implements Computable { //Japan 类实现Computable接口
    	int number;
    	public int f(int x){
    		return MAX+x; //直接使用接口中的常量
    	}
    }

    Example6_1.java

    public class Example6_1{
    	public static void main(String args[]){
    		China zhang;
    		Japan henlu;
    		zhang=new China();
    		henlu=new Japan();
    		zhang.number=32+Computable .MAX; //用接口名访问接口的常量
    		henlu.number=14+Computable.MAX;
    		System.out.println("zhang的学号"+zhang.number+",zhang 求和结果"+zhang.f(100));
    		System.out.println("henlu的学号"+henlu.number+",henlu 求和结果"+henlu.f(100));
    	}
    }

    如果一个类声明实现一个接口,但没有重写接口中的所有方法,那么这个类必须是抽象类,也就是说,抽象类既可以重写接口中的方法,也可以直接拥有接口中的方法,例如:

    interface Computable {
        final int MAX = 100;
        vo1d speak(String s);
        int f(int x);
        float g(float x,float y);
    }
    abstract classA implements Computable{
        public int f(int x){
            int sum 0:
            for(int i=1;i<=x;i++) {
                sum=sum+i;
            }
        return sum;
        }
    }

        4.接口的细节说明

          程序可以用接口名方问接口中的常量,但是如果个类实现了接口,那么该类可以直接在类体中使用该接口中的常量。

    定义接口时,如果关键字interface前面加上public关键字,就称这样的接口是一个public接口。public接口可以被任何一个类实现。如果一个接口不加public修饰,就称作友好接口,友好接口可以被与该接口在同一包中的类实现。

          如果父类实现了某个接口,那么子类也就自然实现了该接口,子类不必再显式地使用关键字implements声明实现这个接口,

          接口也可以被继承,即可以通过关键字extends声明个接口是另个接口的 子接口。由于接口中的方法和常量都是public的,子接口将继承父接口中的全部方法和常量。

    注: Java提供的接口都在相应的包中,通过import语向不仅可以引入包中的类,也可以引入包中的接口,例如:
    
        importJava.io.*;
    
    不仅引入了java.io包中的类,同时也引入了该包中的接口。
    
    

    展开全文
  • IDEA快速实现接口快捷方式 ALT +INSERT 例如:查看Subject接口的实现类; 一.常用快捷键(这些我们经常用) Alt + Enter 引入类 Ctrl + O 查看我们继承的类或者接口中的方法,以及我们要实现的方法 Ctrl + ...

    查找接口的实现类:

    IDEA 风格 ctrl + alt +B

     

    IDEA快速实现接口快捷方式

    ALT +INSERT

    例如:查看Subject接口的实现类;

    一.常用快捷键(这些我们经常用)

    Alt + Enter   引入类

    Ctrl + O  查看我们继承的类或者接口中的方法,以及我们要实现的方法

    Ctrl + Alt + b

    查看接口实现类中方法(就是我们使用接口编程时,在调用实现类方法处直接Ctrl+鼠标左键方法,只能进入到接口中定义的方法处,但是使用该快捷键则直接到实现类的该方法中了)

    idea快捷键:ctrl+alt+v idea 调用方法快速赋值变量

    Alt + Insert    set/get; 构造方法;  toString; 重写方法。。。

    Ctrl+Alt+T 将代码包在一个块中,例如try/catch  ;synchronized等

    在IDEA 中的任何位置都可以使用此快捷键Ctrl + Shift + n或者麻烦点的,知道类名查找类:Ctrl + Shift + Alt + N; 哈哈,我知道你不会记麻烦的。

     

    展开全文
  • 对C#隐式实现接口成员与显示实现接口成员的简单说明
  • 实现接口 Interface Iterable<T>

    万次阅读 2019-03-19 19:58:30
    实现接口 Interface IterableJava Doc完整代码 Java Doc public interface Iterable Implementing this interface allows an object to be the target of the enhanced for statement (sometimes called the “for-...
  • 实现类AccessTokenListener实现了接口ServletContextListener,但是eclipse却没有红线提示实现类AccessTokenListener去实现接口的方法。 import javax.servlet.ServletContextListener; public class ...
  • IDEA实现接口方法的实现

    千次阅读 2018-07-04 14:43:30
    IDEA快速实现接口快捷方式ALT +INSERT
  • Kotlin编程之接口和实现接口

    万次阅读 2017-05-31 17:41:08
    Kotlin编程中: 定义接口和实现接口
  • 抽象类实现接口

    千次阅读 2018-07-11 22:30:12
    https://www.cnblogs.com/IanI/p/4549851.html众所周知普通类如果实现一个接口,那么普通类需要重写接口中的所有方法... 在Java中,使用抽象类来实现接口,并不是毫无作用。相反,有时间有很大的作用。 当你只想...
  • 1.结论 并不是所有的类实现接口后都必须实现接口的所有方法!2.特殊情况 当Java抽象类实现某个接口后没必要实现所有的方法。3.注意点 当Java普通类实现接口后必须实现接口中的所有方法。4.原因为什么抽象类不需要...
  • 定义和实现接口

    千次阅读 2017-09-25 20:10:09
    接口在继承中我们讲到了接口,那么如何去定义和实现一个接口呢?定义一个接口在语法上和定义一个抽象类完全相同...}实现接口 public class Type1Enemy:IFlyHandler{}如果有同时继承多个接口,那么就用逗号隔开接口名。
  • java抽象类实现接口可以不用实现方法 学习struts2时,拦截器接口Interceptor继承了Serializable接口,拦截器抽象类AbstractInterceptor实现了Interceptor接口,在AbstractInterceptor类中却没有声明或...
  • 继承接口与实现接口的理解

    千次阅读 2017-05-28 21:47:29
    在我学习的过程中发现对两个相似的概念很难理解,就是实现接口和继承接口,我在网上也查了查答案,发现不是我想要的回答。我就是想弄清楚一个类实现一个接口和继承一个接口有什么区别,因为我发现就没有区别,继承和...
  • java 的接口可以实现接口吗?抽象类呢?

    万次阅读 多人点赞 2017-05-15 15:52:56
    面试中可能会遇到这样的问题: 1.接口可以实现接口吗? ans:不可以. 2.抽象类可以实现接口吗? ans:可以
  • Java中类实现接口

    万次阅读 2018-09-05 17:39:49
    Java中类实现接口实例: (方便查看) 设计一个动物声音“模拟器”,希望模拟器可以模拟许多动物的叫声,为了便于扩展采用面向接口的编程思想来实现,编写想应的类以及主类,并且能够调用模拟器发出两种不同动物的...
  • IDEA快速实现接口快捷方式

    万次阅读 2017-02-28 11:29:00
    IDEA快速实现接口快捷方式 ALT +INSERT
  • 实现接口Controller定义控制器

    千次阅读 2018-10-24 20:24:00
    实现接口Controller定义控制器 实现接口Controller定义控制器 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现。 控制器解析用户的请求并将其转换为一个模型。在Spring ...
  • PHP实现接口多继承

    千次阅读 2017-06-13 16:53:47
    当然接口的继承也是和类的继承一样使用extends关键字...需要注意的是当你接口继承其它接口时候,直接继承父接口的静态常量属性和抽象方法,所以类实现接口时必须实现所有相关的抽象方法。 下面举例说明: 1.继承单接口
  • C++纯虚函数实现接口

    千次阅读 2017-12-13 14:29:28
    C++纯虚函数纯虚函数语法 virtual type functionname()=0;virtual声明的方法后加上=0是纯虚函数 Java Interface接口Java 中使用Interface...Java Interface接口C++实现接口利用两个特性 1. 纯虚函数必须被派生类实现
  • 定义一个接口,并定义相应的类来实现实现接口中的方法 */ public interface Circle {//定义接口 double PI = 3.1415;// 定义常量 void setRadius(double radius);// 定义抽象方法 double area();// 定义抽象...
  • Promise实现接口超时限制

    千次阅读 2018-12-27 23:22:17
    主要思想:通过Promise.race()实现接口超时限制    // 定义上传文件接口函数 export const uploadFile= (params) =&gt; { let uri = serverSrc + '/api/xxx/xxx' // 设置请求地址 return Promise.race([ ...
  • Java 枚举实现接口进行统一管理

    千次阅读 2019-06-26 19:39:06
    Java 枚举实现接口进行统一管理
  • C#中定义和实现接口

    千次阅读 2018-04-09 19:58:56
    定义和实现接口 定义一个接口在语法上与定义一个抽象类完全相同,但是不允许提供接口中任何成员的实现方式,也即只能含有方法的签名,不能有方法的实现。一般情况下,接口只包含方法、属性、索引器和事件的声明。 ...
  • PHP实现接口

    千次阅读 2018-07-24 21:00:48
     接口的思想是指定一个实现了该接口的类必须实现的一系列函数。一般,我们用interface来声明一个接口,并在接口中声明一些方法(即函数),注意只是声明不用实现这个函数。然后,用class声明一个类并用implements去...
  • 问题引入: 今天用vs2008 快捷键时 我按了shift+Alt+F10 (接口的快捷键),vs提示 是否显式实现接口,就顺便查了什么是显式什么是隐式, 以及他们的区别,现总结如下: 先定义一个接口:public Interface ...
  • 我们可以定义一个接口类型的引用变量来引用实现接口的类的实例,当这个引用调用方法时,它会根据实际引用的类的实例来判断具体调用哪个方法,这和上述的超类对象引用访问子类对象的机制相似。//定义接口InterA ...
  • visio实现接口UML图

    千次阅读 2014-03-04 18:37:11
    visio画实现接口 手把手完成visio画一个接口加一个实现类,使用标准的UML实现接口的形状 1 首先画一个接口 2 改变接口的显示方式为类显示 3 画出实现类 4 右键 实现类选择【 形状显示选项】,点击【实现链接】。...
  • 实现接口@override加上报错?

    千次阅读 2019-01-27 12:17:33
    对于类实现接口,实现方法时,对于编译器级别1.5,方法上不允许增加这个注解。(在1.5级别时,类对接口的实现不叫继承) 而对于1。6以上级别就可以增加这个注解,类继承类,类实现接口,都可以看作方法的重写 解决:...
  • **抽象类可以使用implements关键字实现接口,但又不用在该抽象类里实现接口里的具体方法(不实现接口的具体方法不会报错),那设计抽象类可以使用implements来实现接口有什么意义啊?** 抽象类: public ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 465,141
精华内容 186,056
关键字:

实现接口