首页 > 编程语言 >Kotlin与Java互调原理项目实战

Kotlin与Java互调原理项目实战

时间:2023-06-19 10:37:36浏览次数:79  
标签:body Java java Kotlin 互调 kotlin 转换 size View


数天前我将我java开发的工程,全部转换成了kotlin形式的工程。如果你也想做,本身也有一定的java开发安卓程序的功底。本文将比较适合你。

创建kotlin工程,拷贝类文件xml文件等核心文件到工程目录下,形成一个kotlin底子的java代码组成的工程,然后通过ctrl +shift +alt +k 快捷代码逐个转换为kotlin。转换的结果相对比较成功。将转换中遇到的问题总结如下。

1. 循环,改成filter map的使用

那些只是听说过kotlin的小白,在转换前,请参考:最适合Android程序员的kotlin笔记——集合操作 很多普通的操作,AS可以帮我们自动转,但是唯独集合(AS工具的薄弱环节)这里可以优化的比较多。所以建议熟悉。

2. 字符串非空判断改成kotlin形式。

快捷键转换后,还是equal("")形式,改成纯正的kotlin风格:
一下方法为kotlin特有:

.isEmpty()
.isBlank()
.isEmptyOrNull()
.isNullOrBlank()

类似的,点出来,自己看用那个合适。

3. 不必要的bindview

原来的:

@BindView(R.id.ad_image)
    ImageView ad_image;
    @BindView(R.id.countdownProgressView)
    TextView countdownProgressView;

问题: 类似此类的代码,转换后还会存在。

解决办法: 转换前,对齐控件的变量名和id名。转换后,直接删掉。

你会惊奇的发现,.kt 文件直接引用了xml文件。代码中可以直接使用id来对view进行操作了。

4.丑陋的equals

if (!StringUtils.equals(password, password2)) {
        toast(resources.getString(R.string.two_password_input_error))
        return
    }

改成等号,不等号。

java中的 equals ,kotlin中可用 == 替代,java中的比较对象的引用,kotlin中,用===替代。

5. 容易错转的map

在进行此类型的转换和修正前,请百度一下kotlin map集合操作。
以下是原java代码:

private String getTypemane(int id) {
        String aa = "";
        List<Map<Integer, String>> typelist = listDataSaveUtil.getDataList();
        Map<Integer, String> map = typelist.get(0);
        for (Map.Entry<Integer, String> str : map.entrySet()) {
            if (String.valueOf(id).equals(str.getKey() + "")) {
                aa = str.getValue();
            }
        }
        return aa;
    }

ktlin错误转换为:

private fun getTypemane(id: Int): String {
        var aa = ""
        val typelist = listDataSaveUtil!!.getDataList<Map<Int, String>>()
        val map = typelist[0]
        for ((key, value) in map) {
            if (id == key) {
                aa = value
            }
        }
        return aa
    }

运行报错,不能将int 转number,我给他改成了:

private fun getTypemane(id: Int): String {
        var aa = ""
        val typelist = listDataSaveUtil!!.getDataList<Map<Int, String>>()
        val map = typelist[0]
       if(map.contains(id)){
            aa=map.getValue(id)
        }
        return aa
    }

6.不够清爽的if else 转换

java代码:

private void isShowRv(AllTypeBean body) {
        if (getAreaList(body).size() == 1) {
            mRvArea.setVisibility(View.GONE);
        } else {
            mRvArea.setVisibility(View.VISIBLE);
        }

        if (body.getClassX().size() == 1) {
            mRvStyle.setVisibility(View.GONE);
        } else {
            mRvStyle.setVisibility(View.VISIBLE);
        }

        if (body.getType().size() == 1) {
            mRvAllTvStyle.setVisibility(View.GONE);
        } else {
            mRvAllTvStyle.setVisibility(View.VISIBLE);
        }

        if (body.getYear().size() == 1) {
            mRvYear.setVisibility(View.GONE);
        } else {
            mRvYear.setVisibility(View.VISIBLE);
        }

    }

使用快捷键转换,怎么结果还是一堆if?!!
还是难看,能否用when(kotlin最擅长的)改造下,动手,效果如下:

