7. 好客租房-项目日常推进ing

news2025/1/12 18:56:11

7. 好客租房-项目日常推进ing

本章节不涉及大量内容,主要是为了推荐项目代码日常进度而设置, 包括添加mock接口, 添加更新房源接口, 为系统添加缓存.

7.1 为前端系统提供mock服务

往往在项目开发中, 为实现前后端并行开发,后端需要对前端所有的请求都都进行支持。当然不要求立刻实现, 只需要先模拟数据返回以便前端测试连通性,页面美观.

mock数据不涉及微服务, 主要是在api-sereve模块中开发

7.1.1 新增文件 mock-data.properties

mock.indexMenu={"data":{"list":[{"id":1,"menu_name":"\u4E8C\u624B\u623F","menu_logo":"home","menu_path":"/home","menu_status":1,"menu_style":null},{"id":2,"menu_name":"\u65B0\u623F","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null},{"id":3,"menu_name":"\u79DF\u623F","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null},{"id":4,"menu_name":"\u6D77\u5916","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null},{"id":5,"menu_name":"\u5730\u56FE\u627E\u623F","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null},{"id":6,"menu_name":"\u67E5\u516C\u4EA4","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null},{"id":7,"menu_name":"\u8BA1\u7B97\u5668","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null},{"id":8,"menu_name":"\u95EE\u7B54","menu_logo":null,"menu_path":null,"menu_status":null,"menu_style":null}]},"meta":{"status":200,"msg":"\u6D4B\u8BD5\u6570\u636E"}}
mock.indexInfo={"data":{"list":[{"id":1,"info_title":"\u623F\u4F01\u534A\u5E74\u9500\u552E\u4E1A\u7EE9\u7EE7","info_thumb":null,"info_time":null,"info_content":null,"user_id":null,"info_status":null,"info_type":1},{"id":2,"info_title":"\u4E0A\u534A\u5E74\u571F\u5730\u5E02\u573A\u4E24\u91CD\u5929\uFF1A\u4E00\u7EBF\u964D\u6E29\u4E09\u56DB\u7EBF\u91CF\u4EF7\u9F50\u5347","info_thumb":null,"info_time":null,"info_content":null,"user_id":null,"info_status":null,"info_type":1}]},"meta":{"status":200,"msg":"\u6D4B\u8BD5\u6570\u636E"}}
mock.indexFaq={"data":{"list":[{"question_name":"\u5728\u5317\u4EAC\u4E70\u623F\uFF0C\u9700\u8981\u652F\u4ED8\u7684\u7A0E\u8D39\u6709\u54EA\u4E9B\uFF1F","question_tag":"\u5B66\u533A,\u6D77\u6DC0","answer_content":"\u5404\u79CD\u8D39\u7528","atime":33,"question_id":1,"qnum":2},{"question_name":"\u4E00\u822C\u9996\u4ED8\u4E4B\u540E\uFF0C\u8D37\u6B3E\u591A\u4E45\u53EF\u4EE5\u4E0B\u6765\uFF1F","question_tag":"\u5B66\u533A,\u660C\u5E73","answer_content":"\u5927\u69821\u4E2A\u6708","atime":22,"question_id":2,"qnum":2}]},"meta":{"status":200,"msg":"\u6D4B\u8BD5\u6570\u636E"}}
mock.indexHouse={"data":{"list":[{"id":1,"home_name":"\u5B89\u8D1E\u897F\u91CC123","home_price":"4511","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":null,"home_type":1,"home_tags":"\u6D77\u6DC0,\u660C\u5E73","home_address":null,"user_id":null,"home_status":null,"home_time":12,"group_id":1},{"id":8,"home_name":"\u5B89\u8D1E\u897F\u91CC \u4E09\u5BA4\u4E00\u5385","home_price":"4500","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":null,"home_type":1,"home_tags":"\u6D77\u6DC0","home_address":null,"user_id":null,"home_status":null,"home_time":23,"group_id":2},{"id":3,"home_name":"\u5B89\u8D1E\u897F\u91CC \u4E09\u5BA4\u4E00\u5385","home_price":"4220","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":null,"home_type":2,"home_tags":"\u6D77\u6DC0","home_address":null,"user_id":null,"home_status":null,"home_time":1,"group_id":1},{"id":4,"home_name":"\u5B89\u8D1E\u897F\u91CC \u4E09\u5BA4\u4E00\u5385","home_price":"4500","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":"4500","home_type":2,"home_tags":"\u6D77\u6DC0","home_address":"","user_id":null,"home_status":null,"home_time":12,"group_id":2},{"id":5,"home_name":"\u5B89\u8D1E\u897F\u91CC \u4E09\u5BA4\u4E00\u5385","home_price":"4522","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":null,"home_type":3,"home_tags":"\u6D77\u6DC0","home_address":null,"user_id":null,"home_status":null,"home_time":23,"group_id":1},{"id":6,"home_name":"\u5B89\u8D1E\u897F\u91CC \u4E09\u5BA4\u4E00\u5385","home_price":"4500","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":null,"home_type":3,"home_tags":"\u6D77\u6DC0","home_address":null,"user_id":null,"home_status":null,"home_time":1221,"group_id":2},{"id":9,"home_name":"\u5B89\u8D1E\u897F\u91CC \u4E09\u5BA4\u4E00\u5385","home_price":"4500","home_desc":"72.32\u33A1/\u5357 \u5317/\u4F4E\u697C\u5C42","home_infos":null,"home_type":4,"home_tags":"\u6D77\u6DC0","home_address":null,"user_id":null,"home_status":null,"home_time":23,"group_id":1}]},"meta":{"status":200,"msg":"\u6D4B\u8BD5\u6570\u636E"}}
mock.infosList1={"data":{"list":{"total":8,"data":[{"id":13,"info_title":"wwwwwwwwwwwww","info_thumb":null,"info_time":null,"info_content":null,"user_id":null,"info_status":null,"info_type":1},{"id":12,"info_title":"\u623F\u4F01\u534A\u5E74\u9500\u552E\u4E1A\u7EE9\u7EE7","info_thumb":null,"info_time":null,"info_content":null,"user_id":null,"info_status":null,"info_type":1}]}},"meta":{"status":200,"msg":"\u83B7\u53D6\u6570\u636E\u6210\u529F"}}
mock.infosList2={"data":{"list":{"total":4,"data":[{"id":9,"info_title":"\u623F\u4F01\u534A\u5E74\u9500\u552E\u4E1A\u7EE9\u7EE7\u7EED\u51B2\u9AD8\u4E09\u5DE8\u5934\u9500\u552E\u989D\u8FC7\u4EBF","info_thumb":null,"info_time":null,"info_content":null,"user_id":null,"info_status":null,"info_type":2},{"id":7,"info_title":"\u623F\u4F01\u534A\u5E74\u9500\u552E\u4E1A\u7EE9\u7EE7\u7EED\u51B2\u9AD8\u4E09\u5DE8\u5934\u9500\u552E\u989D\u8FC7\u4EBF","info_thumb":null,"info_time":null,"info_content":null,"user_id":null,"info_status":null,"info_type":2}]}},"meta":{"status":200,"msg":"\u83B7\u53D6\u6570\u636E\u6210\u529F"}}
mock.infosList3={"data":{"list":{"total":10,"data":[{"username":"tom","question_name":"\u5728\u5317\u4EAC\u4E70\u623F\uFF0C\u9700\u8981\u652F\u4ED8\u7684\u7A0E\u8D39\u6709\u54EA\u4E9B\uFF1F","question_tag":"\u5B66\u533A,\u6D77\u6DC0","answer_content":"\u5404\u79CD\u8D39\u7528","atime":33,"question_id":1,"qnum":2},{"username":"tom","question_name":"\u4E00\u822C\u9996\u4ED8\u4E4B\u540E\uFF0C\u8D37\u6B3E\u591A\u4E45\u53EF\u4EE5\u4E0B\u6765\uFF1F","question_tag":"\u5B66\u533A,\u660C\u5E73","answer_content":"\u5927\u69821\u4E2A\u6708","atime":22,"question_id":2,"qnum":2}]}},"meta":{"status":200,"msg":"\u83B7\u53D6\u6570\u636E\u6210\u529F"}}
mock.my={"data":{"id":1,"username":"tom","password":"123","mobile":"123","type":null,"status":null,"avatar":"public/icon.png"},"meta":{"status":200,"msg":"\u83B7\u53D6\u6570\u636E\u6210\u529F"}}

