黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目——第四部分

news2024/11/15 21:44:17

黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目——第四部分

  • 1. 套餐管理
    • 1.1 新增套餐
      • 1.1.1 添加菜品数据回显
    • 1.2 保存添加套餐
    • 1.3 套餐信息分页查询
    • 1.4 删除套餐
    • 1.5 需要自己单独实现的功能
      • 1.5.1 套餐管理的启售、停售
      • 1.5.2 套餐管理的修改
      • 1.5.3 后台订单展示和查询

在这里插入图片描述

在这里插入图片描述

1. 套餐管理

需求分析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 新增套餐

套餐就是菜品的集合。

后台系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐。

在这里插入图片描述

数据模型:
新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmeal dish表插入套餐和菜品关联数据。所以在新增套餐时,涉及到两个表:

  • setmeal——套餐表
  • setmeal dish——套餐菜品关系表

代码开发:

准备工作:

在开发业务功能前,先将需要用到的类和接口基本结构创建好:

  • 实体类SetmealDish ( 直接从课程资料中导入即可,Setmeal实体前面课程中已经导入过了)
  • DTO SetmealDto (直接从课程资料中导入即可)
  • Mapper接口SetmealDishMapper
  • 业务层接口SetmealDishService
  • 业务层实现类SetmealDishServicelmpl
  • 控制层SetmealController
package com.itheima.reggie.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 套餐菜品关系
 */
@Data
public class SetmealDish implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;
    //套餐id
    private Long setmealId;
    //菜品id
    private Long dishId;
    //菜品名称 (冗余字段)
    private String name;
    //菜品原价
    private BigDecimal price;
    //份数
    private Integer copies;
    //排序
    private Integer sort;
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
    //是否删除
    private Integer isDeleted;
}

创建mapper:

package com.itheima.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.SetmealDish;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SetmealDishMapper extends BaseMapper<SetmealDish> {
}

创建service:

package com.itheima.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.SetmealDish;


public interface SetmealDishService extends IService<SetmealDish> {
}
package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.SetmealDish;
import com.itheima.reggie.mapper.SetmealDishMapper;
import com.itheima.reggie.service.SetmealDishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public class SetmealDishServiceImpl extends ServiceImpl<SetmealDishMapper, SetmealDish> implements SetmealDishService {
}

1.1.1 添加菜品数据回显

controller层代码:

