当前位置: 首页 > news >正文

001 websocket(评论功能demo)(消息推送)

文章目录

    • ReviewController.java
    • WebSocketConfig.java
    • WebSocketProcess.java
    • ServletInitializer.java
    • WebsocketApplication.java
    • readme
    • index.html
    • application.yaml
    • pom.xml

ReviewController.java


package com.example.controller;import com.example.websocket.WebSocketProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;@RestController
@RequestMapping("review")
public class ReviewController {@Autowiredprivate WebSocketProcess websocketProcess;@GetMapping("save/{clientID}")public String saveReview(@PathVariable("clientID") Integer clientID)  {Integer replyUserId = 90;// katyString replyUsername ="Katy";String reviewText = "展览的介绍非常不错,快去看吧!!!";String message ="用户"+replyUsername +" 在"+ LocalDateTime.now() +" 回复了您的评论,评论内容是" +reviewText;websocketProcess.sendMsg(clientID,message);return "successfully";}
}

WebSocketConfig.java


package com.example.websocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}

WebSocketProcess.java


package com.example.websocket;/*** 该类封装了 客户端与服务器端的Websocket 通讯的*  (1) 连接对象的管理   ConcurrentHashMap<Long, WebSocketProcess>*  (2) 事件监听      @OnOpen ,  @OnMessage,  @OnClose , @OnError*  (3) 服务器向 (所有/单个)客户端 发送消息*///这个代码示例展示了一个简单的WebSocket服务实现,它依赖于Java WebSocket API和Spring框架的一些特性。接下来,我会详细解释为什么这个服务能够实现其功能,特别是@OnOpen、@OnMessage、@OnClose和@OnError这些注解的作用。
//
//WebSocket基本原理
//WebSocket是一种网络通信协议,允许服务器与客户端之间建立持久的连接,并进行全双工通信。这意味着服务器和客户端可以同时发送和接收消息,而不需要像传统的HTTP请求那样,每次通信都需要重新建立连接。
//
//注解解释
//@OnOpen
//
//当一个WebSocket连接成功建立时,@OnOpen注解的方法会被调用。在这个方法中,通常会执行一些初始化操作,比如保存这个连接的信息,以便后续使用。
//在示例中,@OnOpen方法将新的WebSocket连接(即WebSocketProcess对象自身,因为它实现了@ServerEndpoint)存储到ConcurrentHashMap中,以客户端ID为键。这样,服务器就可以跟踪所有活动的WebSocket连接,并能够根据需要将消息发送给特定的客户端。
//@OnMessage
//
//当服务器从WebSocket连接接收到消息时,@OnMessage注解的方法会被调用。这个方法可以处理从客户端发送过来的数据。
//在代码中,@OnMessage方法可能只是简单地接收并打印消息,或者进行其他形式的处理(尽管示例中并未详细展示)。这是WebSocket通信中处理实时数据交换的关键部分。
//@OnClose
//
//当WebSocket连接关闭时(无论是客户端还是服务器发起的关闭),@OnClose注解的方法会被调用。这个方法通常用于清理资源,比如从连接跟踪集合中移除已关闭的连接。
//在代码中,这个方法确保当某个客户端断开连接时,其信息会从ConcurrentHashMap中删除,从而保持连接管理的准确性。
//@OnError
//
//如果在WebSocket通信过程中出现错误,@OnError注解的方法会被调用。这个方法为开发者提供了一个处理异常和错误的机制。
//在示例中,这个方法可能只是简单地打印出错误信息,但在实际应用中,你可能需要执行更复杂的错误处理和恢复逻辑。
//Spring和WebSocket的结合
//Spring框架通过@ServerEndpoint注解和ServerEndpointExporter类为WebSocket提供了强大的支持。@ServerEndpoint注解用于标记一个类作为WebSocket端点,而ServerEndpointExporter则负责在Spring容器中自动注册这些端点。
//
//通过结合Spring的依赖注入和WebSocket的实时通信能力,代码示例实现了一个功能强大的WebSocket服务,能够处理多客户端连接、消息接收和发送等核心功能。
//
//总结
//这个代码示例通过巧妙地结合Java WebSocket API和Spring框架的特性,实现了一个简单但功能完备的WebSocket服务。这个服务能够管理多个并发的WebSocket连接,处理来自客户端的消息,并能够通过REST接口向特定或所有客户端发送消息,展示了WebSocket在实时通信方面的强大能力。import org.springframework.stereotype.Component;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;/*** 1. manage client and sever socket object(concurrentHashMap)* 2. event trigger :*      receive client connect : onopen*      receive message from client : onmessage*      client socket close :onclose** 3. server  send message to client*/
@Component
@ServerEndpoint(value = "/testWebSocket/{id}")
public class WebSocketProcess {private static ConcurrentHashMap<Integer,WebSocketProcess> map = new ConcurrentHashMap();private Session session;@OnOpenpublic void onOpen(Session session, @PathParam("id") Integer clientId){this.session = session;map.put(clientId,this);System.out.println("server get a socket from client :"  + clientId);}//    receive message from client : onmessage@OnMessagepublic void onMessage(String message, @PathParam("id") Integer clientId){System.out.println("server get message from client id:" + clientId+", and message is :" + message);}@OnClosepublic void onClose(Session session, @PathParam("id") Integer clientId){map.remove(clientId);}//    server  send message to clientpublic  void sendMsg(Integer clientId,String message)  {WebSocketProcess socket =  map.get(clientId);if(socket!=null){if(socket.session.isOpen()){try {socket.session.getBasicRemote().sendText(message);System.out.println("server has send message to  client :"+clientId +", and message is:"+ message);} catch (IOException e) {e.printStackTrace();}}else{System.out.println("this client "+clientId +" socket has closed");}}else{System.out.println("this client "+clientId +" socket has exit");}}public  void sendMsg(String message) throws IOException {Set<Map.Entry<Integer, WebSocketProcess>> entrySet = map.entrySet();for(Map.Entry<Integer, WebSocketProcess> entry: entrySet ){Integer clientId = entry.getKey();WebSocketProcess socket = entry.getValue();if(socket!=null){if(socket.session.isOpen()){socket.session.getBasicRemote().sendText(message);}else{System.out.println("this client "+clientId +" socket has closed");}}else{System.out.println("this client "+clientId +" socket has exit");}}}}

ServletInitializer.java

package com.example;import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;public class ServletInitializer extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(WebsocketApplication.class);}}

