黑马苍穹外卖学习Day6

HttpClient

介绍

HttpClient 是 Apache 提供的一个开源的 Java HTTP 客户端库,用于发送 HTTP 请求和处理 HTTP 响应。它提供了一种更简便的方式来执行 HTTP 请求,并支持多种协议,如 HTTP、HTTPS、FTP 等。
使用 HttpClient 可以方便地与远程服务器进行通信,发送 HTTP 请求并处理响应。在实际应用中,HttpClient 常被用于与 RESTful API 交互、爬虫开发、测试等场景。

入门案例

新建一个test类进行测试

package com.sky.test;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

@SpringBootTest
public class HttpClientTest {
    /**
     * 测试通过HttpClientTest发送GET请求
     */
    @Test
    public void testGet() throws Exception{
        //创建HTTP对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建请求对象
        HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");
        //发送请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //获取服务端返回的状态码
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("服务端返回状态码:"+statusCode);

        HttpEntity entity = response.getEntity();
        String body = EntityUtils.toString(entity);
        System.out.println("服务端返回数据为:"+body);

        //关闭资源
        response.close();
        httpClient.close();
    }

    /**
     * 测试通过HttpClientTest发送POST请求
     */
    @Test
    public void testPost() throws Exception {
        //创建HTTP对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建请求对象
        HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");
        //构造JSON对象
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("username", "admin");
        jsonObject.put("password", "123456");

        StringEntity entity = new StringEntity(jsonObject.toString());
        //指定请求编码方式
        entity.setContentEncoding("utf-8");
        //数据格式
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        //发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        //解析返回结果
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("响应码为:"+ statusCode);
        HttpEntity entity1 = response.getEntity();
        String body = EntityUtils.toString(entity1);
        System.out.println("响应数据为:"+body);
        //关闭请求
        response.close();
        httpClient.close();
    }
}

微信小程序开发

介绍

在这里插入图片描述
在这里插入图片描述

准备工作

注册小程序

登录微信小程序平台按照提示进行注册
在这里插入图片描述

完善小程序信息

登录后进入开发管理和管理,根据页面提示信息补充小程序各项基本信息并生成密钥。
在这里插入图片描述

下载开发者工具

根据提示创建小程序
在这里插入图片描述
在这里插入图片描述

入门案例

在这里插入图片描述
在这里插入图片描述

获取用户信息

在这里插入图片描述

<!--index.wxml-->
<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<scroll-view class="scrollarea" scroll-y type="list">
  <view class="container">
    <!-- 展示动态信息 -->
    <view>
    {{meg}}
    </view>
    <button type="primary" bind:tap="getUserInfo">获取用户信息</button>
    昵称: {{nickName}}
    <image src="{{url}}" style="width: 100px;height: 100px;"></image>
  </view>
</scroll-view>


// index.js
Page({
  data:{
    meg:'hello world',
    nickName:'',
    url:''
  },
  //获取微信用户头像和昵称
  getUserInfo(){
    wx.getUserProfile({
      desc: '获取用户信息',
      success: (res) =>{
        console.log(res.userInfo)
        //为数据赋值
        this.setData({
          nickName: res.userInfo.nickName,
          url: res.userInfo.avatarUrl
        })
      }
    })
  }

})


其中需要调整数据库到2.7以下版本。具体路径为右上角详情->本地设置->调试基础库。
在这里插入图片描述

获取用户授权码

  data:{
    meg:'hello world',
    nickName:'',
    url:'',
    code:''
  },
  //微信登录,获取微信登录的授权码
  wxlogin(){
    wx.login({
      success: (res) => {
        console.log(res.code)
        this.setData({
          code: res.code
        })
      },
    })
  },
    <view>
      <button type="warn" bind:tap="wxlogin">微信登录</button>
      授权码:{{code}}
    </view>

在这里插入图片描述