在开发代码之前,需要梳理一下新增套餐时前端页面和服务端的交互过程:

  1. 页面(backend/page/combo/add.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中
  2. 页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中
  3. 页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中
  4. 页面发送请求进行图片上传,请求服务端将图片保存到服务器
  5. 页面发送请求进行图片下载,将上传的图片进行回显
  6. 点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端

开发新增套餐功能,其实就是在服务端编写代码去处理前端页面发送的这6次请求即可。

第一个交互前面写了;分类管理通过type的值来控制在前端展示的是 菜品分类(type=1) 或者是 套餐分类(type=2)
在这里插入图片描述

在这里插入图片描述

第二个交互前面也写了,在categorycontroller里面的list方法;

第四和第五前面也写了;

第三个交互:前端请求的地址;

在这里插入图片描述

在DishController书写代码:

    /**
     * 根据条件查询对应的菜品数据
     * @param dish
     * @return
     */
    @GetMapping("/list")
    public R<List<Dish>> list(Dish dish){ //会自动映射的
        //这里可以传categoryId,但是为了代码通用性更强,这里直接使用dish类来接受(因为dish里面是有categoryId的),以后传dish的其他属性这里也可以使用
        //构造查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());
        //添加条件,查询状态为1(起售状态)的菜品
        queryWrapper.eq(Dish::getStatus,1);

        //添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

        List<Dish> list = dishService.list(queryWrapper);
        return R.success(list);
    }

控制台输出的sql语句:

SELECT id,name,category_id,price,code,image,description,status,sort,create_time,update_time,create_user,update_user,is_deleted FROM dish WHERE (category_id = ? AND status = ?) ORDER BY sort ASC,update_time DESC

在这里插入图片描述

1.2 保存添加套餐

实现要求:点击保存按钮,发送ajax请求,将套餐相关的数据以json形式提交到服务端;

前端提交请求:

在这里插入图片描述

前端携带的参数:重要

在这里插入图片描述

根据前端传过来的数据我们可以在后端确定我们需要在后端使用什么来接受前端的参数;

编写controller:上面的dishList,我们数据库并不需要这个数据,所以接收数据的实体类没有dishList这个属性也没有关系,前端传过来的数据都是自动映射到接收数据的实体类的属性上的,没有对应起来就不会映射。

涉及两张表的操作:套餐表和菜品表;

    /**
     * 新增套餐
     * 涉及两张表的操作:套餐表和菜品表;
     * @param setmealDto
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody SetmealDto setmealDto){

        setmealService.saveWithDish(setmealDto);

        return R.success("新增套餐成功");
    }

SetmealService中添加自定义的方法:

/**
 * 新增套餐,同时需要保存套餐和菜品的关联关系
 * @param setmealDto
 */
void saveWithDish(SetmealDto setmealDto);
@Autowired
SetmealDishService setmealDishService;

/**
 * 新增套餐,同时需要保存套餐和菜品的关联关系
 * @param setmealDto
 */
@Transactional
@Override
public void saveWithDish(SetmealDto setmealDto) {
    //保存套餐的基本信息,操作setmeal,执行insert
    this.save(setmealDto);
    log.info(setmealDto.toString()); //查看一下这个套餐的基本信息是什么

    //保存套餐和菜品的关联信息,操作setmeal_dish ,执行insert操作
    List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
    //注意上面拿到的setmealDishes是没有setmeanlId这个的值的,通过debug可以发现
    setmealDishes.stream().map((item)->{
        item.setSetmealId(setmealDto.getId());
        return item; //这里返回的就是集合的泛型
    }).collect(Collectors.toList());

    setmealDishService.saveBatch(setmealDishes); //批量保存
}

功能测试,自己测试;

在这里插入图片描述

1.3 套餐信息分页查询

需求分析:

在这里插入图片描述

代码开发:

前端发起的请求以及携带的参数:
在这里插入图片描述

查询分页:

在这里插入图片描述

在开发代码之前,需要梳理一下套餐 分页查询时前端页面和服务端的交互过程:

  1. 页面(backend/ page/combo/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据

  2. 页面发送请求,请求服务端进行图片下载,用于页面图片展示

开发套餐信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求

controller层代码编写:

/**
 * 套餐分页查询
 * @param page
 * @param pageSize
 * @param name
 * @return
 */
@GetMapping("/page")
public R<Page> page(int page, int pageSize, String name){

    //分页构造器对象
    Page<Setmeal> pageInfo = new Page<>(page,pageSize);
    //构造条件查询对象
    LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
    //添加查询条件,根据name进行like模糊查询
    queryWrapper.like(name != null,Setmeal::getName,name);
    //添加排序条件,根据更新时间降序排列
    queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    setmealService.page(pageInfo,queryWrapper);

    /**
     * 注意如果这里直接返回R.success(pageInfo),
     * 虽然不会报错但是分页的数据的套餐分类的名字是显示不了的;
     * 因为这个分页的泛型是Setmeal,Setmeal只封装了f分类的Id categoryId,没有分类的名称 name
     * 所以又需要进行name的获取和设值
     */
    return R.success(pageInfo);
}

bug修复:

/**
 * 套餐分页查询
 * @param page
 * @param pageSize
 * @param name
 * @return
 */
@GetMapping("/page")
public R<Page> page(int page, int pageSize, String name){

    //分页构造器对象
    Page<Setmeal> pageInfo = new Page<>(page,pageSize);
    Page<SetmealDto> dtoPage = new Page<>(page,pageSize);

    //构造条件查询对象
    LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
    //添加查询条件,根据name进行like模糊查询
    queryWrapper.like(name != null,Setmeal::getName,name);
    //添加排序条件,根据更新时间降序排列
    queryWrapper.orderByDesc(Setmeal::getUpdateTime);
    setmealService.page(pageInfo,queryWrapper);

    //对象的拷贝  注意这里要把分页数据的全集合records给忽略掉
    BeanUtils.copyProperties(pageInfo,dtoPage,"records");
    List<Setmeal> records = pageInfo.getRecords();

    //对records对象进行处理然后封装好赋值给list
    List<SetmealDto> list = records.stream().map((item)->{
        SetmealDto setmealDto = new SetmealDto();

        //对setmealDto进行除categoryName的属性进行拷贝(因为item里面没有categoryName)
        BeanUtils.copyProperties(item,setmealDto);

        //获取分类id  通过分类id获取分类对象  然后再通过分类对象获取分类名
        Long categoryId = item.getCategoryId();

        //根据分类id获取分类对象  判断是否为null
        Category category = categoryService.getById(categoryId);

        if (category != null){
            String categoryName = category.getName();
            setmealDto.setCategoryName(categoryName);
        }
        return setmealDto;
    }).collect(Collectors.toList());
    dtoPage.setRecords(list);

    return R.success(dtoPage);
}

在这里插入图片描述

1.4 删除套餐

在这里插入图片描述

代码开发:

单个套餐删除前端发的请求和携带的参数:

在这里插入图片描述

套餐批量删除前端发的请求和携带的参数:

在这里插入图片描述

在这里插入图片描述

controller层开发

在SetmealService中添加自定义的方法:

/**
 * 删除套餐,同时需要删除套餐和菜品的关联数据
 * @param ids
 */
void removeWithDish(List<Long> ids);

实现该方法:

/**
 * 删除套餐,同时需要删除套餐和菜品的关联数据
 * @param ids
 */
@Override
@Transactional
public void removeWithDish(List<Long> ids) {
    //sql语句应该是这样的:select count(*) setmeal where id in () and status = 1;
    //查询套餐的状态,看是否可以删除
    LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper();
    queryWrapper.in(Setmeal::getId,ids);
    queryWrapper.eq(Setmeal::getStatus,1);
    int count = this.count(queryWrapper);
    //如果不能删除,抛出一个业务异常
    if (count > 0){
        throw new CustomException("套餐正在售卖中,不能删除");
    }
    //如果可以删除,先删除套餐表中的数据--setmeal 
    this.removeByIds(ids);
    //删除关系表中的数据--setmeal_dish
    //delete from setmeal_dish where setmeal_id in (1,2,3)
    LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper();
    lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);
    setmealDishService.remove(lambdaQueryWrapper);
}

功能测试;

在这里插入图片描述

1.5 需要自己单独实现的功能

1.5.1 套餐管理的启售、停售

前端发来的请求:

根据前面菜品模块自己实现的功能,我们可以知道,我们只需要写一个批量处理的方法就可以完成单个或者是批量套餐的启售,停售;

SetmealController中的controller层代码:

/**
 * 对菜品批量或者是单个 进行停售或者是起售
 * @return
 */
@PostMapping("/status/{status}")
//这个参数这里一定记得加注解才能获取到参数,否则这里非常容易出问题
public R<String> status(@PathVariable("status") Integer status,@RequestParam List<Long> ids){
    setmealService.updateSetmealStatusById(status,ids);
    return R.success("售卖状态修改成功");
}

SetmealService中添加下面方法:

/**
 * 根据套餐id修改售卖状态
 * @param status
 * @param ids
 */
void updateSetmealStatusById(Integer status,List<Long> ids);

该方法的实现:

/**
 * 根据套餐id修改售卖状态
 * @param status
 * @param ids
 */
@Override
public void updateSetmealStatusById(Integer status,  List<Long> ids) {
    LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper();
    queryWrapper.in(ids !=null,Setmeal::getId,ids);
    List<Setmeal> list = this.list(queryWrapper);

    for (Setmeal setmeal : list) {
        if (setmeal != null){
            setmeal.setStatus(status);
            this.updateById(setmeal);
        }
    }
}

1.5.2 套餐管理的修改

分为两步:数据回显示,和提交修改数据到数据库

前端点击套餐修改,前端发过来的请求

SetmealController 中添加下面的代码:

/**
 * 回显套餐数据:根据套餐id查询套餐
 * @return
 */
@GetMapping("/{id}")
public R<SetmealDto> getData(@PathVariable Long id){
    SetmealDto setmealDto = setmealService.getDate(id);

    return R.success(setmealDto);
}

SetmealService添加下面的代码:

/**
 * 回显套餐数据:根据套餐id查询套餐
 * @return
 */
SetmealDto getDate(Long id);

该方法的实现:

/**
 * 回显套餐数据:根据套餐id查询套餐
 * @return
 */
@Override
public SetmealDto getDate(Long id) {
    Setmeal setmeal = this.getById(id);
    SetmealDto setmealDto = new SetmealDto();
    LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper();
    //在关联表中查询,setmealdish
    queryWrapper.eq(id!=null,SetmealDish::getSetmealId,id);

    if (setmeal != null){
        BeanUtils.copyProperties(setmeal,setmealDto);
        List<SetmealDish> list = setmealDishService.list(queryWrapper);
        setmealDto.setSetmealDishes(list);
        return setmealDto;
    }
    return null;
}

测试:数据回显成功

但是这样我们再点击添加菜品会发现,右边只展示菜品的价格并没有展示菜品对应的名称:

已选菜品中的菜品并没有展示对应的菜品名;

在这里插入图片描述

修改后的运行情况展示:

在这里插入图片描述

搜索框的作用:

在这里插入图片描述
在这里插入图片描述
DishController.java修改

    @GetMapping("/list")
    public R<List<Dish>> list(Dish dish)
    {
        if(dish.getId()!=null)
        log.info(dish.getCategoryId().toString());
        if(dish.getName()!=null)
        log.info(dish.getName().toString());
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        queryWrapper.like(dish.getName()!=null,Dish::getName,dish.getName());
        queryWrapper.eq(Dish::getStatus,1);
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(queryWrapper);

        return R.success(list);
    }

controller层代码:

为了不把问题复杂化,我是先把相关的setmealDish内容移除然后再重新添加,这样就可以不用考虑dish重复的问题和哪些修改哪些没修改;

@PutMapping
public R<String> edit(@RequestBody SetmealDto setmealDto){

    if (setmealDto==null){
            return R.error("请求异常");
        }

        if (setmealDto.getSetmealDishes()==null){
            return R.error("套餐没有菜品,请添加套餐");
        }
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        Long setmealId = setmealDto.getId();

        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId,setmealId);
        setmealDishService.remove(queryWrapper);

        //为setmeal_dish表填充相关的属性
        for (SetmealDish setmealDish : setmealDishes) {
            setmealDish.setSetmealId(setmealId);
        }
        //批量把setmealDish保存到setmeal_dish表
        setmealDishService.saveBatch(setmealDishes);
        setmealService.updateById(setmealDto);

        return R.success("套餐修改成功");
}