WebsocketApplication.java

package com.example;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class WebsocketApplication {public static void main(String[] args) {SpringApplication.run(WebsocketApplication.class, args);}}

readme


在生产环境中,可能需要更复杂的错误处理和日志记录机制。此外,考虑到安全性,可能还需要实施WebSocket连接的身份验证和授权。WebSocket服务端:使用WebSocketProcess类来处理WebSocket连接、接收和发送消息。这个类使用了@ServerEndpoint注解来定义WebSocket端点,并通过@OnOpen@OnMessage@OnClose@OnError注解来处理WebSocket事件。REST控制器:ReviewController类是一个REST控制器,它提供了一个RESTful API(save/{clientID})来模拟用户提交评论,并通过WebSocket向特定客户端发送通知。配置:WebSocketConfig类配置了ServerEndpointExporter,这是一个Spring Bean,用于注册所有带有@ServerEndpoint注解的类作为WebSocket端点。前端页面:提供了一个简单的HTML页面,该页面使用JavaScriptWebSocket来与服务器建立连接,并接收服务器发送的消息。
Maven POM文件:定义了项目依赖和构建配置。WebSocketProcess@Component@ServerEndpoint:这两个注解表明这个类是一个Spring组件和一个WebSocket端点。
ConcurrentHashMap<Integer, WebSocketProcess>:用于管理WebSocket连接。
@OnOpen 方法:当WebSocket连接打开时调用,将连接保存到map中。
@OnMessage 方法:当从客户端接收到消息时调用(但当前实现中未使用消息内容)。
@OnClose 方法:当WebSocket连接关闭时调用,从map中移除连接。
sendMsg 方法:用于向特定客户端或所有客户端发送消息。
ReviewController@RestController@RequestMapping("review"):定义了一个REST控制器,并指定了基础URL路径。
saveReview 方法:提供了一个RESTful API,用于模拟用户提交评论,并通过WebSocket向特定客户端发送通知。
前端页面
JavaScript代码使用new WebSocket("ws://localhost:8080/app/testWebSocket/"+clientID)WebSocket服务端建立连接。
定义了onopen、onmessage和onclose事件处理器来处理WebSocket事件。
Maven POM文件
定义了Spring Boot的父POM和项目的基本信息。
添加了必要的依赖,如spring-boot-starter-websocket、spring-boot-starter-web等。
配置了Maven构建插件。

index.html