when {
            getAreaList(body!!).size == 1 -> mRvArea!!.visibility = View.GONE
            getAreaList(body!!).size != 1 -> mRvArea!!.visibility = View.VISIBLE

            body!!.classX!!.size == 1 -> mRvStyle!!.visibility = View.GONE
            body.classX!!.size != 1 -> mRvStyle!!.visibility = View.VISIBLE

            body!!.type!!.size == 1 -> mRvAllTvStyle!!.visibility = View.GONE
            body.type!!.size != 1 -> mRvAllTvStyle!!.visibility = View.VISIBLE

            body!!.year!!.size == 1 -> mRvYear!!.visibility = View.GONE
            body.year!!.size != 1 -> mRvYear!!.visibility = View.VISIBLE
        }

运行,程序业务逻辑出错!!!!,断点研究发现,代码只走到when中第二行,就break了。后面没走。好傻!生手!

正确的写法:如下:

when {
            getAreaList(body!!).size == 1 -> mRvArea!!.visibility = View.GONE
            getAreaList(body!!).size != 1 -> mRvArea!!.visibility = View.VISIBLE
        }
        when {
            body!!.classX!!.size == 1 -> mRvStyle!!.visibility = View.GONE
            body.classX!!.size != 1 -> mRvStyle!!.visibility = View.VISIBLE
        }
        when {
            body!!.type!!.size == 1 -> mRvAllTvStyle!!.visibility = View.GONE
            body.type!!.size != 1 -> mRvAllTvStyle!!.visibility = View.VISIBLE
        }
        when {
            body!!.year!!.size == 1 -> mRvYear!!.visibility = View.GONE
            body.year!!.size != 1 -> mRvYear!!.visibility = View.VISIBLE
        }

一堆when,不爽。能否再简化下,聪明的你一定想到了,还是用回if else

if在 java中是语句,kotlin中是表达式(表达式有值,语句不返回值)

改!:

mRvArea!!.visibility = if (getAreaList(body!!).size == 1) View.GONE else View.VISIBLE
        mRvStyle!!.visibility = if (body!!.classX!!.size == 1) View.GONE else View.VISIBLE
        mRvAllTvStyle!!.visibility = if (body!!.type!!.size == 1) View.GONE else View.VISIBLE
        mRvYear!!.visibility = if (body!!.year!!.size == 1) View.GONE else View.VISIBLE
总结: when结构,替换的时候,典型的场景应该是switch case 那种(一旦某一个条件满足,直接跳出函数体)
普通的if根据需求,千万别像我一样转错了。但是如果是连续的else if结构,也可以替换。
if (customView != null) {
                hideCustomView()
            } else if (wv_web_view!!.canGoBack()) {
                wv_web_view!!.goBack()
            } else {
                finish()
            }

转成如下:

when{
                customView != null-> hideCustomView()
                wv_web_view!!.canGoBack()->  wv_web_view!!.goBack()
                else->finish()
            }

还有这种单if的垃圾代码,都很适合转when

注意这种单if和上面的单if的不同,这正是我这个条目想强调的部分。
if (VipType == HdVipType) {
            userMessage!!.vip!!.isHdvip = true
        }
        if (VipType == DlanVipType) {
            userMessage!!.vip!!.isDlanvip = true
        }
改动秘诀:

看是否能转换为else if 能转换成else if的 ,在转when,遵循这个原则。

7、漏失的toString()

例子:

private Map<Integer, String> getIntegerStringMap(HomeTypeBean body) {
        Map<Integer, String> map = new HashMap<>();
        for (HomeTypeBean.TypeBean categoryBean : body.getType()) {
            map.put(categoryBean.getType_id(), categoryBean.getType_name());
        }
        return map;
    }

转换Kotlin后:

private fun getIntegerStringMap(body: HomeTypeBean): Map<Int, String> {
        val map = HashMap<Int, String>()
        for (categoryBean in body.type!!) {
            map[categoryBean.type_id] = categoryBean.type_name
        }
        return map
    }

编译器出现报错将for循环中map一行,下划线标红。

private fun getIntegerStringMap(body: HomeTypeBean): Map<Int, String> {
        val map = HashMap<Int, String>()
        for (categoryBean in body.type!!) {
            map[categoryBean.type_id] = categoryBean.type_name.toString()
        }
        return map
    }

原来是没有添加toString(); 这种情况,as有报错,并有提示。但此处Studio给出的提示不易懂,注意!

8. 集合的转换不够彻底:

例子java代码:

private List<String> bornTypeList(HomeTypeBean body) {
        List<String> typeList = new ArrayList<>();
        for (HomeTypeBean.TypeBean categoryBean : body.getType()) {
            typeList.add(categoryBean.getType_name());

        }
        return typeList;
    }

as工具转换为kotlin代码后:

private fun bornTypeList(body: HomeTypeBean): List<String> {
        val typeList = ArrayList<String>()
        for (categoryBean in body.type!!) {
            typeList.add(categoryBean.type_name.toString())

        }
        return typeList
    }

太丑了,羞于使用,优化,代码如下:

private fun bornTypeList(body: HomeTypeBean): List<String> { 
        return body.type!!.map { it.type_name.toString() }
    }

9. 失灵的onclick

使用bindview的条件下,如下转换后的kotlin代码,出现业务问题,点击事件失灵:

@OnClick(R.id.searcher_view, R.id.play_history_image, R.id.all)
    fun onClick(v: View) {

        //搜索
        if (v === searcher_view) {
            ActivityUtils.startActivity(Intent(activity, SearcherActivity::class.java))
            return
        }
        //播放记录
        if (v === play_history_image) {
            ActivityUtils.startActivity(PlayHistoryActivity::class.java)
            return
        }

        //全部
        if (v === all) {
            val intent = Intent(activity, AllTypeActivity::class.java)
            intent.putExtra(ConstantUtils.TYPE_NAME, videoType)
            intent.putExtra(ConstantUtils.TYPE_ID, typeId)
            ActivityUtils.startActivity(intent)
        }
    }

10. 无法优雅转换的单例

在java中我有如下代码:

public class DataBeanModel {

    private SparseArray<List<PlayVosBean.VodsBean.DataBean>> listHashMap = new SparseArray<>();

    private static class SingletonHolder {
        private static final DataBeanModel INSTANCE = new DataBeanModel();
    }

    private DataBeanModel() {
    }

    public static final DataBeanModel getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public void clearAll(){
        listHashMap.clear();
    }

    public void putValue(int Page, ArrayList<PlayVosBean.VodsBean.DataBean> dataBeans){
        listHashMap.put(Page, dataBeans);
    }
    public List<PlayVosBean.VodsBean.DataBean> getSetByPage(int position){
        return  listHashMap.get(position);
    }

    public SparseArray<List<PlayVosBean.VodsBean.DataBean>> getAll(){
        return listHashMap;

    }
}

as工具转换后:

class DataBeanModel private constructor() {

    val all = SparseArray<List<PlayVosBean.VodsBean.DataBean>>()

    private object SingletonHolder {
        private val INSTANCE = DataBeanModel()
    }

    fun clearAll() {
        all.clear()
    }

    fun putValue(Page: Int, dataBeans: ArrayList<PlayVosBean.VodsBean.DataBean>) {
        all.put(Page, dataBeans)
    }

    fun getSetByPage(position: Int): List<PlayVosBean.VodsBean.DataBean> {
        return all.get(position)
    }

    companion object {

        val instance: DataBeanModel
            get() = SingletonHolder.INSTANCE
    }
}

已经非常臃肿,浓浓的java式kotlin,怎么办?
正确的做法:

  1. 注释和单例相关的方法:
private static class SingletonHolder {
        private static final DataBeanModel INSTANCE = new DataBeanModel();
    }

    private DataBeanModel() {
    }

    public static final DataBeanModel getInstance() {
        return SingletonHolder.INSTANCE;
    }
  1. 按下ctrl shift alt k 转换成kotlin,将类关键字class 替换为Object
  2. 删除注释部分
object DataBeanModel {

    val all = SparseArray<List<PlayVosBean.VodsBean.DataBean>>()
    fun clearAll() {
        all.clear()
    }

    fun putValue(Page: Int, dataBeans: ArrayList<PlayVosBean.VodsBean.DataBean>) {
        all.put(Page, dataBeans)
    }

    fun getSetByPage(position: Int): List<PlayVosBean.VodsBean.DataBean> {
        return all.get(position)
    }
}
  1. 调用的部分,改为(中间加INSTANCE):
DataBeanModel.INSTANCE.clearAll();

值得注意的是,当我在运行业务逻辑的时候,提示我,getSetByPage 这个方法: return all.get(position)
这个代码,里面all已经强制要求为空。导致我程序报错。不知道all为什么会为空。回滚吧。