发送请求

  //发送请求
  sendRequest(){
    wx.request({
      url: 'http://localhost:8080/user/shop/status',
      method:'GET',
      success: (res)=>{
        //代表后端响应的整个JSON数据
        console.log(res.data)
      }
    })
  }
    <view>
      <button type="default" bind:tap="sendRequest">发送请求</button>
    </view>

在这里插入图片描述

微信登录

微信登录流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

需求分析

在这里插入图片描述
在这里插入图片描述

代码开发

openid是微信用户的唯一标识
新建Controller层

@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用户相关接口")
@Slf4j
public class UserController {
    @Autowired
    UserService userService;
    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 微信登录
     * @param userLoginDTO
     * @return
     */
    @PostMapping("/login")
    @ApiOperation("微信登录")
    public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
        log.info("微信用户登录:{}",userLoginDTO.getCode());
        //微信登录
        User user = userService.wxLogin(userLoginDTO);
        //为微信用户生成令牌
        Map<String,Object> claims=  new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID,user.getId());
        String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);

        UserLoginVO userLoginVO = UserLoginVO.builder()
                .id(user.getId())
                .openid(user.getOpenid())
                .token(token)
                .build();
        return Result.success(userLoginVO);
    }
}

Service实现类

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    //微信服务接口登录地址
    public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
    @Autowired
    private WeChatProperties weChatProperties;
    @Autowired
    private UserMapper userMapper;
    /**
     * 微信登录
     * @param userLoginDTO
     * @return
     */
    @Override
    public User wxLogin(UserLoginDTO userLoginDTO) {
        String openid = getOpenid(userLoginDTO.getCode());
        //判断openid是否为空,如果为空表示登录失败,抛出业务异常
        if(openid == null){
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }
        //是否是新用户
        User user = userMapper.getByOpenID(openid);
        //是新用户,自动完成注册
        if (user==null){
            user = User.builder()
                    .openid(openid)
                    .createTime(LocalDateTime.now())
                    .build();
        }
        userMapper.insert(user);
        //返回用户对象
        return user;
    }
    private String getOpenid(String code){
        //调用微信服务器接口服务,获得当前微信服务的openid
        Map<String,String> map = new HashMap<>();
        map.put("appid",weChatProperties.getAppid());
        map.put("secret", weChatProperties.getSecret());
        map.put("js_code", code);
        map.put("grant_type", "authorization_code");
        String json = HttpClientUtil.doGet(WX_LOGIN, map);
        JSONObject jsonObject = JSON.parseObject(json);
        String openid = jsonObject.getString("openid");
        return openid;
    }
}

Mapper接口

@Mapper
public interface UserMapper {
    @Select("select * from user where openid= #{openid}")
    User getByOpenID(String openid);

    /**
     * 插入数据
     * @param user
     */
    void insert(User user);
}