另一套

    @Override
    public void updateWithDish(SetmealDto setmealDto) {
        this.updateById(setmealDto);
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId,setmealDto.getId());
        setmealDishService.remove(queryWrapper);
        List<SetmealDish> list = setmealDto.getSetmealDishes();
        list.stream().map((item)->{
            item.setSetmealId(setmealDto.getId());
            return item;
        }).collect(Collectors.toList());
        setmealDishService.saveBatch(list);
    }

1.5.3 后台订单展示和查询

点击订单明细,前端会发下面的请求:携带的数据是分页使查询用的;

先写个controller看能不能接收到前端传过来的参数:发现只要参数和前端传过来的参数名对应就可以拿到参数的

orders.java

package com.itheima.reggie.entity;

import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 订单
 */
@Data
public class Orders implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    //订单号
    private String number;

    //订单状态 1待付款,2待派送,3已派送,4已完成,5已取消
    private Integer status;


    //下单用户id
    private Long userId;

    //地址id
    private Long addressBookId;


    //下单时间
    private LocalDateTime orderTime;


    //结账时间
    private LocalDateTime checkoutTime;


    //支付方式 1微信,2支付宝
    private Integer payMethod;


    //实收金额
    private BigDecimal amount;

    //备注
    private String remark;

    //用户名
    private String userName;

    //手机号
    private String phone;

    //地址
    private String address;

    //收货人
    private String consignee;
}