7.1.2 创建MockConfig

package cn.itcast.haoke.dubbo.api.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * 读取 mock-data.properties 中的内容
 * 
 * @author 过道
 */
@Configuration
@PropertySource("classpath:mock-data.properties")
@ConfigurationProperties(prefix = "mock")
@Data
public class MockConfig {
    private String indexMenu;
    private String indexInfo;
    private String indexFaq;
    private String indexHouse;
    private String infosList1;
    private String infosList2;
    private String infosList3;
    private String my;
}

7.1.3 创建MockController

package cn.itcast.haoke.dubbo.api.controller;

import cn.itcast.haoke.dubbo.api.config.MockConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * 模拟数据响应, 通过读取mock-data.properties的内容来返回假数据
 * 
 * @author 过道
 */
@RequestMapping("mock")
@RestController
@CrossOrigin
public class MockController {
    @Autowired
    private MockConfig mockConfig;

    /**
     * 菜单
     */
    @GetMapping("index/menu")
    public String indexMenu() {
        return this.mockConfig.getIndexMenu();
    }

    /**
     * 首页资讯
     */
    @GetMapping("index/info")
    public String indexInfo() {
        return this.mockConfig.getIndexInfo();
    }

    /**
     * 首页问答
     */
    @GetMapping("index/faq")
    public String indexFaq() {
        return this.mockConfig.getIndexFaq();
    }

