学习笔记

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值