10. 无法正确转换+=1

我有如下java代码:

newHost = appMessageBean.getHostUrlList().get(hostPosition += 1);

直接as转换后,在代码下面直接爆红。

解決方案:在外面写hostPosition+=1, 然后再用as工具转换,正确代码。
hostPosition = hostPosition + 1
                    newHost = appMessageBean!!.hostUrlList!![hostPosition]

11. 变异的trim方法:

我在java中的trim方法,kotlin转换为了如下形式:

result.addProperty("mobile", etPhone!!.text.toString().trim { it <= ' ' })
注意:kotlin的trim()方法意思发生了变异,是指去除前后的空格。和java中的trim方法等价的就是:.trim { it <= ’ ’ } 转换并没有发生错误,慢慢学习吧。编译器的快捷键转换是正确的。这个给编译器点个赞。

12. 不够优雅的工具类

kotlin中,方法不一定会写在类内部。操作方法,
  • 工具类去掉类的包裹,直接全部都是方法
  • 类文件的第一行,指明名字即可,如下:

@file:JvmName(“AesUtils”)
package com.play.myapplication.helper

  • java文件中该怎么用怎么用
  • 如果是在kotlin文件中,直接写方法即可,前面的“类点”也给省略了

13. 错误转换的get 方法。

默认as的转换工具,会对,get 开头的方法,进行重新梳理。

有以下java代码:

/**
     * 标题栏id
     */

    protected abstract int getTitleBarId();

    /**
     * 引入布局
     */
    protected abstract int getLayoutId();

用来子类复写,父类回调。结果AS自动转换:

/**
     * 标题栏id
     */
    protected abstract val titleBarId: Int

    /**
     * 引入布局
     */
    protected abstract val layoutId: Int

荒唐呀,我这个是一个父类方法,子类需要复写。这时候就会导致更多的转换异常,解决办法,在java阶段,改成重命名成其他(比如got)开头的方法。然后再用工具转换。

注意不要用get set开头,除非确定是当成成员处理。

13. 不够优雅的弱引用。

有弱引用代码,转换后,累赘不够优雅,并且
弱引用使用处,如下的位置,还会爆红。

weakReference.get().setAppMessageBeanFromSP()

添加双感叹号。

weakReference.get()!!.setAppMessageBeanFromSP()

爆红解决,单仍不够优雅。
解决方案:
采用委托机制处理
第一步,创建weak类:

class Weak<T : Any>(initializer: () -> T?) {
    var weakReference = WeakReference<T?>(initializer())

    constructor() : this({
        null
    })

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {
        return weakReference.get()
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
        weakReference = WeakReference(value)
    }
}

第二步
生命的地方这样写,

var act:MyActivity? by Weak()

引用的地方:

act.setAppMessageBeanFromSP()
14. 意外的问号
OkGoUtils.postRequest(ConstantUtils.getUrlConstant().getaskvip, JsonObject.toString(), new JsonCallBack<UserandVip>(UserandVip.class, this) {

            @Override
            public void onSuccess(Response<UserandVip> response) {
}
)}

转换完之后,给我添加一个:

OkGoUtils.postRequest<UserandVip>(
            ConstantUtils.getUrlConstant().getaskvip,
            JsonObject.toString(),
            object : JsonCallBack<UserandVip**?**>(
                *UserandVip::class.java, this*
            ) {
                *override fun onSuccess*(response: Response<UserandVip>) {
                    super.onSuccess(response)
}
)}

很奇怪,导致斜体的部分都在飘红。
去掉问号就可以了。这里没必要if null

15. 错误转换的json文件:重要#############巨坑巨坑#################

Kotlin与Java互调原理项目实战_java代码

之前我们项目中存在一个签到的问题,原来里面是用json转换的,字段是signin , 使用kotlin转换后,kotlin自动会为boolean类型的字段加上is,变成如上图所示,结果倒是json变换的时候,请求返回的bean中,接收不到新的数据singin=true。获取的isSignin=false。破坏了原来代码的逻辑。大罪大罪!!!!!!!!!!!!!!!!!转换方法要坑满才能明白过来呀