    /**
     * 首页房源信息
     */
    @GetMapping("index/house")
    public String indexHouse() {
        return this.mockConfig.getIndexHouse();
    }

    /**
     * 查询资讯
     */
    @GetMapping("infos/list")
    public String infosList(@RequestParam("type") Integer type) {
        switch (type) {
            case 1:
                return this.mockConfig.getInfosList1();
            case 2:
                return this.mockConfig.getInfosList2();
            case 3:
                return this.mockConfig.getInfosList3();
        }
        return this.mockConfig.getInfosList1();
    }

    /**
     * 我的中心
     */
    @GetMapping("my/info")
    public String myInfo() {
        return this.mockConfig.getMy();
    }
}

7.1.4 使用swagger-ui测试

启动ApiDubboApplication项目, 打开swagger, 随便找到一个mock接口, 点击测试. 表现正常.

7.2 实现后台系统的更新房源数据功能

这个完全无脑实现下就可以了. 再熟悉下相关文件分布就可以了. 主要是为了功能的完整性.

// Controller
@PutMapping
@ResponseBody
public ResponseEntity<Void> update(@RequestBody HouseResources houseResources) {
    try {
    	boolean bool = this.houseResourcesService.update(houseResources);
        if (bool) {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        }
    } catch (Exception e) {
    	e.printStackTrace();
    }
    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}

// service
public boolean update(HouseResources houseResources) {
	return this.apiHouseResourcesService.updateHouseResources(houseResources);
}

// dubbo服务的service 接口
/**
* 修改房源
*
* @param houseResources
* @return
*/
boolean updateHouseResources(HouseResources houseResources);

// service接口的实现
@Override
public boolean updateHouseResources(HouseResources houseResources) {
	return this.houseResourcesService.updateHouseResources(houseResources);
}

// houseResourcesService的实现.
@Override
public boolean updateHouseResources(HouseResources houseResources) {
	return super.update(houseResources) == 1;
}

7.3 系统添加Redis缓存

在接口服务中,如果每一次都进行数据库查询,那么必然会给数据库造成很大的并发压力。所以需要为接口添加缓
存,缓存技术选用Redis,并且使用Redis的集群,Api使用Spring-Data-Redis。

这里省去了搭建Redis相关的环节(默认大家都会了哈), 如果需要请自行百度. 我这里使用的是已经搭建好的单机版本.

一个花费五秒钟的思考问题:

缓存应该加api处还是dubbo服务处?

7.3.1 引入依赖

揭晓答案

加在api处,可以减少对java系统的负载, 但是会有部分重复缓存的内容. dubbo服务处则依然会占用dubbo造成的带宽, 也不会降低 api模块的负载, 并且往往需要每个dubbo模块都维护自己的服务.

因为我们是小型项目(就一个后端), 我们这里选择加载api处, 最大程度的降低我们的任务量.

在api模块引入redis相关依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

7.3.2 编写Redis的配置文件

我直接卸载application.properties中

