优秀开源项目解读(六

news2024/11/17 19:35:30

一、Piggy Metrics介绍

PiggyMetrics是一个模拟的个人记账理财的应用,原作者称其为一个端到端的微服务PoC(Proof of Concept),也就是说他开发这个是为了验证微服务架构和Spring Cloud技术栈。PiggyMetrics目前在github上有超过12k星,是学习微服务架构和Spring Cloud技术栈的一个不错参考。

项目工程结构

│  
├─account-service # 账户服务
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      ├─main
│      │  ├─java
│      │  │  └─com
│      │  │      └─piggymetrics
│      │  │          └─account
│      │  │              │  AccountApplication.java
│      │  │              ├─client
│      │  │              │      AuthServiceClient.java
│      │  │              │      StatisticsServiceClient.java
│      │  │              │      StatisticsServiceClientFallback.java
│      │  │              ├─config
│      │  │              │      ResourceServerConfig.java
│      │  │              │      
│      │  │              ├─controller
│      │  │              │      AccountController.java
│      │  │              │      ErrorHandler.java
│      │  │              │      
│      │  │              ├─domain
│      │  │              │      Account.java
│      │  │              │      Currency.java
│      │  │              │      Item.java
│      │  │              │      Saving.java
│      │  │              │      TimePeriod.java
│      │  │              │      User.java
│      │  │              │      
│      │  │              ├─repository
│      │  │              │      AccountRepository.java  
│      │  │              └─service
│      │  │                  │  AccountService.java
│      │  │                  │  AccountServiceImpl.java
│      │  │                  │  
│      │  │                  └─security
│      │  │                          CustomUserInfoTokenServices.java
│      │  │                          
│      │  └─resources
│      │          bootstrap.yml
│                  
├─auth-service # 授权认证服务
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      ├─main
│      │  ├─java
│      │  │  └─com
│      │  │      └─piggymetrics
│      │  │          └─auth
│      │  │              │  AuthApplication.java
│      │  │              ├─config
│      │  │              │      OAuth2AuthorizationConfig.java
│      │  │              │      WebSecurityConfig.java  
│      │  │              ├─controller
│      │  │              │      UserController.java   
│      │  │              ├─domain
│      │  │              │      User.java
│      │  │              ├─repository
│      │  │              │      UserRepository.java    
│      │  │              └─service
│      │  │                  │  UserService.java
│      │  │                  │  UserServiceImpl.java
│      │  │                  └─security
│      │  │                          MongoUserDetailsService.java
│      │  │                          
│      │  └─resources
│      │          bootstrap.yml
│      │          
│      └─              
├─config # 配置中心
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      └─main
│          ├─java
│          │  └─com
│          │      └─piggymetrics
│          │          └─config
│          │                  ConfigApplication.java
│          │                  SecurityConfig.java
│          │                  
│          └─resources
│              │  application.yml
│              │  
│              └─shared
│                      account-service.yml
│                      application.yml
│                      auth-service.yml
│                      gateway.yml
│                      monitoring.yml
│                      notification-service.yml
│                      registry.yml
│                      statistics-service.yml
│                      turbine-stream-service.yml
│                      
├─gateway # API网关
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      ├─main
│      │  ├─java
│      │  │  └─com
│      │  │      └─piggymetrics
│      │  │          └─gateway
│      │  │                  GatewayApplication.java
│      │  │                  
│      │  └─resources
│          
├─monitoring
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      ├─main
│      │  ├─java
│      │  │  └─com
│      │  │      └─piggymetrics
│      │  │          └─monitoring
│      │  │                  MonitoringApplication.java
│      │  │                  
│      │  └─resources
│      │          bootstrap.yml
│      │          
│      └─test
│          ├─java
│          │  └─com
│          │      └─piggymetrics
│          │          └─monitoring
│          │                  MonitoringApplicationTests.java
│          │                  
│          └─resources
│                  bootstrap.yml
│                  
├─notification-service # 通知服务
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      ├─main
│      │  ├─java
│      │  │  └─com
│      │  │      └─piggymetrics
│      │  │          └─notification
│      │  │              │  NotificationServiceApplication.java
│      │  │              │  
│      │  │              ├─client
│      │  │              │      AccountServiceClient.java
│      │  │              │      
│      │  │              ├─config
│      │  │              │      ResourceServerConfig.java
│      │  │              │      
│      │  │              ├─controller
│      │  │              │      RecipientController.java
│      │  │              │      
│      │  │              ├─domain
│      │  │              │      Frequency.java
│      │  │              │      NotificationSettings.java
│      │  │              │      NotificationType.java
│      │  │              │      Recipient.java
│      │  │              │      
│      │  │              ├─repository
│      │  │              │  │  RecipientRepository.java
│      │  │              │  │  
│      │  │              │  └─converter
│      │  │              │          FrequencyReaderConverter.java
│      │  │              │          FrequencyWriterConverter.java
│      │  │              │          
│      │  │              └─service
│      │  │                      EmailService.java
│      │  │                      EmailServiceImpl.java
│      │  │                      NotificationService.java
│      │  │                      NotificationServiceImpl.java
│      │  │                      RecipientService.java
│      │  │                      RecipientServiceImpl.java
│      │  │                      
│      │  └─resources
│      │          bootstrap.yml
│      │          
├─registry # 注册服务
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      └─main
│          ├─java
│          │  └─com
│          │      └─piggymetrics
│          │          └─registry
│          │                  RegistryApplication.java
│          │                  
│          └─resources
│                  bootstrap.yml
│                  
├─statistics-service # 统计服务
│  │  Dockerfile
│  │  pom.xml
│  │  
│  └─src
│      ├─main
│      │  ├─java
│      │  │  └─com
│      │  │      └─piggymetrics
│      │  │          └─statistics
│      │  │              │  StatisticsApplication.java
│      │  │              │  
│      │  │              ├─client
│      │  │              │      ExchangeRatesClient.java
│      │  │              │      ExchangeRatesClientFallback.java
│      │  │              │      
│      │  │              ├─config
│      │  │              │      ResourceServerConfig.java
│      │  │              │      
│      │  │              ├─controller
│      │  │              │      StatisticsController.java
│      │  │              │      
│      │  │              ├─domain
│      │  │              │  │  Account.java
│      │  │              │  │  Currency.java
│      │  │              │  │  ExchangeRatesContainer.java
│      │  │              │  │  Item.java
│      │  │              │  │  Saving.java
│      │  │              │  │  TimePeriod.java
│      │  │              │  │  
│      │  │              │  └─timeseries
│      │  │              │          DataPoint.java
│      │  │              │          DataPointId.java
│      │  │              │          ItemMetric.java
│      │  │              │          StatisticMetric.java
│      │  │              │          
│      │  │              ├─repository
│      │  │              │  │  DataPointRepository.java
│      │  │              │  │  
│      │  │              │  └─converter
│      │  │              │          DataPointIdReaderConverter.java
│      │  │              │          DataPointIdWriterConverter.java
│      │  │              │          
│      │  │              └─service
│      │  │                  │  ExchangeRatesService.java
│      │  │                  │  ExchangeRatesServiceImpl.java
│      │  │                  │  StatisticsService.java
│      │  │                  │  StatisticsServiceImpl.java
│      │  │                  │  
│      │  │                  └─security
│      │  │                          CustomUserInfoTokenServices.java
│      │  │                          
│      │  └─resources
│      │          bootstrap.yml
│                  
└─turbine-stream-service # turbine流服务
    │  Dockerfile
    │  pom.xml
    │  
    └─src
        ├─main
        │  ├─java
        │  │  └─com
        │  │      └─piggymetrics
        │  │          └─turbine
        │  │                  TurbineStreamServiceApplication.java
        │  │                  
        │  └─resources
        │          bootstrap.yml         
        └─
复制代码

二、Piggy Metrics服务拆分

技术栈技术栈选型
API网关Spring Cloud Zuul
负载均衡Eurake+Ribbon
远程调用Feign
限流熔断Hystrix
服务注册与发现Spring Cloud Eurake
授权认证Spring Cloud OAuth2
配置中心Spring Cloud Config&&Apollo
分布式调用链监控Spring Cloud Sleuth
链路追踪Zipkin
消息队列RabbitMQ
日志监控ELK

三、Piggy Metrics业架构设计

目前PiggMetrics采用前后分离架构,前端是单页SPA,后端采用基于Spring Cloud技术栈的微服务架构。

3.1 业务服务架构

Piggy Metrics项目主要有三个服务,Account service 账户服务,存储用户账户和记账信息、Statistics service 统计服务,计算用户财务状况和统计信息、Notification service 通知服务,存储通知和备份等相关配置。

3.2 原基础服务架构

  • API网关: 基于Spring Cloud Zuul的网关,是调用后台API的聚合入口,实现反向路由和负载均衡(Eureka+Ribbon)、限流熔断(Hystrix)等功能。CLIENT单页应用和ZUUL网关暂住在一起,简化部署。
  • 服务注册和发现: 基于Spring Cloud Eureka的服务注册中心。业务服务启动时通过Eureka注册,网关调用后台服务通过Eureka做服务发现,服务之间调用也通过Eureka做服务发现。
  • 授权认证服务: 基于Spring Security OAuth2的授权认证中心。客户端登录时通过AUTHSERVICE获取访问令牌(走用户名密码模式)。服务之间调用也通过AUTHSERVICE获取访问令牌(走客户端模式)。令牌校验方式、各资源服务器去AUTHSERVICE集中校验令牌。
  • 配置服务: 基于Spring Cloud Config的配置中心,集中管理所有Spring服务的配置文件。
  • 分布式调用链: 基于Spring Cloud Sleuth的调用链监控。网关调用后台服务,服务之间调用,都采用Zipkin进行埋点和跟踪。
  • 软负载和限流熔断: 基于Spring Cloud Ribbon&HystrixZuul调用后台服务,服务之间相互调用,都通过Ribbon实现软负载,也通过Hystrix实现熔断限流保护。
  • METRICS & DASHBOARD: 基于Spring Cloud Turbine + Hystrix Dashboard,对所有Hystrix产生的Metrics流进行聚合,并展示在Hystrix Dashboard上。
  • 日志监控: 采用ELK栈集中收集和分析应用日志。

3.3 优化后的基础服务架构

上图是经过造后优化后的架构,浅蓝色标注的都属于基础服务,主要替换的组件如下:

  1. 授权认证服务:替换为使用第8模块为课程定制开发的Gravitee OAuth2服务器。
  2. 配置服务:替换为使用携程Apollo做统一配置中心,集中管理所有Spring微服务的配置。
  3. 分布式调用链:替换为使用大众点评开源的CAT做调用链监控,从网关调后台服务,服务之间相互调用,都采用CAT客户端进行埋点监控。CAT埋点既演示使用拦截器(interceptor)方式,也演示使用AOP非侵入方式。
  4. METRICS&ALERTING:网关和微服务都启用Prometheus Metrics端点,便于集成Prometheus监控和告警。

其它组件,比如Zuul网关、Eureka服务发现、Ribbon软负载、Hystrix限流熔断,以及ELK集中日志都同原架构,没有太大变化。

技术亮点

通过Piggy Metrics项目可以从中学习到以下几点:

  1. 如何使用Apollo集中管理Spring应用的配置?
  2. 网关集中验证令牌token怎么实现?
  3. 基于OAuth2的注册登录和API调用具体是如何实现的?
  4. CAT非侵入式埋点怎么做,如何尽量减少业务研发直接使用CAT进行埋点?

注册登录流程

上图展示PiggyMetrics的登录注册流程,简化流程如下:

  1. 客户端应用向后台发起注册请求。
  2. 请求通过网关反向路由到账户服务(Account Svc)。
  3. 账户服务先去授权认证服务(Gravitee OAuth2)创建一个用户(包括用户和密码,这样后续才可以登录获取访问令牌)。账户服务再保存新账户信息到本地MongoDB数据库。
  4. 注册成功以后,客户应用向授权认证服务请求访问令牌(走用户名密码模式),拿到令牌以后缓存本地localstorage

服务调用流程

上图展示PiggyMetrics的API调用流程,简化流程如下:

  1. 客户端向后台服务发起API调用,调用时在HTTP授权头上带上访问令牌。
  2. 网关截获API请求,根据安全需求判断是否需要验令牌,如果需要,则向授权服务器发起令牌校验请求。授权服务器校验令牌并返回有效型性信息,如果令牌有效,同时返回用户名等相关信息。网关再判断校验是否通过,如果通过,则将用户名以HTTP HEADER方式向后台服务传递,如果不通过,则直接报授权错到客户端。
  3. 资源服务器从HTTP HEADER请求头获取用户名等信息,可通过用户名进一步查询用户相关信息,实现业务逻辑。

客户端调用后台服务,经过改造为网关集中校验令牌方式,这样可以简化安全架构,即在企业内网,资源服务器端可直接获取用户名信息,不需要再到授权服务器做集中令牌校验。另外,服务之间的调用也改造为可以直接调用,不需要授权认证和令牌,这种做法也是很多一线企业实际落地的做法,即在生产环境中,内部服务之间调用不授权认证,这样可以简化服务的开发和部署,但是对于安全敏感的服务要求做好生产网段隔离(需运维配合)。

代码解读

项目采用Spring Security&OAuth2实现用户认证授权,通过实现UserDetailsService接口实现身份认证:

UserDetailsService

@Service
public class MongoUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository repository;

    /**
     * 根据用户名获取用户(用户的角色、权限等信息)
     *
     * @return UserDetails
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return repository.findById(username).orElseThrow(() -> new UsernameNotFoundException(username));
    }
}
复制代码

WebSecurityConfig配置类

security的WebSecurityConfigurerAdapter常用于配置任认证管理器配置、核心过滤器配置、安全过滤器链配置, HttpSecurity使用了builder的构建方式来灵活指定访问策略。

/**
 * spring security配置
 *
 * @return UserDetails
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 自定义身份认证逻辑
     */
    @Autowired
    private MongoUserDetailsService userDetailsService;

   /**
     * anyRequest          |   匹配所有请求路径
     * access              |   SpringEl表达式结果为true时可以访问
     * anonymous           |   匿名可以访问
     * denyAll             |   用户不能访问
     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
     * permitAll           |   用户可以任意访问
     * rememberMe          |   允许通过remember-me登录的用户访问
     * authenticated       |   用户登录后可访问
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    /**
     * 解决 无法直接注入 AuthenticationManager
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
复制代码

AuthorizationServerConfigurer

AuthorizationServerConfigurer是配置OAuth2授权配置服务的配置类接口,只需要添加@EnableAuthorizationServer,Spring会实现自动注入,接口有三个方法,可实现客户端的配置、安全功能、以及各个Endpoint(端点)的相关配置。

public interface AuthorizationServerConfigurer {
    // 配置授权服务器的安全性
    void configure(AuthorizationServerSecurityConfigurer security) throws Exception;

    //客户端信息配置
    void configure(ClientDetailsServiceConfigurer clients) throws Exception;

    //配置授权服务器端点的非安全功能,如令牌存储、令牌定制、用户批准和授权类型。默认情况下你不需要做任何事情,除非你需要密码授权,在这种情况下你需要提供一个 {@link AuthenticationManager}。
    void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception;
}
复制代码

AuthorizationServerConfigurerAdapter

AuthorizationServerConfigurerAdapter继承了AuthorizationServerConfigurer接口

public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {

    public AuthorizationServerConfigurerAdapter() {
    }

    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    }

    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    }

    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    }
}
复制代码

PiggyMetrics定义OAuth2AuthorizationConfig

OAuth2AuthorizationConfigAuthorizationServerConfigurer默认的实现类,它是Spring Security OAuth2授权服务器的默认配置,当没有自定义配置时,将会使用此配置。

EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    //保存 OAuth2 token ,有InMemoryTokenStore、JdbcTokenStore、JwkTokenStore、RedisTokenStore
    private TokenStore tokenStore = new InMemoryTokenStore();
    
    private final String NOOP_PASSWORD_ENCODE = "{noop}";

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    private MongoUserDetailsService userDetailsService;

    @Autowired
    private Environment env;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        // 在内存中创建一个Oauth2 Client
        clients.inMemory()
                .withClient("browser")
                // 授权类型集合
                .authorizedGrantTypes("refresh_token", "password")
                .scopes("ui")
                .and()
                .withClient("account-service")
                // 密码
                .secret(env.getProperty("ACCOUNT_SERVICE_PASSWORD"))
                .authorizedGrantTypes("client_credentials", "refresh_token")
                .scopes("server")
                .and()
                .withClient("statistics-service")
                .secret(env.getProperty("STATISTICS_SERVICE_PASSWORD"))
                .authorizedGrantTypes("client_credentials", "refresh_token")
                .scopes("server")
                .and()
                .withClient("notification-service")
                .secret(env.getProperty("NOTIFICATION_SERVICE_PASSWORD"))
                .authorizedGrantTypes("client_credentials", "refresh_token")
                // 授权范围
                .scopes("server");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // token存储器
        endpoints
                .tokenStore(tokenStore)
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
                .passwordEncoder(NoOpPasswordEncoder.getInstance());
    }
}
复制代码

Feign服务调用

Piggy Metrics在AccountService调用用户服务来创建用户,通过在账户服务定义FeignClient(AuthServiceClient)实现远程调用:

@FeignClient(name = "auth-service")
public interface AuthServiceClient {

   @RequestMapping(method = RequestMethod.POST, value = "/uaa/users", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
   void createUser(User user);
}
复制代码

AuthService#UserController开放创建用户的API:

@RestController
@RequestMapping("/users")
public class UserController {

   @Autowired
   private UserService userService;

   @RequestMapping(value = "/current", method = RequestMethod.GET)
   public Principal getUser(Principal principal) {
      return principal;
   }

   @PreAuthorize("#oauth2.hasScope('server')")
   @RequestMapping(method = RequestMethod.POST)
   public void createUser(@Valid @RequestBody User user) {
      userService.create(user);
   }
}
复制代码

Piggy Metrics扩展点

实际上这个架构进行生产化,仍需做生产化扩展,下面是一些可能的扩展点:

  1. 安全,采用网关集中令牌校验后,内部服务可以直接调用,不需要授权认证,但在生产环境中,特别是对于安全敏感的服务,需要考虑安全增强,例如生产网段隔离IP白名单等机制。
  2. CAT客户端进一步封装,案例演示中为了简化,使用一些手工埋点,但在实际生产中,一般需要有独立框架团队对CAT客户端进行进一步封装,对常用基础组件(服务框架,数据访问层,MVC框架,消息系统,缓存系统等)进行集中埋点,并提供封装好的客户端(最好做到无侵入,可参考Spring Cloud Sleuth Starter埋点方式),方便业务研发团队接入。基本上,框架层集中埋点以后,业务应用只需引入依赖即可,一般不需要再手工埋点。
  3. 用户服务解耦,演示案例中,用户服务(包括用户数据库)和Gravitee OAuth2集成在一起,但实际企业中用户服务可能是独立不耦合的,Gravitee OAuth2可以扩展集成独立用户服务,账户服务也可以集成对接独立用户服务。
  4. 前后分离部署,演示案例中,为简化部署,前端应用和网关住在一起,但在实际生产中,根据企业业务和团队规模,前端应用和后端微服务可能是完全分离部署的,具体做法可参考波波的视频课程。
  5. Gravitee OAuth2,另外Gravitee OAuth2本身也需要扩展 Gravitee OAuth2。

) - Piggy Metrics微服务项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓讲课笔记5.6 列表视图

文章目录零、本讲学习目标一、导入新课二、新课讲解(一)列表视图概述1、继承关系图2、列表视图API文档3、列表视图四要素4、四种常用适配器(二)数组适配器1、数组适配器API文档2、数据适配器继承关系图3、数组适配器构造方法&…

第3章 定义内存缓存和log4net日志中间件

006 ICaching、MemoryCaching、SqlSugarMemoryCacheService 、MemoryCacheSetup Icaching:继承该接口的具体实现类,用于把内存缓存中间件实例注入到内置容器中,为实体实例的缓存数据交互操作提供内存管理操作支撑。 MemoryCaching&#xff1a…

了解Redis之命令操作

目录 1、Redis简介 2、Redis安装 2.1解压redis 2.2.安装gcc 2.3.编译redis 2.4.检测安装情况 2.5.修改redis.conf文件 2.6启动redis 2.7.测试redis启动是否成功 3、Redis命令 3.1.String 3.2.Hash 3.3.List 3.4.set 1、Redis简介 Redis是一个开源(BSD许可…

第二次上机作业 大连理工大学

某百货公司6月份各天的销售数据如下:【数据】 x = c(257,276,301,252,238,310,246,236,265,278,271,292,261,281,301,274,267,280,291,258,272,284,268,303,273,263,301,249,269,295)计算该百货公司日销售额的中位数、四分位数和众数 median(x)# 中位数 quantile(x) # 四分位…

详解TCP为什么不能是两次握手

三次握手的过程 注意不要遗漏全双工下两缓存(读/写缓存)的分配和变量的分配。 CLOSED:表示初始状态。 LISTEN:该状态表示服务器端的某个SOCKET处于监听状态,可以接受连接。 SYN_SENT:这个状态与SYN_RCVD遥…

极限学习机和自适应稀疏表示算法 (EA-SRC)(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

梦开始的地方—— C语言动态内存管理(malloc+calloc+realloc+free)

文章目录动态内存管理1.为什么需要动态内存分配?2. 动态内存函数malloc&freecallocrealloc3. 常见的动态内存错误对NULL解引用对动态开辟空间的越界访问对非动态开辟内存使用free释放使用free释放一块动态开辟内存的一部分对同一块动态内存多次释放动态开辟内存…

Vue实现模糊查询:filter()

需求&#xff1a;在输入框里输入内容&#xff0c;包含相关内容的值被筛选出来&#xff1b; 图示&#xff1a; 最初的代码&#xff1a; <body><div id"box"><input type"text" input"handleInput()" v-model"mytext"&…

计算机网络 - 网络层 选择填空判断复习题

一. 单选题&#xff08;共25题&#xff0c;80分&#xff09; (单选题) 以下( )协议完成了从网卡到IP地址的映射。 A A.ARP协议 B.RARP协议 C.IGMP协议 D.ICMP协议 (单选题) 一个C类地址,采用了255.255.255.240作为子网掩码,那么这个C类地址可以划分为( )个子网。 A A.16 B.32 …

零基础自学javase黑马课程第十四天

零基础自学javase黑马课程第十四天 ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f52e;本文由京与旧铺原创&#xff0c;csdn首发&#xff01; &#x1f618;系列专栏&#xff1a;java学习 &#x1f4bb;首发时间&#xff1a;&#x1f39e;2022年11月21日&…

【Hack The Box】Linux练习-- FriendZone

HTB 学习笔记 【Hack The Box】Linux练习-- FriendZone &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月17日&#x1f334; &#…

秋招失足,拿到这份“Java 高分指南(25 专题)”,金三银四翻盘有望

面试造火箭&#xff0c;工作拧螺丝&#xff01;金九银十灰溜溜地落榜&#xff0c;备受打击。正当准备明年金三银四之际&#xff0c;意外喜提朋友赠送的这“Java 高分指南&#xff08;25 专题&#xff09;”&#xff1a;Elasticsearch、微服务、Linux、JavaOOP、集合/泛型、Mysq…

move_base代码解析(一)MoveBase::executeCb

move_base是ROS中的经典路径规划算法&#xff0c;move_base 功能包提供了基于动作(action)的路径规划实现&#xff0c;move_base 可以根据给定的目标点&#xff0c;控制机器人底盘运动至目标位置&#xff0c;并且在运动过程中会连续反馈机器人自身的姿态与目标点的状态信息。 …

HTTP协议中的HTTP报文

HTTP中的HTTP报文 1、HTTP报文信息 1.1定义 用于HTTP协议交互的信息叫做HTTP 报文。 HTTP 报文大致可分为报文首部和报文主体两块。两者由最初出现的空行&#xff08;CRLF&#xff09;来划分&#xff08;通常并不一定要有报文主体&#xff09;。 1.2请求报文和响应报文 请…

CSS13_由html{height: 100%} 引发的CSS百分比宽高度的思考

一、html, body { height:100% } CSS有一个常见设置&#xff1a;html,body{ height:100% }&#xff0c;可能大家已经熟视无睹了&#xff0c;但细细思索&#xff0c;可能会有些奇怪&#xff0c;为什么html还需要设置height:100%呢&#xff1f;html不就代表整个页面了吗&#xf…

[附源码]java毕业设计网上书店管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SpringBoot项目使用JSP

SpringBoot不推荐使用JSP,而是使用模板技术代替JSP视图 先创建个SpringBoot项目 使用JSP需要如下配置 加入一个处理JSP的依赖(使用该JSP依赖原因是SpringBoot的jar包是内嵌了一个Tomcat因此要用这个Jar包,如果你的SpringBoot需要打成war包,不使用内嵌Tomcat,可用通用的JSP依赖…

深度学习基础--神经网络(3)神经网络的学习,损失函数初识

文章目录神经网络的学习从数据中学习数据区分损失函数均方误差交叉熵误差mini-batch学习损失函数更新的思路本文为学习笔记整理参考书籍&#xff1a;《深度学习入门 : 基于Python的理论与实现 》/ (日) 斋藤康毅著 ; 陆宇杰译. – 北京 : 人民邮电出版社, 2018.7&#xff08;20…

Android插件式换肤以及资源加载流程分析

前言 APP更换皮肤的方式有很多&#xff0c;如系统自带的黑夜模式、插件换肤、通过下发配置文件加载不同主题等等&#xff0c;我们这里就浅谈下插件换肤方式。想实现插件换肤功能&#xff0c;我们就需要先弄清楚 :APP是如何完成资源加载的。 资源加载流程 这里我们以ImageVie…

植物大战僵尸变态辅助开发系列教程(E语言实现和VC6实现)(中)

植物大战僵尸变态辅助开发系列教程&#xff08;E语言实现和VC6实现&#xff09;&#xff08;中&#xff09;26、第一种方法实现变态加速功能27、第二种方法找出变态攻击加速的方法28、加快阳光、金币生产速度29、全屏僵尸29、全屏减速第一课30、全屏减速第二课31、全屏奶油的找…