1.Java
1.1:java基础
1.1.1:java的环境变量
2.1:Thread
2.1.1ThreadPool
Java通过Executors提供四种线程池,分别为:
1、newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
2、newFixedThreadPool
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool
创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
// 1秒后执行一次性任务:
ses.schedule(new Task("one-time"), 1, TimeUnit.SECONDS);
如果任务以固定的每3秒执行,我们可以这样写:
// 2秒后开始执行定时任务,每3秒执行:
ses.scheduleAtFixedRate(new Task("fixed-rate"), 2, 3, TimeUnit.SECONDS);
如果任务以固定的3秒为间隔执行,我们可以这样写:
// 2秒后开始执行定时任务,以3秒为间隔执行:
ses.scheduleWithFixedDelay(new Task("fixed-delay"), 2, 3, TimeUnit.SECONDS);
4、newCachedThreadPoo
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2.2线程同步类
位于并发包:import java.util.concurrent
CyclicBarrier
CountDownLatch
2.3为什么volatile关键字保证不了线程安全
https://www.baidu.com/link?url=Nw9F04CWme4shk8hDS_64BLSlkO8WEiKwsCYx9FcVdiCifTnmQFefZ66hajjg24S5cHMbiqcUO4W-WNGqCdiqoVVcS1OlSx75YM5ry0u6gy&wd=&eqid=eebfb77f00003439000000065f30b7e8
3:Algorithm
4:WebSocket
端点类
@Component
@ServerEndpoint("/websocket/{username}")
class UserSocket {
private val log = LoggerFactory.getLogger(UserSocket::class.java)
private lateinit var session: Session
private lateinit var username: String
object static {
var onlineNumber = 0
val clients = ConcurrentHashMap<String, UserSocket>()
}
@OnOpen
fun open(@PathParam("username") username: String, session: Session) {
if (username in static.clients.keys) {
log.error("有多个相同的用户连接!")
session.close()
return
}
static.onlineNumber++
log.info("欢迎您 -> $username")
this.session = session
this.username = username
static.clients[username] = this
println("当前在线人数: ${static.clients.size}")
static.onlineNumber = static.clients.size
}
@OnError
fun error(session: Session, error: Throwable) {
Console.error(error.message)
}
@OnClose
fun onClose() {
//webSockets.remove(this);
try {
static.clients.remove(username);
static.onlineNumber--;
} catch (e: Exception) {
log.error("有连接强制关闭!")
}
log.error("有连接关闭! 当前在线人数" + static.onlineNumber);
}
@OnMessage
fun message(message: String, session: Session) {
println(message)
Console.log(JSONUtil.parse(message).toBean(SocketMessage::class.java))
static.clients.forEach { t: String, u: UserSocket ->
if (u != this)
u.session.basicRemote.sendText(message)
}
}
}
配置类
@Configuration
class WebSocketConfig {
@Bean
fun userSocket() = UserSocket()
@Bean
fun serverEndpointExporter(): ServerEndpointExporter? {
return ServerEndpointExporter()
}
}
5:Stream
2.Android
2.1自定义广播
广播类
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) =
Toast.makeText(context, "自定义广播", Toast.LENGTH_SHORT).show()
}
静态注册广播 (该广播接收器监听一个名为 com.jiayou.OK_HTTP 的广播)
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.jiayou.OK_HTTP" />
</intent-filter>
</receiver>
声明权限
<uses-permission android:name="com.jiayou.OK_HTTP" />
<permission android:name="com.jiayou.OK_HTTP" android:protectionLevel="signature"/>
发送广播
sendBroadcast(Intent("com.jiayou.OK_HTTP"), "com.jiayou.OK_HTTP")
2.2有序广播
在intent-filter节点新增了个android:priority属性,该值越大,越先接收广播
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.jiayou.OK_HTTP" />
</intent-filter>
</receiver>
发送有序广播
sendOrderedBroadcast(Intent("com.jiayou.OK_HTTP"), null)
截断广播
abortBroadcast()
2.3运行时权限
声明权限
<uses-permission android:name="android.permission.CALL_PHONE" />
gradle引入permissionx依赖
implementation 'com.permissionx.guolindev:permissionx:1.1.1'
PermissionX.init(this)
.permissions(android.Manifest.permission.CALL_PHONE)
.request { allGranted, _, _ ->
if (allGranted) {
try {
val intent = Intent(Intent.ACTION_CALL)
intent.data = Uri.parse("tel:10086")
startActivity(intent)
} catch (e: SecurityException) {
e.printStackTrace()
}
} else {
Toast.makeText(this, "您拒绝了拨打电话权限", Toast.LENGTH_SHORT).show()
}
}
2.4通知
val systemService = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
systemService.createNotificationChannel(NotificationChannel("myid", "myname", NotificationManager.IMPORTANCE_HIGH))
val autoCancel = NotificationCompat.Builder(applicationContext, "myid")
.setContentTitle("下载提醒")
.setSubText("收到一条消息")
.setSmallIcon(R.drawable.head)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
val notificationManager = NotificationManagerCompat.from(applicationContext);
notificationManager.notify(100, autoCancel.build());
2.5Snackbar
<androidx.coordinatorlayout.widget.CoordinatorLayout app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/coor"
android:layout_width="match_parent"
android:layout_height="wrap_content"></androidx.coordinatorlayout.widget.CoordinatorLayout>
Snackbar.make(coor, "收到新的消息!", Snackbar.LENGTH_INDEFINITE).setAction("点击") { Toast.makeText(applicationContext, "dad", Toast.LENGTH_LONG).show()}.show()
Snackbar配合CoordinatorLayout可以在超时之前滑动删除
3.Linux
3.1常用命令
进程查看: ps -ef | grep xxxx
某个端口:netstat -lnp | grep xxxx
4.MQ
4.1:RabbitMq
POM
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
交换机绑定
@Configuration
public class DirectRabbitConfig {
//队列 起名:TestDirectQueue
@Bean
public Queue TestDirectQueue() {
return new Queue("TestDirectQueue",true); //true 是否持久
}
//队列 起名:TestDirectQueue1
@Bean
public Queue TestDirectQueue1() {
return new Queue("TestDirectQueue1",true);
}
//Direct交换机 起名:TestDirectExchange
@Bean
DirectExchange TestDirectExchange() {
return new DirectExchange("TestDirectExchange");
}
//绑定 将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
@Bean
Binding bindingDirect() {
return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
}
@Bean
Binding bindingDirect1() {
return BindingBuilder.bind(TestDirectQueue1()).to(TestDirectExchange()).with("TestDirectRouting1");
}
}
消息确认
@Configuration
public class RabbitConfig {
@Bean
public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory){
RabbitTemplate rabbitTemplate = new RabbitTemplate();
rabbitTemplate.setConnectionFactory(connectionFactory);
//设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
rabbitTemplate.setMandatory(true);
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println("ConfirmCallback: "+"相关数据:"+correlationData);
System.out.println("ConfirmCallback: "+"确认情况:"+ack);
System.out.println("ConfirmCallback: "+"原因:"+cause);
}
});
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("ReturnCallback: "+"消息:"+message);
System.out.println("ReturnCallback: "+"回应码:"+replyCode);
System.out.println("ReturnCallback: "+"回应信息:"+replyText);
System.out.println("ReturnCallback: "+"交换机:"+exchange);
System.out.println("ReturnCallback: "+"路由键:"+routingKey);
}
});
return rabbitTemplate;
}
}
配置
spring:
application:
name: rabbitmq-provider
rabbitmq:
host: jiayou.art
port: 5672
username: lishuang
password: jiayou0000
virtual-host: /
#确认消息已发送到交换机(Exchange)
#确认消息已发送到队列(Queue)
publisher-returns: true
publisher-confirm-type: correlated
4.2:kafka
4.3:ActiveMq
5.DateBase
5.1:Mysql
5.2:Redis
5.2.1:在Kotlin中使用Redis
自定义RedisTemplate的序列化data实体类应该加上空构造函数
5.2.2Redis发布订阅模型实现(SpringBoot)
发布者:
@Component
public class RedisSubscriber extends MessageListenerAdapter {
@Autowired
private RedisTemplate<String, User> redisTemplate;
@Override
public void onMessage(Message message, byte[] bytes) {
System.out.println(message);
byte[] body = message.getBody();
byte[] channel = message.getChannel();
String msg = redisTemplate.getStringSerializer().deserialize(body);
String topic = redisTemplate.getStringSerializer().deserialize(channel);
User user = new JSONObject(msg).toBean(User.class);
System.out.println(user);
System.out.println("监听到topic为" + topic + "的消息:" + msg);
}
}
订阅者:
@RestController
public class SampleController {
@Autowired
private RedisTemplate<String, User> redisTemplate;
@GetMapping("/send1")
String send1(String data) {
redisTemplate.convertAndSend("testkafka", new User("lishuang", "jiayou0000", new Date()));
return "success";
}
}
发布-订阅
@Configuration
public class Redis {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("testkafka"));
container.addMessageListener(listenerAdapter, new PatternTopic("testkafka1"));//配置要订阅的订阅项
return container;
}
}
6.Kotlin
6.1协程
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.3.7</version>
</dependency>
6.2反射
在kotlin里被val
修饰的对象不提供set方法!!!
在kotlin里被val
修饰的对象不提供set方法!!!
在kotlin里被val
修饰的对象不提供set方法!!!
6.3集合
subtract 补集
7.Opencv
img = cv2.imread(r"D:\p\1.jpg", cv2.IMREAD_GRAYSCALE) #灰度图
cv2.imshow("aoligei", img)
cv2.waitKey(0)
8.Vue
8.1Class绑定
一般语法
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
**计算属性,**这是一个常用且强大的模式:
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
数组:
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
渲染为:
<div class="active text-danger"></div>
如果你也想根据条件切换列表中的 class,可以用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
这样写将始终添加 errorClass
,但是只有在 isActive
是 truthy[1] 时才添加 activeClass
。
不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
8.2Style绑定
一般用法
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
或
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
数组
v-bind:style
的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
8.3Axios跨域
与package.json同级目录新增vue.config.js文件,内容配置如下
module.exports = {
devServer: {
proxy:"http://192.168.1.102:8888", //后端地址
port: 8080 //前台项目启动端口
}
}
axios配置:
Vue.prototype.$axios = axios
请求例子:
var file = this.file
const data = new FormData();
data.append('file', file);
this.$axios.post('/rec',data, {
headers: {
'content-type': 'multipart/form-data'
}
})
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
9.Oauth2
9.1Oauth2 + Redis
认证服务器
Maven:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
安全配置
@EnableWebSecurity
open class SecurityConfig : WebSecurityConfigurerAdapter() {
@Autowired
private lateinit var failHandler: FailHandler
@Autowired
private lateinit var successHandler: SuccessHandler
@Autowired
private lateinit var authFilter: AuthFilter
@Autowired
private lateinit var moreSessionHandler: MoreSessionHandler
@Bean
override fun authenticationManagerBean(): AuthenticationManager {
return super.authenticationManagerBean()
}
@Bean
open fun passwordEncoder(): PasswordEncoder {
return BCryptPasswordEncoder()
}
override fun configure(http: HttpSecurity) {
http.csrf().disable()
http.authorizeRequests().antMatchers("/oauth/*").permitAll().anyRequest().authenticated()
http.formLogin().successHandler(successHandler).failureHandler(failHandler)
http.addFilterBefore(authFilter, UsernamePasswordAuthenticationFilter::class.java)
http.sessionManagement {
it.maximumSessions(1).expiredSessionStrategy(moreSessionHandler)
}
}
override fun configure(auth: AuthenticationManagerBuilder) {
auth.inMemoryAuthentication().withUser("lishuang").password(passwordEncoder().encode("jiayou0000")).roles("admin")
}
override fun configure(web: WebSecurity) {
web.ignoring().antMatchers("/oauth/check_token")
}
}
认证配置
@Configuration
open class Oauth2Config {
@Configuration
@EnableAuthorizationServer
open class AuthServer : AuthorizationServerConfigurerAdapter() {
@Autowired
private lateinit var authenticationManager: AuthenticationManager
@Autowired
private lateinit var redisConnectionFactory: RedisConnectionFactory
@Autowired
private lateinit var passwordEncoder: PasswordEncoder
@Bean
open fun redisTokenStore() = RedisTokenStore(redisConnectionFactory)
@Bean
open fun authorizationServerTokenServices(): AuthorizationServerTokenServices? {
val defaultTokenServices = DefaultTokenServices()
defaultTokenServices.setTokenStore(redisTokenStore())
defaultTokenServices.setSupportRefreshToken(true)
defaultTokenServices.setReuseRefreshToken(true)
defaultTokenServices.setAccessTokenValiditySeconds(600)
defaultTokenServices.setRefreshTokenValiditySeconds(60 * 10)
return defaultTokenServices
}
override fun configure(clients: ClientDetailsServiceConfigurer) {
clients.inMemory().withClient("client-a")
.secret(passwordEncoder.encode("client-a-secret"))
.redirectUris("http://localhost:9001/callback")
//支持 授权码、密码两种授权模式,支持刷新token功能
.authorizedGrantTypes("authorization_code", "password", "refresh_token");
}
override fun configure(endpoints: AuthorizationServerEndpointsConfigurer) {
endpoints
.tokenStore(RedisTokenStore(redisConnectionFactory))
.authenticationManager(authenticationManager)
.tokenServices(authorizationServerTokenServices())
}
override fun configure(security: AuthorizationServerSecurityConfigurer) {
security.allowFormAuthenticationForClients()
//客户端校验token访问许可
.checkTokenAccess("permitAll()")
//客户端token调用许可
.tokenKeyAccess("permitAll()");
}
}
}
yml配置
spring:
application:
name: oauth2-auth
redis:
client-name: lishuang
password: jiayou0000
host: jiayou.art
port: 8003
资源服务器
maven
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
资源配置
@Configuration
@EnableResourceServer
open class ResourceServerConfiguration : ResourceServerConfigurerAdapter() {
@Autowired
private lateinit var redisConnectionFactory: RedisConnectionFactory
//存储方式
@Bean
open fun redisTokenStore() = RedisTokenStore(redisConnectionFactory)
override fun configure(http: HttpSecurity) {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.requestMatchers().anyRequest()
.and()
.anonymous()
.and()
.authorizeRequests()
// .antMatchers("/product/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')")
.antMatchers("/**").authenticated();//配置order访问控制,必须认证过后才可以访问
}
override fun configure(resources: ResourceServerSecurityConfigurer) {
resources.stateless(true)
resources.tokenStore(redisTokenStore())
}
}
yml
spring:
redis:
client-name: lishuang
password: jiayou0000
host: jiayou.art
port: 8003
端点
认证端点(POST)密码模式
http://localhost:8000/oauth/token?username=lishuang&password=jiayou0000&grant_type=password&scope=select&client_id=client-a&client_secret=client-a-secret
刷新端点(POST)
http://localhost:8888/auth/oauth/token?grant_type=refresh_token&refresh_token=25cdad60-7741-480c-8ea6-56cd507d4a40&client_id=client-a&client_secret=client-a-secret&scope=select
检测端点(GET)
http://localhost/oauth/check_token?token=f57ce129-2d4d-4bd7-1111-f31ccc69d4d1
9.1Oauth2 + Jwt
10.GateWay
maven
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
路由配置
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #允许通过服务名访问
lower-case-service-id: true #将服务名全转换为小写
routes:
- id: oauth2-resource #唯一ID
uri: lb://resource #地址(微服务名)
predicates: #路由地址
- Path=/**
filters:
- AddRequestHeader=X-Request-Foo, Bar
- StripPrefix=1
- id: oauth2-auth
uri: lb://auth
predicates:
- Path=/**
filters:
- AddRequestHeader=X-Request-Foo, Bar
负载均衡
@Bean
@LoadBalancedopen
fun restTemplate() = RestTemplate()
全局过滤器
@Component
class ServerGatewayFilter : GlobalFilter, Ordered {
override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
Console.log("ServerGatewayFilter filter ")
Console.log(exchange.request.headers)
val serverHttpRequest = exchange.request.mutate().headers {
it.set("username", "lisha")
it.add("username", "lisha")
}.build()
return chain.filter(exchange.mutate().request(serverHttpRequest).build())
}
override fun getOrder() = -200
}
注意
在使用负载均衡的时候,需要加这个注解
@EnableFeignClients
11.Maven
打包插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.jiayou.kantu.KantuKt</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
12.SpringBoot
扫描非主类的包和其子包下的Bean
实现ImportSelector接口,把要扫描的类的包名添加到数组
class AutoConfigurationor : ImportSelector {
override fun selectImports(importingClassMetadata: AnnotationMetadata) = arrayOf("com.anther.HelloService")
override fun getExclusionFilter(): Predicate<String>? {
return super.getExclusionFilter()
}
}
在主程序加上@Import注解
@SpringBootApplication
@Import(AutoConfigurationor::class)
class AutoconfigurationTestApplication
自定义Starter的Yml提示依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
统一异常定制
@Configuration
class BeanConfig {
@Bean
fun webServerFactoryCustomizer(): WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
return WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
it.addErrorPages(ErrorPage(HttpStatus.NOT_FOUND, "/not_find"))
}
}
}
13.Hutool
金额大小写转换
Convert.digitToChinese(10.10); //壹拾元壹角
文件上传
HashMap<String, Object> paramMap = new HashMap<>();
//文件上传只需将参数中的键指定(默认file),值设为文件对象即可,对于使用者来说,文件上传与普通表单提交并无区别
paramMap.put("file", FileUtil.file("D:\\face.jpg"));
String result= HttpUtil.post("https://www.baidu.com", paramMap);
14.Dubbo-SpringBoot
maven
<dependencies>
<!-- 公共接口-->
<dependency>
<groupId>com.jiayou</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.3</version>
</dependency>
<!-- 连接Nacos-->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
公共接口
interface TestService {
fun ins()
fun del()
fun upd()
fun sel()
}
服务提供者
@Service(version = "1.0.0", interfaceClass = TestService.class)
public class TestServiceImpl implements TestService {
@Override
public void ins() {
System.out.println("insert");
}
@Override
public void del() {
System.out.println("delete");
}
@Override
public void upd() {
System.out.println("update");
}
@Override
public void sel() {
System.out.println("select");
}
}
yml
dubbo:
application:
name: dubbo_provider
protocol:
name: dubbo
port: 20880 #netty监听地址
registry:
address: nacos://127.0.0.1:8848 #注册中心地址
protocol: nacos #协议类型
scan:
base-packages: com.jiayou #扫描业务类
server:
port: 8081
spring:
application:
name: dubbo_auto_configuration_provider_demo
服务消费者
@RestController
public class TestController {
//注入对象,跨服调用
@Reference(version = "1.0.0")
private TestService testServiceImpl;
//注入对象,跨服调用
@Reference(version = "1.0.0")
private HelloService helloService;
@RequestMapping("/ins")
public String ins() {
testServiceImpl.ins();
return "ins";
}
@RequestMapping("/del")
public String del() {
helloService.hello();
testServiceImpl.del();
return "del";
}
@RequestMapping("/upd")
public String upd() {
testServiceImpl.upd();
return "upd";
}
@RequestMapping("/sel")
public String sel() {
testServiceImpl.sel();
return "sel";
}
}
yml
dubbo:
application:
name: dubbo_consumer
protocol:
name: consumer
port: 20881
registry:
address: nacos://127.0.0.1:8848
protocol: nacos
server:
port: 8888
15.Spring Framework
循环依赖
https://blog.csdn.net/u010853261/article/details/77940767