16. 点击事件
源代码:
btn_stop_dlan.setOnClickListener(this::onClick);
        btn_iv_dlan_full.setOnClickListener(this::onClick);
        btn_iv_add_volume.setOnClickListener(this::onClick);
        btn_iv_delete_volume.setOnClickListener(this::onClick);

        btn_ad_x.setOnClickListener(this::onClick);
        iv_pause_ad.setOnClickListener(this::onClick);
        btn_video_tv.setOnClickListener(this::onClick);
        btn_video_hd.setOnClickListener(this::onClick);
        btn_video_next.setOnClickListener(this::onClick);
        btn_video_skip.setOnClickListener(this::onClick);
        rl_close_father.setOnClickListener(this::onClick);
        rl_pause_father.setOnClickListener(this::onClick);
        rl_close_father.setOnClickListener(this::onClick);
        btn_video_start.setOnClickListener(this::onClick);
转换后的代码:

但是下面报红线

btn_stop_dlan.setOnClickListener(OnClickListener { v: View ->
            onClick(
                v
            )
        })
        btn_iv_dlan_full.setOnClickListener(OnClickListener { v: View ->
            onClick(
                v
            )
        })
        btn_iv_add_volume.setOnClickListener(OnClickListener { v: View ->
            onClick(
                v
            )
        })
        btn_iv_delete_volume.setOnClickListener(OnClickListener { v: View ->
            onClick(
                v
            )
        })
        btn_ad_x.setOnClickListener(OnClickListener { v: View ->
            onClick(
                v
            )
        })
17. 缺失的hanlder类型

java代码(减缩版)

private Handler mDialogHandler;   
  public void initTimerDialog() {
       btn_btn_finish_0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                    mDialogHandler.removeCallbacksAndMessages(null);

            }
        });
        };

快捷键转换(减缩版)

private var mDialogHandler: Handler? = null
   fun initTimerDialog() {

        btn_btn_finish_0!!.setOnClickListener(object : OnClickListener {
            override fun onClick(v: View) {

                    mDialogHandler.removeCallbacksAndMessages(null)

            }
        })
}

转换后:此行报错!
mDialogHandler.removeCallbacksAndMessages(null)
订正:
(mDialogHandler as Handler).removeCallbacksAndMessages(null)

Alt+enter中有,只要合理选择就行。

第二个坑:
简化后的java代码如下:

public Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            String s = msg.obj.toString();
            runCount();
        }
    };

转换后,第一行,handler名字这里报错:

Kotlin与Java互调原理项目实战_java_02

怎办?看了alt+enter的提示,看不懂。
解决方案就是:
不用用handler做名字,换个hanlderOne啥的,handler这个名字好像已经被占用了。