后端对应的xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sky.mapper.UserMapper">
    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        insert into user (openid, name, phone, sex, id_number, avatar, create_time) VALUES
            (#{openid},#{name},#{phone},#{sex},#{idNumber},#{avatar},#{createTime})
    </insert>
</mapper>

配置web层、拦截器组件学习

对注射web层中WebMvcConfiguration的理解

    /**
     * 设置静态资源映射
     * 当访问 /doc.html路径时,Spring MVC将会去 classpath:/META-INF/resources/目录下寻找对应的静态资源
     * 而访问 /webjars/** 路径时,将会去 classpath:/META-INF/resources/webjars/目录下寻找对应的静态资源。
     * 这样做的好处是可以将一些静态资源集中存放在指定的目录,而不需要暴露给外部直接访问项目的文件结构。
     * 这有助于更好地组织项目结构,同时提供对静态资源的有效管理和映射。
     * @param registry
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始设置静态资源映射");
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    /**
     * 扩展Spring MVC框架的消息转换器
     * 将 Java 对象转换为 JSON 数据:当服务器端需要将 Java对象转换为 JSON数据
     * 以便于发送给客户端时,消息转换器负责将 Java对象序列化为JSON格式的数据。
     * 将 JSON数据转换为 Java对象:当客户端发送包含JSON数据的请求体给服务器时
     * 消息转换器负责将接收到的JSON数据反序列化为对应的 Java对象。
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器..");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,可以将Java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转换器加入容器中
        converters.add(0,converter);
    }
    /**
     * 注册自定义拦截器
     * 第一个拦截器 jwtTokenAdminInterceptor 注册在路径 /admin/**下,但排除了路径/admin/employee/login。
     * 第二个拦截器 jwtTokenUserInterceptor 注册在路径 /user/**下,但排除了路径/user/user/login和/user/shop/status。
     * 这样配置的效果是,当请求路径匹配拦截路径时,会触发相应的拦截器执行相应的逻辑。拦截器可以用于处理请求前的预处理、日志记录、权限验证等工作。
     * 通过拦截器来验证 JWT 令牌,确保请求的合法性,这在安全性要求较高的 Web 应用中是常见的做法。
     * @param registry
     */
    protected void addInterceptors(InterceptorRegistry registry) {
        log.info("开始注册自定义拦截器...");
        registry.addInterceptor(jwtTokenAdminInterceptor)
                .addPathPatterns("/admin/**")
                .excludePathPatterns("/admin/employee/login");

        registry.addInterceptor(jwtTokenUserInterceptor)
                .addPathPatterns("/user/**")
                .excludePathPatterns("/user/user/login")
                .excludePathPatterns("/user/shop/status");
    }

对jwt拦截器的理解



/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取当前线程id
        System.out.println("当前线程id"+Thread.currentThread().getId());
        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法,直接放行
            return true;
        }

        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getUserTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            //这个方法是自定义的 JWT 解析方法,接受两个参数,第一个是用于解密的密钥
            //第二个是待解析的 JWT 令牌 (token)。该方法返回一个 Claims 对象,其中包含了 JWT 中的声明信息。
            Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
            //这一行代码从 Claims 对象中获取用户ID的声明,并将其转换成Long类型。在JWT的声明中,通常会包含一些声明(比如过期时间、签发者等)
            // 同时也会包含自定义的声明。在这里,通过 JwtClaimsConstant.USER_ID 来获取用户ID的声明。
            Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
            log.info("当前用户id:", userId);
            //在拦截器中存入
            //这行代码的作用是将用户ID存入线程上下文。线程上下文是一个与线程关联的数据存储区域,可以在整个线程的生命周期内共享数据。
            //在这个具体的场景中,当用户的 JWT 令牌验证通过后,将用户的ID存入线程上下文,以便在后续的业务逻辑中能够方便地获取当前用户的ID,
            //而不必在每个方法参数中传递用户ID或者从其他地方再次获取。这样做的好处是简化了代码,提高了代码的可读性和可维护性。
            //举例来说,如果有其他地方需要使用当前用户的ID,可以通过 BaseContext.getCurrentId() 获取,
            //而不必传递用户ID的参数。这在涉及多个方法、类之间需要传递用户ID的情况下,可以减少重复代码,提高开发效率。
            BaseContext.setCurrentId(userId);
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }
    }
}

导入商品浏览功能

需求分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码实现

C端-分类接口

Controller层注意对注释进行命名用来区别admin的相同请求,具体实现方法可以通用。

@RestController("userCategoryController")
@Api(tags = "C端-分类接口")
@RequestMapping("/user/category")
@Slf4j
public class CategoryController {
    @Autowired
    private CategoryService categoryService;
    // Spring MVC 默认会按照参数名字和请求中的参数名字进行匹配。在你的情况下,接口路径为 /list
    // 而请求参数为 type,由于参数名字和请求中的参数名字一致,Spring MVC 可能会自动将参数值绑定到方法的参数上。
    //这是Spring MVC 的一种简化规则,适用于一些简单的情况。
    @GetMapping("/list")
    @ApiOperation("条件查询")
    /**
     * 条件查询
     */
    public Result<List<Category>> list(Integer type){
        List<Category> list = categoryService.list(type);
        return Result.success(list);
    }
}