<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
<h2>Home Page</h2><div id="content"></div><script>$(function (){let ws ;if('WebSocket' in window){console.log("this broswer is  support websocket.")let clientID = Math.ceil(Math.random()*100);<!-- build webscoket to server  -->ws = new WebSocket("ws://localhost:8080/app/testWebSocket/"+clientID);ws.onopen = function (){$("#content").append("client id= "+clientID +"has connect to server")}// receive message from serverws.onmessage = function (event){var message = event.data;$("#content").append("<br>");$("#content").append("client id= "+clientID +"receive message from server, content is :" + message)}ws.onclose = function (){console.log("client id= "+clientID +"has closed, disconnect to server")}}else{console.log("this browser is not support websocket.")}})</script>
</body>
</html>

application.yaml


server:servlet:context-path: /app

pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>websocket</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>websocket</name><description>websocket</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

相关文章:

001 websocket(评论功能demo)(消息推送)

文章目录 ReviewController.javaWebSocketConfig.javaWebSocketProcess.javaServletInitializer.javaWebsocketApplication.javareadmeindex.htmlapplication.yamlpom.xml ReviewController.java package com.example.controller;import com.example.websocket.WebSocketProces…...

二分查找向下取整导致的死循环69. x 的平方根

二分查找向下取整导致的死循环 考虑伪题目&#xff1a;从数组arr中查找出目标元素target对应的下标&#xff0c;如果数组中不存在目标元素&#xff0c;找 到第一个元素值小于target的元素的下标。 编写二分查找算法如下&#xff1a; Testvoid testBinarySearch(){int[] arr n…...

Kivy 异步任务

如果要进行一些非常耗时的操作(例如&#xff1a;爬虫等)&#xff0c;那么页面就会在这里卡住&#xff0c;而系统就会以为这个软件无响应&#xff0c;并提示关闭&#xff0c;可以说明用户体验极差&#xff0c;因此我们在此处引入异步操作。 在py中引入事件调节器&#xff0c;并在…...

DEV--C++小游戏(吃星星(0.1))

目录 吃星星&#xff08;0.1&#xff09; 简介 头文件 命名空间变量 副函数 清屏函数 打印地图函数 移动函数 主函数 0.1版完整代码 吃星星&#xff08;0.1&#xff09; 注&#xff1a;版本<1为未实现或只实现部分 简介 用wasd去吃‘*’ 头文件 #include<bi…...

LINUX 入门 4

LINUX 入门 4 day6 7 20240429 20240504 耗时&#xff1a;240min 课程链接地址 第4章 LINUX环境编程——实现线程池 C基础 第3节 #define里面的行不能乱空行&#xff0c;要换行就打\ typedef 是 C 和 C 中的一个关键字&#xff0c;用于为已有的数据类型定义一个新的名字。…...

Imagine Flash、StyleMamba 、FlexControl、Multi-Scene T2V、TexControl

本文首发于公众号&#xff1a;机器感知 Imagine Flash、StyleMamba 、FlexControl、Multi-Scene T2V、TexControl You Only Cache Once: Decoder-Decoder Architectures for Language Models We introduce a decoder-decoder architecture, YOCO, for large language models, …...

Java Collections.emptyList() 方法详解

前言 在Java开发的日常中&#xff0c;我们常常需要处理集合数据结构&#xff0c;而这其中就免不了要面对“空集合”的场景。传统的做法可能是直接返回 null&#xff0c;但这往往会引入空指针异常的风险&#xff0c;降低了代码的健壮性。幸运的是&#xff0c;Java为我们提供了一…...

Vue前端环境准备

vue-cli Vue-cli是Vue官方提供的脚手架&#xff0c;用于快速生成一个Vue项目模板 提供功能&#xff1a; 统一的目录结构 本地调试 热部署 单元测试 集成打包上线 依赖环境&#xff1a;NodeJs 安装NodeJs与Vue-Cli 1、安装nodejs&#xff08;已经安装就不用了&#xff09; node-…...

代码随想录算法训练营第四十二天| 01背包问题(二维、一维)、416.分割等和子集

系列文章目录 目录 系列文章目录动态规划&#xff1a;01背包理论基础①二维数组②一维数组&#xff08;滚动数组&#xff09; 416. 分割等和子集①回溯法&#xff08;超时&#xff09;②动态规划&#xff08;01背包&#xff09;未剪枝版剪枝版 动态规划&#xff1a;01背包理论基…...

故障——蓝桥杯十三届2022国赛大学B组真题

问题分析 这道题纯数学&#xff0c;考察贝叶斯公式 AC_Code #include <bits/stdc.h> using namespace std; typedef pair<int,double> PI; bool cmp(PI a,PI b){if(a.second!b.second)return a.second>b.second;return a.first<b.first; } int main() {i…...

SSD存储基本知识

存储技术随着时间的推移经历了显著变化&#xff0c;新兴的存储介质正逐步挑战已经成为行业标准的硬盘驱动器&#xff08;HDD&#xff09;。在众多竞争者中&#xff0c;固态硬盘&#xff08;SSD&#xff09;是最广泛采用且最有潜力占据主导地位的——它们速度快、运行安静&#…...

buuctf-misc题目练习二

ningen 打开题目后是一张图片&#xff0c;放进winhex里面 发现PK&#xff0c;PK是压缩包ZIP 文件的文件头&#xff0c;下一步是想办法进行分离 Foremost可以依据文件内的文件头和文件尾对一个文件进行分离&#xff0c;或者识别当前的文件是什么文件。比如拓展名被删除、被附加…...

Nginx rewrite项目练习

Nginx rewrite练习 1、访问ip/xcz&#xff0c;返回400状态码&#xff0c;要求用rewrite匹配/xcz a、访问/xcz返回400 b、访问/hello时正常访问xcz.html页面server {listen 192.168.99.137:80;server_name 192.168.99.137;charset utf-8;root /var/www/html;location / {root …...

2024,AI手机“元年”? | 最新快讯

文 | 伯虎财经&#xff0c;作者 | 铁观音 2024年&#xff0c;小米、荣耀、vivo、一加、努比亚等品牌的AI手机新品如雨后春笋般涌现。因此&#xff0c;这一年也被业界广泛视为AI手机的“元年” 试想&#xff0c;当你轻触屏幕&#xff0c;你的手机不仅响应你的指令&#xff0c;更…...

5月9(信息差)

&#x1f30d; 可再生能源发电量首次占全球电力供应的三成 &#x1f384;马斯克脑机接口公司 Neuralink 计划将 Link 功能扩展至现实世界&#xff0c;实现控制机械臂、轮椅等 马斯克脑机接口公司 Neuralink 计划将 Link 功能扩展至现实世界&#xff0c;实现控制机械臂、轮椅等…...

leetcode203-Remove Linked List Elements

题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&…...

2024付费进群系统,源码及搭建变现视频课程(教程+源码)

自从我做资源站项目盈利稳定后&#xff0c;我越来越对网站类项目感兴趣了&#xff0c;毕竟很多网站类项目还是需要一定技术门槛的&#xff0c;可以过滤掉一些人&#xff0c;很多新人做项目就只盯着短视频&#xff0c;所以网站类项目也就没那么的卷。 这个付费进群系统&#xf…...

深入理解Django:中间件与信号处理的艺术

title: 深入理解Django&#xff1a;中间件与信号处理的艺术 date: 2024/5/9 18:41:21 updated: 2024/5/9 18:41:21 categories: 后端开发 tags: Django中间件信号异步性能缓存多语言 引言 在当今的Web开发领域&#xff0c;Django以其强大的功能、简洁的代码结构和高度的可扩…...

rk3588局域网推流

最近无意间看见在网上有使用MediaMtx插件配合ffmpeg在Windows来进行推流&#xff0c;然后在使用其他软件进行拉流显示数据图像的&#xff0c;既然windows都可以使用 &#xff0c;我想linux应该也可以&#xff0c;正好手上也有一块RK3588的开发板&#xff0c;就测试了一下&#…...

Android虚拟机机制

目录 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09;二、Android dex、odex、oat、vdex、art区别 一、Android 虚拟机 dalvik/art&#xff08;6版本后&#xff09; 每个应用都在其自己的进程中运行&#xff0c;都有自己的虚拟机实例。ART通过执行DEX文件可在设…...

【触摸案例-手势解锁案例-按钮高亮 Objective-C语言】

一、我们来说这个self.btns,这个问题啊,为什么不用_btns, 1.我们说,在懒加载里边儿,经常是写下划线啊,_btns,为什么不写,首先啊,这个layoutSubviews:我们第一次,肯定会去执行这个layoutSubviews: 然后呢,去懒加载这个数组, 然后呢,接下来啊,走这一句话, 第一次…...

ChatPPT开启高效办公新时代,AI赋能PPT创作

目录 一、前言二、ChatPPT的几种用法1、通过在线生成2、通过插件生成演讲者模式最终成品遇到问题改进建议 三、ChatPPT其他功能 一、前言 想想以前啊&#xff0c;为了做个PPT&#xff0c;我得去网上找各种模板&#xff0c;有时候还得在某宝上花钱买。结果一做PPT&#xff0c;经…...

【C语言项目】贪吃蛇(上)

个人主页 ~ gitee仓库~ 欢迎大家来到C语言系列的最后一个篇章–贪吃蛇游戏的实现&#xff0c;当我们实现了贪吃蛇之后&#xff0c;我们的C语言就算是登堂入室了&#xff0c;基本会使用了&#xff0c;当然&#xff0c;想要更加熟练地使用还需要多多练习 贪吃蛇 一、目标二、需要…...

LeNet-5上手敲代码

LeNet-5 LeNet-5由Yann LeCun在1998年提出&#xff0c;旨在解决手写数字识别问题&#xff0c;被认为是卷积神经网络的开创性工作之一。该网络是第一个被广泛应用于数字图像识别的神经网络之一&#xff0c;也是深度学习领域的里程碑之一。 LeNet-5的整体架构&#xff1a; 总体…...

javaWeb入门(自用)

1. vue学习 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"https://unpkg.com/vue2"></script> </head> <body><div id"…...

web3风格的网页怎么设计?分享几个,找找感觉。

web3风格的网站是指基于区块链技术和去中心化理念的网站设计风格。这种设计风格强调开放性、透明性和用户自治&#xff0c;体现了Web3的核心价值观。 以下是一些常见的Web3风格网站设计元素&#xff1a; 去中心化标志&#xff1a;在网站的设计中使用去中心化的标志&#xff0…...

ASP.NET MVC(-)表单的提交、获取表单数据

FromCollection 方式...

[AIGC] 《MyBatis-Plus 结合 Spring Boot 的动态数据源介绍及 Demo 演示》

在现代的 Web 应用开发中&#xff0c;Spring Boot 已经成为了一种流行的框架选择。而 MyBatis-Plus 则为 MyBatis 框架提供了更强大的功能和便利。当它们结合使用时&#xff0c;动态数据源的运用变得更加简单和高效。 动态数据源的概念允许我们在运行时根据不同的条件或需求选…...

【华为OD机试C卷D卷】部门人力分配(C++/Java/Python)

【华为OD机试】-(A卷+B卷+C卷+D卷)-2024真题合集目录 【华为OD机试】-(C卷+D卷)-2024最新真题目录 题目描述 部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。 这部…...

毕业设计:《基于 Prometheus 和 ELK 的基础平台监控系统设计与实现》

前言 《基于 Prometheus 和 ELK 的基础平台监控系统设计与实现》&#xff0c;这是我在本科阶段的毕业设计&#xff0c;通过引入 Prometheus 和 ELK 架构实现企业对指标与日志的全方位监控。并且基于云原生&#xff0c;使用容器化持续集成部署的开发方式&#xff0c;通过 Sprin…...

在人才网站做业务/东莞推广服务

迭代器 __iter__() 获取迭代器 __next__() 下一个 生成器 本质就是迭代器 两种方式写生成器 1. 生成器函数 2. 生成器表达式 生成器函数 函数内部有yield. yield返回 -> return yield可以把函数分段执行 生成器函数被调用的时候. 返回生成器 def func(): yield g func() —…...

网站留言板作用/如何在网站上推广自己的产品

2019独角兽企业重金招聘Python工程师标准>>> ECShop商城自带众多购物便利功能&#xff0c;如促销&#xff0c;团购&#xff0c;拍卖&#xff0c;红包&#xff0c;专题&#xff0c;祝福贺卡等等...但是对做外贸网站的商家而言就必不可少了--多国货币功能的实现。当你…...

电商详情做的最好看的网站/seo是什么意思广东话

导读作者&#xff1a;Sveta Smirnova翻译&#xff1a;郑志江校对&#xff1a;徐晨亮原文 &#xff1a;MySQL Memory Management, Memory Allocators and Operating System本文涉及链接在文末展示When users experience memory usage issues with any software, including MySQL…...

wordpress成员资格/seo营销技巧培训班

动画 Android系统框架提供了两种动画系统&#xff1a;属性动画和View动画。属性动画更加灵活&#xff0c;可以提供更多特性&#xff0c;因而优先选择属性动画。除了这两个&#xff0c;还有Drawable动画&#xff0c;它可以加载图片资源&#xff0c;一张一张地展示。 属性动画 …...

网站做自签发证书/专业网站优化

作者: _陈哈哈 来源: blog.csdn.net/qq_39390545/article/details/107020686Part1前言BATJTMD等大厂的面试难度越来越高&#xff0c;但无论从大厂还是到小公司&#xff0c;一直未变的一个重点就是对SQL优化经验的考察。一提到数据库&#xff0c;先“说一说你对SQL优化的见解吧&…...

石家庄市建设局质监站网站/网络站点推广的方法有哪些

前言 在SpringBoot中使用自定义注解、aop切面打印web请求日志。主要是想把controller的每个request请求日志收集起来&#xff0c;调用接口、执行时间、返回值这几个重要的信息存储到数据库里&#xff0c;然后可以使用火焰图统计接口调用时长&#xff0c;平均响应时长&am…...