在这里插入图片描述
OrdersMapper

package com.itheima.reggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.Orders;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OrdersMapper extends BaseMapper<Orders> {
}

OrdersService

package com.itheima.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.Orders;

public interface OrdersService extends IService<Orders> {
}

OrdersServiceImpl

package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.Orders;
import com.itheima.reggie.mapper.OrdersMapper;
import com.itheima.reggie.service.OrdersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper,Orders> implements OrdersService {
}


主要使用到mybatis-plus动态sql语句的生成:

这里我就直接把功能直接写在controller层了,看自己需求分层;(本人这里偷个懒)

    /**
     * 后台查询订单明细
     * @param page
     * @param pageSize
     * @param number
     * @param beginTime
     * @param endTime
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String number,String beginTime,String endTime){
        //分页构造器对象
        Page<Orders> pageInfo = new Page<>(page,pageSize);
        //构造条件查询对象
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();

        //添加查询条件  动态sql  字符串使用StringUtils.isNotEmpty这个方法来判断
        //这里使用了范围查询的动态SQL,这里是重点!!!
        queryWrapper.like(number!=null,Orders::getNumber,number)
                .gt(StringUtils.isNotEmpty(beginTime),Orders::getOrderTime,beginTime)
                .lt(StringUtils.isNotEmpty(endTime),Orders::getOrderTime,endTime);

        orderService.page(pageInfo,queryWrapper);
        return R.success(pageInfo);
    }

在这里插入图片描述

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

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

相关文章

qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed

方法一&#xff1a; 如果是https&#xff0c;改为http。 方法二&#xff1a; Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题-CSDN博客 其他&#xff1a;

Elasticsearch零基础实战

分享后可优化点&#xff08;待完成&#xff09; java es8 查询如何打印查询入参 &#xff1f;&#xff08;直接执行的json&#xff09; es自定义分词器 如何实现&#xff1f; kibana 监控jvm分子分母是什么 &#xff1f; es如何 改索引结构&#xff1f; 修改数据原理 分享…

JDBC-数据库连接池(druid)

一、背景 在介绍JDBC基本概念中&#xff0c;似乎Java程序每次与数据库交互都要通过驱动创建一个新的连接对象&#xff08;Connection&#xff09;&#xff0c;再由连接对象创建一个可执行SQL的Statement对象&#xff08;或PreparedStatement对象&#xff09;&#xff0c;操作完…

海康威视摄像头+服务器+录像机配置校园围墙安全侦测区域入侵侦测+越界侦测

一、适用场景 1、校园内&#xff0c;防止课外时间翻越围墙到校外、从校外翻越围墙到校内&#xff1b; 2、通过服务器摄像头的侦测功能及时抓图保存&#xff0c;为不安全因素提供数字化依据&#xff1b; 3、网络录像机保存监控视频&#xff0c;服务器保存抓拍到的入侵与越界&am…

学习笔记16——操作系统

学习笔记系列开头惯例发布一些寻亲消息&#xff0c;感谢关注&#xff01; 链接&#xff1a;https://www.mca.gov.cn/lljz/indexdetail.html?idd0afa7f6f36946319a206d61937f9b63&type0&t10.11199120579373845 八股——操作系统一些基础知识整理 一个java程序对应一个…

腾讯云com域名注册1元一年,非常可以!

腾讯云com域名注册优惠价格1元首年&#xff0c;条件是企业新用户&#xff0c;个人新用户注册com域名是33元首年&#xff0c;第二年续费价格85元一年。活动 txybk.com/go/domain-sales 活动打开如下图&#xff1a; 腾讯云com域名注册优惠价格 腾讯云com域名注册原价是85元一年&a…

*4.3 CUDA MEMORY TYPES

CUDA设备包含几种类型的内存&#xff0c;可以帮助程序员提高计算到全局内存的访问率&#xff0c;从而实现高执行速度。图4.6显示了这些CUDA设备内存。全局内存和恒定内存出现在图片的底部。主机可以通过调用API函数来写入&#xff08;W&#xff09;和读取&#xff08;R&#xf…

PHP反序列化漏洞利用及修复,示例代码讲解

您提到的PHP反序列化漏洞是一个重要的网络安全问题。在我的网络安全工程师的角色下&#xff0c;我可以提供关于此问题的深入分析。 PHP反序列化漏洞通常发生在当不可信的数据被反序列化时。序列化是将数据结构或对象状态转换为可存储或可传输的格式的过程&#xff0c;而反序列…

快速幂算法总结

知识概览 快速幂可以在O(logk)的时间复杂度之内求出来的结果。 例题展示 快速幂 题目链接 活动 - AcWing 系统讲解常用算法与数据结构&#xff0c;给出相应代码模板&#xff0c;并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/877/ 代码 #inc…

机器学习 前馈神经网络

人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;是指一系列受生物学和神经科学启发的数学模型&#xff0e;这些模型主要是通过对人脑的神经元网络进行抽象&#xff0c;构建人工神经元&#xff0c;并按照一定拓扑结构来建立人工神经元之间的连接…

一文讲透使用Python绘制双纵轴线图

双纵轴线图主要用来展示两个因变量和一个自变量的关系&#xff0c;并且两个因变量的数值单位不同。具体来说&#xff0c;双纵轴线图是指在一幅图上有一个横轴和两个纵轴&#xff0c;适用于三个变量。两个纵轴分别表示一个变量&#xff0c;横轴变量同时适用于两个纵轴上的变量&a…

Selenium-java元素等待三种方式

第二种方式需要写在创建driver时的代码下面 第三种则是对每个定位元素进行配置

Linux基础知识总结

目录 一、Linux权限设置 更改文件属性 chgrp - 更改文件属组 chown - 更改文件所有者&#xff0c;也可以同时更改文件所属组。 chmod - 更改文件属性 二、Linux文件与目录管理 处理目录的常用命令 ls&#xff08;list files&#xff09;- 列出目录及文件名 cd&#xff…

【Linux】Linux系统编程——Linux命令解析器

【Linux】Linux系统编程——Linux命令解析器 什么是Linux 命令解析器&#xff1f; Linux 命令解析器&#xff0c;通常被称为 shell&#xff0c;是 Linux 操作系统中的一个关键组件。它充当用户和系统内核之间的接口&#xff0c;允许用户通过输入命令来控制和管理操作系统和应…

【Spring Cloud】关于Nacos配置管理的详解介绍

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Spring Cloud》。&#x1f3af;&#x1f3af; &am…

Java面试汇总——redis篇

1、什么是缓存穿透 ? 怎么解决 ? 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存就形同虚设&#xff08;只有数据库查到了&#xff0c;才会让redis缓存&#xff0c;但现在的问题是查不到&#xff09;&#xff0c;会频繁的去访问数据库。 解决…

关键字:package关键字

在 Java 中&#xff0c;package关键字用于组织和管理类文件。它将类文件分组到不同的包中&#xff0c;以提供更好的代码组织和可读性。 以下是package关键字的用法&#xff1a; 1.package语句&#xff1a;在 Java 源代码的开头使用package关键字来声明当前类所属的包。例如&a…

基于yolov5的PCB板缺陷检测(附有详细步骤通俗易懂版)

PCB板缺陷检测 模型训练 在初学的时候&#xff0c;可能不太了解到底模型训练是个什么流程&#xff0c;到底是什么意思。其实也很简单&#xff0c;就是我们用一个框架&#xff08;如pytorch&#xff0c;tensorflow等&#xff09;通过一定的算法如yolov5&#xff0c;对一定的数…

Python笔记07-异常、模块和包

文章目录 异常及捕获方法python模块python包安装第三方包 异常及捕获方法 当检测到一个错误时&#xff0c;Python解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的“异常”, 也就是我们常说的BUG 例如&#xff1a;以r方式打开一个不存在的…

有没有一个完美的葡萄酒饮用温度呢?

我们很多人都有一个简单的冷藏葡萄酒的方法&#xff0c;把白葡萄酒扔进冰箱&#xff0c;在室温下饮用红葡萄酒。虽然这很容易&#xff0c;但会导致红葡萄酒上桌时温度过高&#xff0c;白葡萄酒上桌时温度过低。为了帮助你从你的葡萄酒收藏中获得最长的寿命、香气和风味&#xf…