18.IDE 自带的插件转换 Java 代码, 项目上线后后台空指针Error增加(***重要#############巨坑巨坑#################***)

IDE 里面的插件 “Covert Java File To Kotlin File” 早已被大家熟知,要是不知道的小伙伴,赶紧写个 Java 文件,尝试点击 Android Studio 工具栏的 Code 下面的 “Convert Java File To Kotlin File”。
这样的方式足够地快,但却会出现很多很多的 !!,这是由于 Kotlin 的 null safety 特性。这是 Kotlin 在 Android 开发中的很牛逼的一大特性,想必不少小伙伴都被此 Android 的 NullPointException 困扰许久。我们直接转换 Java 文件造成的各种 !! ,其实也就意味着你可能存在潜在的未处理的 KotlinNullPointException。

19. 资源id和object对象的变量名重名

if (FilmAllModel.INSTANCE.getTotal() == 1)
转换为kotlin
if(total==1)
此处直接报错,阅读提示,发现,我们的一个资源id也叫total,重名导致,报错。

20. 不变的枚举

枚举对开发者非常友好。数量有限的元素,描述性的名字,因此大幅提高了代码的可读性。另外他还支持多态。由于这些原因枚举在代码中被广泛使用。——摘自作者:《Android 高性能编程》(西班牙)([恩里克·洛佩斯·马尼亚斯](意)([迪戈·格兰奇尼]

正如摘要所言,枚举很好。但我不推荐枚举,缘由有两个:

  1. 枚举通常会占用两倍于静态常亮的内存,在朱凯翻译的android delveop官方性能优化里已经不推荐(Enums usually request twice as much memory as static constants)
  1. 枚举在有几个成员,就分别会被转换为几个对象, 并且分贝为他们的name 参数分配String 。。。——《Adnroid 高性能编程》也正因为如此,以简化著称的kotlin语言,少见的为enum添加一个class ,比java的创建还多一个关键字。就是因为他本质是一个类,而且还不是一个省心的class ,是class里面还有class。

在安卓高性能编程这本书里,作者推荐,用静态常量代替枚举类的成员,将枚举类前面的enum,换成class,回归一个正常的类。

说了这么多有什么用呢? 因为kotlin自动转换,枚举类还是枚举类,若要转换的优雅,还得自己操作。
怎么办呢?

  • 我们在转换的时候也可以遵循这个步骤:
  1. 先将类转换 2 . 再转kotlin。
    java代码:
public enum EventType { 
    LOG_MINE, 
    UD_HEADER, 
    INVISIBLE_RED_DOT,
}

kotlin转换:

object EventType {    
    const val LOG_MINE = 0 
    const val UD_HEADER = 1 
    const val INVISIBLE_RED_DOT = 2
}


标签:body,Java,java,Kotlin,互调,kotlin,转换,size,View
From: https://blog.51cto.com/u_16163480/6511269

相关文章

  • kotlin协程原理分析项目实战
    自从6.0加入动态权限之后,很多地方都要用到,开始的时候使用的原生代码写权限请求,代码格式如:if(应用是否已经请求了该权限组){权限请求后的代码}else{请求权限}然后不知道在fragment或是activity里面重写overrideonRequestPermissionsResult{if(请求成功){......
  • 用kotlin来开发一个cli工具 | 没用的技能+1
    脚手架脚手架是为了保证各施工过程顺利进行而搭设的工作平台而在程序开发过程中,每个工程或者说公司也都需要一个脚手架工具。通过脚手架命令行的形式简化开发流程,避免发生一些人为的相对低级的问题,所以这个也就是为什么叫做脚手架的原因吧。而由于每个公司的代码规范都不同,一般情况......
  • java 如何字符串中提取数字,这个方法真的很不错
    Java中提取字符串中的数字,可以使用正则表达式或非正则表达式的方法。1.使用正则表达式可以使用正则表达式"\d+"来匹配字符串中的数字,并使用Matcher和Pattern类实现。importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassExtractNumbersFromString......
  • java 如何字符串中提取数字,这个方法真的很不错
    Java中提取字符串中的数字,可以使用正则表达式或非正则表达式的方法。1.使用正则表达式可以使用正则表达式"\d+"来匹配字符串中的数字,并使用Matcher和Pattern类实现。importjava.util.regex.Matcher;importjava.util.regex.Pattern;publicclassExtractNumbersFromString......
  • Java判断null的几种方式
    组内codereview时,有同学提到字符串判断空值的写法,如下两种,(1)null在后,@TestpublicvoidtestDemo1(){Stringstr=null;if(str==null){System.out.println("null在后");return;}}(2)null在前,@TestpublicvoidtestDemo2(){Stringstr=null;if(n......
  • java课程设计
    importjava.sql.*;importstaticjava.sql.DriverManager.*;importjavax.swing.*;importjava.awt.*;importjava.awt.event.*;importjava.text.SimpleDateFormat;importjava.util.ArrayList;importjava.util.Random;classConnect{//建立数据库的连接Connecti......
  • 10个ai算法常用库java版
    根据AI项目的具体需求,可以选择最合适的库或框架,并开始尝试使用不同的算法来构建AI解决方案。1.Deeplearning4j 它是一个用于Java和Scala的开源分布式深度学习库。Deeplearning4j支持各种深度学习架构,包括卷积神经网络(CNN)、递归神经网络(RNN)和深度信念网络(DBN......
  • Java Websocket 02: 原生模式通过 Websocket 传输文件
    目录JavaWebsocket01:原生模式Websocket基础通信JavaWebsocket02:原生模式通过Websocket传输文件Websocket原生模式传输文件关于Websocket传输的消息类型,允许的参数包括以下三类以下类型之一,同时只能出现一个文本类型(textmessages)的消息:String......
  • java限流
    @ComponentpublicclassLimiterUtil{@ResourceprivateRedisTemplate<String,String>redisTemplate;/***固定窗口限流算法**@returntrue限流false放行*/publicbooleanfixedWindow(Stringkey,intcount){longcountCache=redisTemplate.op......
  • daka :p java day 1!
    书写helloworld!publicclasshelloworld{publicstaticvoidmain(String[]arges){System.out.println("helloworld!");}}  ......