# redis集群配置
spring.redis.jedis.pool.max-wait = 5000
spring.redis.jedis.pool.max-Idle = 100
spring.redis.jedis.pool.min-Idle = 10
spring.redis.timeout = 1000
spring.redis.port=6379
# TODO 记得替换为你自己的IP, port一般都是6379, 如果你不是也需要替换哦
spring.redis.host=127.0.0.1 
spring.redis.password=test123

7.3.3 编写配置类

package cn.itcast.haoke.dubbo.api.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 本次不上分布式redis, 先使用单机版代替, 未来上分布式
 *
 * @author 过道
 */
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory
                                                               redisConnectionfactory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionfactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

7.3.4 测试项目与Redis连通性

我们依然使用junit进行测试.

package cn.itcast.haoke.dubbo.api;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Set;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRedis {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void testSave() {
        for (int i = 0; i < 100; i++) {
            this.redisTemplate.opsForValue().set("key_" + i, "value_" + i);
        }
        Set<String> keys = this.redisTemplate.keys("key_*");
        for (String key : keys) {
            String value = this.redisTemplate.opsForValue().get(key);
            System.out.println(value);
            this.redisTemplate.delete(key);
        }
    }
}

7.3.5 添加缓存逻辑

在编写代码之前我简单介绍一下用到的技术

我们需要拦截所有发给本系统Controller的请求, 所以我们将用到拦截器, 拦截请求后判断是否已被缓存,如果已被缓存, 那么直接从缓存中取出结果.

如果没有被缓存, 那么走原有逻辑, 在发送响应之前, 我们需要将响应内容缓存到Redis中.

流程图如下:

首先, 使用Spring的拦截器拦截所有HTTP请求, 代码:

package cn.itcast.haoke.dubbo.api.interceptor;

import cn.itcast.haoke.dubbo.server.util.IOUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Component
public class RedisCacheInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private static ObjectMapper mapper = new ObjectMapper();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse
            response, Object handler) throws Exception {
        if (!StringUtils.equalsIgnoreCase(request.getMethod(), "get")) {
            // 非get请求,如果不是graphql请求,放行
            if (!StringUtils.equalsIgnoreCase(request.getRequestURI(), "/graphql")) {
                return true;
            }
        }
        String data =
                this.redisTemplate.opsForValue().get(createRedisKey(request));
        if (StringUtils.isEmpty(data)) {
            // 缓存未命中
            return true;
        }
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        // 支持CORS跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods",
                "GET,POST,PUT,DELETE,OPTIONS");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        response.getWriter().write(data);
        return false;
    }

    public static String createRedisKey(HttpServletRequest request) throws
            Exception {
        String paramStr = request.getRequestURI();
        Map<String, String[]> parameterMap = request.getParameterMap();
        if (parameterMap.isEmpty()) {
            paramStr += IOUtils.toString(request.getInputStream(), "UTF-8");
        } else {
            paramStr += mapper.writeValueAsString(request.getParameterMap());
        }
        String redisKey = "WEB_DATA_" + paramStr;
        return redisKey;
    }
}

然后我们需要注册拦截器到Spring.

package cn.itcast.haoke.dubbo.api.config;

import cn.itcast.haoke.dubbo.api.interceptor.RedisCacheInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private RedisCacheInterceptor redisCacheInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.redisCacheInterceptor).addPathPatterns("/**");
    }
}

最后我们将查询请求的响应内容进行一个缓存. 这里使用的技术也是Spring提供的@ControllerAdvice注解.

package cn.itcast.haoke.dubbo.api.interceptor;

import cn.itcast.haoke.dubbo.api.controller.GraphQLController;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.time.Duration;

/**
 * ControllerAdvice是Spring提供的, 会在结果被发送前进行拦截, 拦截逻辑自己实现, 这样就可以实现缓存了.
 */