C端-菜品浏览接口
Controller层

@RestController("userDishController")
@Api(tags = "C端-菜品浏览接口")
@RequestMapping("/user/dish")
@Slf4j
public class DishController {
    @Autowired
    private DishService dishService;

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    private Result<List<DishVO>> list(Long categoryId){
        List<DishVO> dishVOS = dishService.listWithFlavor(categoryId);
        return Result.success(dishVOS);
    }

Service实现层

    /**
     * 根据分类id查询菜品以及口味
     * @param categoryId
     * @return
     */
    @Override
    public List<DishVO> listWithFlavor(Long categoryId) {
        Dish dish = Dish.builder()
                        .categoryId(categoryId)
                        .status(StatusConstant.ENABLE)
                        .build();
        List<Dish> dishList = dishMapper.list(dish);
        List<DishVO> dishVOList = new ArrayList<>();
        for (Dish d : dishList){
            DishVO dishVO = new DishVO();
            BeanUtils.copyProperties(d, dishVO);
            List<DishFlavor> dishFlavorList = dishFlavorMapper.getByDishId(d.getId());
            dishVO.setFlavors(dishFlavorList);
            dishVOList.add(dishVO);
        }
        return dishVOList;
    }

C端-套餐浏览接口
Controller层

@RestController("userSetmealController")
@Api(tags = "C端-套餐浏览接口")
@RequestMapping("/user/setmeal")
@Slf4j
public class SetmealController {
    @Autowired
    private SetmealService setmealService;
    /**
     * 套餐浏览接口
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询套餐")
    public Result<List<Setmeal>> list(Long categoryId){
        List<Setmeal> setmeals = setmealService.list(categoryId);
        return Result.success(setmeals);
    }

    /**
     * 根据套餐id查询包含的菜品
     * @param id
     * @return
     */
    @ApiOperation("根据套餐id查询包含的菜品")
    @GetMapping("/dish/{id}")
    public Result<List<DishItemVO>> dishList(@PathVariable("id") Long id){
        List<DishItemVO> dishItemVOS = setmealService.dishList(id);
        return Result.success(dishItemVOS);
    }

Service层实现类

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    @Override
    public List<Setmeal> list(Long categoryId) {
        Setmeal setmeal = new Setmeal();
        setmeal.setCategoryId(categoryId);
        setmeal.setStatus(StatusConstant.ENABLE);
        List<Setmeal> setmeals = setmealMapper.list(setmeal);
        return setmeals;
    }

    /**
     * 根据套餐id查询包含的菜品
     * @param id
     * @return
     */
    @Override
    public List<DishItemVO> dishList(Long id) {
        return setmealMapper.dishList(id);
    }

Mapper接口

    /**
     * 根据分类id查询菜品
     * @param Setmeal
     * @return
     */
    List<Setmeal> list(Setmeal setmeal);

    /**
     * 根据套餐id查询包含的菜品
     * @param setmealId
     * @return
     */
    @Select("select sd.name,sd.copies,d.image,d.description from setmeal_dish sd left join dish d on sd.dish_id = d.id " +
            "where sd.setmeal_id = #{setmealId}")
    List<DishItemVO> dishList(Long setmealId);

XML底层