@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private ObjectMapper mapper = new ObjectMapper();

    /**
     * 对于给定的controller里的方法, 是否要进行拦截的一个判断.
     * @param returnType 返回类型
     * @param converterType 转化器
     * @return 是否可以执行 'beforeBodyWrite'方法.
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        // 如果方法上有GetMapping, 那么触发缓存, 这里的底层逻辑是GetMapping按照RestFul来说就是查询.
        if (returnType.hasMethodAnnotation(GetMapping.class)) {
            return true;
        }
        // 如果 是Post,那么只缓存 GraphQLController 的返回内容, 因为 GraphQL 也是对查询结果的一种缓存
        if (returnType.hasMethodAnnotation(PostMapping.class) &&
                StringUtils.equals(GraphQLController.class.getName(),
                        returnType.getExecutable().getDeclaringClass().getName())) {
            return true;
        }
        return false;
    }

    /**
     * 在返回给前端之前会调用这个方法, 将返回的内容提前缓存起来
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest
                                          request, ServerHttpResponse response) {
        try {
            String redisKey =
                    RedisCacheInterceptor.createRedisKey(((ServletServerHttpRequest)
                            request).getServletRequest());
            String redisValue;
            if (body instanceof String) {
                redisValue = (String) body;
            } else {
                redisValue = mapper.writeValueAsString(body);
            }
            this.redisTemplate.opsForValue().set(redisKey, redisValue,
                    Duration.ofHours(1));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }
}

7.3.6 使用swagger或者插件进行debug测试

在拦截器 RedisCacheInterceptor 类上加上debug断点, 然后再网页端发起请求

第一次进了缓存, 第二次命中缓存. 测试完成.

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

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

相关文章

2022年度总结——2022我在CSDN的那些事暨2023我的目标展望:Pursue freedom Realize self-worth

&#x1f4cb;前言 关于年度征文&#xff1a; 活动地址&#xff1a;2022年度征文活动页-CSDN &#x1f4da;文章目录 &#x1f4cb;前言 &#x1f3af;再见2022&#xff0c;2023新年快乐 &#x1f3af;回顾2022——“我”与我在CSDN的那些事 &#x1f9e9;伊始——CSDN&…

Allegro如何做镂空丝印操作指导

Allegro如何做镂空丝印操作指导 在PCB设计丝印的时候,会需要画镂空的丝印,Allegro升级到了172版本的时候,可以画镂空的丝印,如下图 具体操作如下 选择Shape Add Rect命令Options选择需要画到的层面,比如Silkscreen TOP层

Lesson1:走进C++的殿堂

首先在此声明一下&#xff0c;C的学习需要C语言的基础&#xff0c;不先学习C语言而直接学C是不现实的。市面上任何一本C的书籍&#xff0c;前几章的内容一定涉及到C语言的学习。 一、什么是C 照片上的这位老人便是C语言之父——本贾尼斯特劳斯特卢普&#xff08;Bjarne Stroust…

JavaScript学习

JavaScript 是一门跨平台、面向对象的脚本语言&#xff0c;而Java语言也是跨平台的、面向对象的语言&#xff0c;只不过Java是编译语言&#xff0c;是需要编译成字节码文件才能运行的&#xff1b;JavaScript是脚本语言&#xff0c;不需要编译&#xff0c;由浏览器直接解析并执行…

Spring核心模块解析—BeanDifinition。

BeanDifinition前言什么是BeanDefinition&#xff1f;为什么要有BeanDefinition&#xff1f;BeanDifinition重点源码总结前言 Spring中的BeanDifinition在Bean的实例化流程中占有着非常重要的角色&#xff0c;如果你不了解BeanDifinition的话&#xff0c;面试或者学习Bean的生…

【Leetcode每日一题】69. x 的平方根/Sqrt(x)|二分查找---day3

博主简介&#xff1a;努力学习的预备程序媛一枚~博主主页&#xff1a; 是瑶瑶子啦所属专栏: LeetCode每日一题–进击大厂 目录题目描述题目分析&#xff1a;代码分析&#xff1a;题目描述 链接: 69. x 的平方根/Sqrt(x) 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术…

10+种编程语言做个计算器

用十种编程语言开发计算器应用 C语言C#&#xff08;windows桌面软件&#xff09;Swift &#xff08;ios应用&#xff09;pythonDart&#xff08;Flutter应用&#xff0c;跨平台&#xff0c;适用安卓、ios、mac、windows、web&#xff09;Java&#xff08;安卓App&#xff09;K…

【Linux】多线程同步与互斥

目录&#x1f308;前言&#x1f338;1、Linux线程同步&#x1f368;1.1、同步概念与竞态条件&#x1f367;1.2、条件变量&#x1f33a;2、条件变量相关API&#x1f368;2.1、初始化和销毁条件变量&#x1f367;2.2、阻塞等待条件满足&#x1f383;2.3、唤醒阻塞等待的条件变量&…

python数据可视化开发:Matplotlib库参数配置基础知识

文章目录前言01.工具栏组件02.数据03.设置字体字典&#xff08;1&#xff09;全局字体样式&#xff08;2&#xff09;常用中文字体对应名称&#xff08;3&#xff09;查询当前系统所有字体04.图像配置实例05.图表标题06.文本组件07.坐标轴标签组件08.网格组件09.绘制折线10.图例…

传染疾病模型

1 分支过程 1.1 工作原理 第一波疫情 假设一个人携带一种新的病毒&#xff0c;以独立的概率p将疾病传染给遇到的每一个人假设这个人在感染期遇到了k个人 ——>这k个人是该疾病传染的第一波基于疾病是随机传染的&#xff0c;所以第一波中有些人会感染疾病&#xff0c;有些人…

一篇基于深度学习的命名实体识别技术的研究报告

一篇基于深度学习的命名实体识别技术的研究报告 本篇文章主要是自己刚接触NER领域时&#xff0c;研读这篇《 A Survey on Deep Learning for Named Entity Recognition 》NER综述论文时翻译的中文版&#xff0c;这篇综述时间是2020年&#xff0c;可能近两年的部分成果暂未包含…

Python数据可视化(一)图表组成元素

1.1绘制 matplotlib 图表组成元素的主要函数matplotlib 是如何组织内容的&#xff1f;在一个图形输出窗口中&#xff0c;底层是一个 Figure实例&#xff0c;我们通常称之为画布&#xff0c;包含一些可见和不可见的元素。在画布上&#xff0c;自然是图形&#xff0c;这些图形就是…

Java---微服务---RabbitMQ部署

RabbitMQ部署1.单机部署1.1.下载镜像1.2.安装MQ1.3访问管理端2.集群部署2.1.集群分类2.2.设置网络1.单机部署 我们在Centos7虚拟机中使用Docker来安装&#xff0c;如未安装dockr&#xff0c;请参考《Centos7安装Docker》 1.1.下载镜像 方式一&#xff1a;在线拉取 docker …

剑指Offer 第3天、第4天

剑指 Offer 05. 替换空格 class Solution { public:string replaceSpace(string s) {string res;for(auto e : s){if(e ){res%;res2;res0;}elserese;}return res;} }; 剑指 Offer 58 - II. 左旋转字符串 class Solution { public:string reverseLeftWords(string s, int n) {…

java spring IOC xml方式注入对象类型的list集合数据

我们新创建一个java项目 然后引入spring的基本依赖 在src下创建一个collectiontype 包 在 collectiontype 包下创建一个 Course类 参考代码如下 package collectiontype;//课程类 public class Course {//课程名称private String cname;public void setCname(String cname) …

Java---微服务---RabbitMQ入门与应用

RabbitMQ入门与应用1.初识MQ1.1.同步和异步通讯1.1.1.同步通讯1.1.2.异步通讯1.2.技术对比&#xff1a;2.快速入门2.1.安装RabbitMQ2.2.RabbitMQ消息模型2.3.导入Demo工程2.4.入门案例2.4.1.publisher实现2.4.2.consumer实现2.5.总结3.SpringAMQP3.1.Basic Queue 简单队列模型3…

浅析一条SQL在mysql中是如何执行的

一. Mysql内部组件结构 MySql大体分为server层和存储引擎层&#xff0c; server层 主要包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内置函数&#xff08;如日期、时间、数学和加密函数等&#xff09;…

spring boot整合redis中间件与热部署实现

热部署 每次写完程序后都需要重启服务器&#xff0c;需要大量的时间&#xff0c;spring boot提供了一款工具devtools帮助实现热部署。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId>…

1. python包管理pip工具

1. 何为pip&#xff1f; pip 是 python包管理工具&#xff0c;该工具提供了对 python包的查找、下载、安装、卸载的功能。 目前最新的 python版本已经预装了 pip。注意&#xff1a;python 2.7.9 或 python 3.4 以上版本都自带 pip 工具。之前在基础篇中我们已经安装了python3…

Java 23种设计模式(6.结构型模式-适配器模式)

结构型模式-适配器模式 代码分析 类图 代码 public class Target {//就是客户期待的接口&#xff0c;目标可以是具体&#xff0c;抽象的类&#xff0c;也可以是接口public String Request(){String msg "normal request";return msg;} }public class Adaptee {pub…