    <select id="list" resultType="com.sky.entity.Setmeal" parameterType="Setmeal">
        select * from setmeal
        <where>
            <if test="name != null">
                and name like concat('%',#{name},'%')
            </if>
            <if test="categoryId != null">
                and category_id = #{categoryId}
            </if>
            <if test="status != null">
                and status = #{status}
            </if>
        </where>
    </select>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c语言-数据类型(上)

目录 一、数据类型 二、常量与变量 常量&#xff1a; 变量&#xff1a; 三、进制&#xff08;八&#xff0c;十&#xff0c;十六&#xff09; 十进制&#xff1a; 八进制&#xff1a; 十六进制&#xff1a; 四、基本类型 1.整型常量&#xff1a; 2.整型变量&#xff…

RocketMQ源码阅读-Message拉取与消费-Broker篇

RocketMQ源码阅读-Message拉取与消费-Broker篇 1. ConsumeQueue是什么2. Message重放2.1 从MappedFile文件读取Message到ConsumeQueue2.2 ConsumeQueue持久化 3. Broker提供的拉取接口3.1 请求Header3.2 拉取消息接口3.3 拉取失败处理 4. Broker提供的更新消费进度接口5. Broke…

【C++】零碎知识点汇总_1

abs() 函数&#xff1a; abs() 是 C 和 C 标准库中的函数&#xff0c;用于计算整数的绝对值。在 C 中&#xff0c;abs() 函数的原型位于 <stdlib.h> 头文件中&#xff0c;用于整数类型在 C 中&#xff0c;abs() 函数的原型位于 <cstdlib> 头文件中&#xff0c;并可…

LeetCode 160: 两个链表的相交节点 - 优雅解法

LeetCode 160: Intersection of Two Linked Lists 题目描述 给定两个单链表 headA 和 headB 的头节点&#xff0c;返回它们相交的节点。如果两个链表没有相交&#xff0c;返回 null。 示例: 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,6,1,8,4,5], sk…

【RTOS】快速体验FreeRTOS所有常用API(1)工程创建

目录 一、工程创建1.1 新建工程1.2 配置RCC1.3 配置SYS1.4 配置外设1&#xff09;配置 LED PC132&#xff09;配置 串口 UART13&#xff09;配置 OLED I2C1 1.5 配置FreeRTOS1.6 工程设置1.7 生成代码1.8 keil设置下载&复位1.9 添加用户代码 本工程皆在快速体验FreeRTOS所有…

MPP架构和分布式架构的区别

前言&#xff1a;对大数据的数据处理需求&#xff0c;当前技术方向上存在两个不同的发展路线&#xff0c;MPP和分布式处理。两者数据处理的基本思路都是一样的&#xff0c;分布式并行处理再合并结果&#xff1b;但由于二者在处理架构上的差异&#xff0c;最终产品在应用需求性能…

【Python学习】Python学习19- 异常处理

目录 【Python学习】Python学习19- 异常处理 前言python标准异常异常处理带异常类型语法不带异常类型语法使用except而带多种异常类型try-finally 语句触发异常 参考 文章所属专区 Python学习 前言 本章节主要说明Python的异常处理。 python标准异常 BaseException 所有异常…

RabbitMQ详解(值得珍藏)

1. 基本概念 RabbitMQ是一款开源&#xff0c;使用Erlang编写的&#xff0c;基于AMQP协议的消息中间件&#xff1b; 提到RabbitMQ&#xff0c;就不得不提AMQP协议。AMQP协议是具有现代特征的二进制协议。是一个提供统一消息服务的应用层标准高级消息队列协议&#xff0c;是应用…

远程控制软件安全吗?一文看懂ToDesk、RayLink、TeamViewer、Splashtop相关安全机制_raylink todesk

目录 一、前言 二、远程控制中的安全威胁 三、国内外远控软件安全机制 【ToDesk】 【RayLink】 【Teamviewer】 【Splashtop】 四、安全远控预防 一、前言 近期&#xff0c;远程控制话题再一次引起关注。 据相关新闻报道&#xff0c;不少不法分子利用远程控制软件实施…

两周掌握Vue3(五):自定义指令、路由、ajax

文章目录 一、自定义指令1.创建和使用自定义指令2.钩子函数3.使用参数 二、路由1.创建一个router实例2.在components目录中创建组件3.将路由实例挂载到应用4.使用路由 三、Ajax 代码仓库&#xff1a;跳转 当前分支&#xff1a;05 一、自定义指令 自定义指令是Vue.js框架提供的…

Unity中URP下的SimpleLit顶点着色器

文章目录 前言顶点着色器1、GPU Instance 相关2、顶点输入数据相关3、雾效混合因子4、对 uv 进行 Tilling 和 Offset 的应用 及 把顶点的坐标信息传给输出结构体5、把法线相关的结果&#xff0c;传给输出结构体6、光照贴图相关7、额外灯相关计算8、阴影相关 前言 在上一篇文章…

Ubuntu下,Flutter安装及在VScode中的配置

1、安装flutter 在自己指定的目录下&#xff0c;新建文件夹&#xff0c;并将源码git clone到本地 $ mkdir flutter $ cd flutter$ git clone -b master https://github.com/flutter/flutter.git2、给flutter添加环境变量 #编辑配置文件 $ vi ~/.bashrc #在末尾加入以下内容&…

指针及其应用

1.定义 指针&#xff1a;也是一个变量&#xff0c;存放所指变量的地址&#xff0c;根据变量定义的不同&#xff0c;指针指向的类型也不同 注意&#xff1a;*是与前面类型一体的 int main(void) {int* p; //等价于int *p;//为了区分变量&#xff0c;C语言中一般将*放置于变量…

Flink(十三)【Flink SQL(上)】

前言 最近在假期实训&#xff0c;但是实在水的不行&#xff0c;三天要学完SSM&#xff0c;实在一言难尽&#xff0c;浪费那时间干什么呢。SSM 之前学了一半&#xff0c;等后面忙完了&#xff0c;再去好好重学一遍&#xff0c;毕竟这玩意真是面试必会的东西。 今天开始学习 Flin…

数据结构学习 jz30 包含 min 函数的栈

关键词&#xff1a;排序 题目&#xff1a;最小栈 方法一&#xff1a;在记录这个数的同时&#xff0c;记录目前的最小值。看了提示才写出来的。 方法二&#xff1a;辅助栈。辅助栈保持非严格递减。看了k神的答案。 方法一&#xff1a; 一开始没想到怎么存最小&#xff0c;看…

从零实现一套低代码(保姆级教程)【后端服务】 --- 【16】初始化后端项目

摘要 在前面的实现过程中&#xff0c;我们的低代码平台&#xff0c;在前端已经有一定的构建页面的能力了。 但是对于我们实现一个平台&#xff0c;肯定要支持用户对页面进行保存等功能&#xff0c;包括后面我们运行时的设计&#xff0c;都要依赖于后端的能力 所以&#xff0c…

运维必存的20个常见的故障排查、修复大全

你们好&#xff0c;我的网工朋友。 “稳定是偶然&#xff0c;异常才是常态”。这句话用来形容运维的工作再合适不过了 对于运维来说&#xff0c;工作最常遇到的就是不稳定性带来的各种故障&#xff0c;经常围绕发现故障、响应故障、定位故障、恢复故障这四大步骤打转。 为此…

一篇文章带你搞懂多线程面试相关的一些问题

目录 1.Callable接口 1.1使用Callable接口来创建线程 1.1相关面试题&#xff1a; 介绍下 Callable 是什么 2.JUC常见的类&#xff08;java.util,concurrent) 2.1ReentrantLock ReentrantLock和sychronized的区别 3.信号量 4.CountDownLatch 5.线程安全的集合类 5.1多线…

Flink-容错机制

Flink中的容错机制 流式数据连续不断地到来&#xff0c;无休无止&#xff1b;所以流处理程序也是持续运行的&#xff0c;并没有一个明确的结束退出时间。机器运行程序&#xff0c;996 起来当然比人要容易得多&#xff0c;不过希望“永远运行”也是不切实际的。因为各种硬件软件…

ioDraw在线图表工具 - 轻松制作专业图表,只需3步!

还在花大量时间手动画图表&#xff1f;还在为图表样式而烦恼&#xff1f;ioDraw为你提供一站式解决方案&#xff01;ioDraw在线图表工具实现了AI自动生成图表&#xff0c;让你轻松制作专业图表&#xff0c;只需3步&#xff01; 1. 录入数据 只需将你的数据告诉ioDraw AI助手&…