蒼穹外賣學習 Day10 Day11 Day12

前言

用于記錄蒼穹外賣Day10、Day11、Day12的學習

Day10 訂單狀態定時處理 來電提醒 客戶催單

訂單狀態定時處理

Spring Task

Spring Task是一個任務調度工具,可以按照約定的時間自動執行某個代碼邏輯(定時自動執行某段Java代碼)

cron表達式

cron表達式其實就是一個字符串,通過cron表達式可以定義任務觸發的時間。

構成規則:分為6或7個域,用空格隔開,每個域代表一個含義。從左到右依次為秒、分鐘、小時、日、月、周、年(可選)

在這里插入圖片描述

cron在線生成器:https://cron.qqe2.com

Spring Task使用步驟

  • 導入坐標spring-context
  • 啟動類添加注解@EnableScheduling開啟任務調度
  • 自定義定時任務類

需求開發

存在的問題:

  • 下單后未支付,訂單一直處于”待支付“狀態
  • 用戶收貨后管理端未點擊完成按鈕,訂單一直處于”派送中“狀態

只需自定義個任務處理類來定時處理即可:

//定時任務類,定時處理訂單狀態
@Component
@Slf4j
public class OrderTask {@Autowiredprivate OrderMapper orderMapper;//處理下單后未支付超時的情況@Scheduled(cron = "0 * * * * ? *")//每分鐘觸發一次
//    @Scheduled(cron="0/5 * * * * ?")public void processTimeOut(){log.info("定時處理下單未支付的訂單");//當前時間減15分鐘LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(-15);List<Orders> list = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, localDateTime);if(list!=null&&list.size()>0){for (Orders orders : list) {orders.setStatus(Orders.CANCELLED);orders.setConsignee("訂單超時,自動取消");orders.setCancelTime(LocalDateTime.now());orderMapper.update(orders);}}}//處理一直處于派送中,沒有完成的訂單@Scheduled(cron = "0 0 1 * * ?")//每天凌晨一點觸發
//    @Scheduled(cron="0/10 * * * * ?")public void processDeliveryOrder(){log.info("定時處理一直在派送的訂單");LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(-60);List<Orders> list = orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, localDateTime);if(list!=null&&list.size()>0){for (Orders orders : list) {orders.setStatus(Orders.COMPLETED);orderMapper.update(orders);}}}
}

來電提醒

WebSocket

WebSocket是基于TCP的一種新的網絡協議。它實現了瀏覽器與服務器全雙工通信–瀏覽器和服務器只需完成一次握手,兩者之間即可建立持久性的連接,并進行雙向數據傳輸

WebSocket和HTTP對比:

  • HTTP是短連接;WebSocket是長連接
  • HTTP是單向通信,基于請求響應模型;WebSocket支持雙向通信。
  • WebSocket和HTTP都是基于TCP協議

應用場景:

  • 視頻彈幕
  • 實況更新
  • 網頁聊天

需求開發

實現思路:

  • 通過WebSocket實現管理端頁面和服務端保持長連接
  • 當客戶支付后,調用WebSocket的相關API從服務端向客戶端推送消息
  • 客戶端解析服務端發送的消息,判斷是來電提醒還是客戶催單,并進行相應的語音播報
  • 約定服務端向客戶端發送的消息的數據格式為JSON,字段包括:type(消息類型,1為來單提醒、2為客戶催單)、orderId、content(消息內容)

這里我們只需要在支付成功后提示管理端即可,在OrderServiceImpl的paySuccess方法中:

		//通過WebSocket向客戶端瀏覽器推送數據Map map=new HashMap();map.put("type",1);map.put("orderId",ordersDB.getId());map.put("content","訂單號:"+outTradeNo);String Json= JSON.toJSONString(map);webSocketServer.sendToAllClient(Json);

注意:啟動項目的時候看看你是否連接上WebSocket,如果沒連接上可能是因為自己修改過端口號的問題,將端口號改回80或者改下前端代碼即可。

客戶催單

實現思路和來電提醒差不多。當用戶在客戶端點擊催單按鈕時,發起請求

  • OrderController
	@GetMapping("/reminder/{id}")@ApiOperation("客戶催單")public Result reminder(@PathVariable Long id){orderService.reminder(id);return Result.success();}
  • OrderServiceImpl
	public void reminder(Long id) {// 根據id查詢訂單Orders orders1= orderMapper.getById(id);// 校驗訂單是否存在if (orders1 == null) {throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);}//通過WebSocket向客戶端瀏覽器推送數據Map map=new HashMap();map.put("type",2);map.put("orderId",id);map.put("content","訂單號:"+orders1.getNumber());String Json= JSON.toJSONString(map);webSocketServer.sendToAllClient(Json);}

Day11 數據統計-圖形報表

效果如下所示:

在這里插入圖片描述

在這里插入圖片描述

Apache ECharts

Apache ECharts是一款基于JavaScript的數據可視化圖表庫,提供直觀、生動、可交互、可個性化定制的數據可視化圖表。簡單來說,它就是一款數據可視化工具。我們只需大致知道它是干啥的,它是在前端使用的,后端開發中我們使用不到。

營業額統計

業務規則:

  • 營業額指訂單狀態為已完成的訂單金額合計
  • 基于可視化報表的折線圖展示營業額數據,x軸為日期,y軸為營業額
  • 根據時間選擇區間,展示每天的營業額數據

ReportController:注意時間的數據格式

@RestController
@Slf4j
@RequestMapping("/admin/report")
@Api(tags = "數據統計相關接口")
public class ReportController {@Autowiredprivate ReportService reportService;@GetMapping("/turnoverStatistics")@ApiOperation("營業額統計")public Result<TurnoverReportVO> turnoverStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("營業額數據統計:{},{}",begin,end);TurnoverReportVO turnoverReportVO=reportService.getTurnoverStatistics(begin,end);return Result.success(turnoverReportVO);}
}

ReportServiceImpl:

這里我的實現方法與課程中略有不同,可以參考一下

public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {TurnoverReportVO turnoverReportVO=new TurnoverReportVO();//1.封裝日期數據//先去得到一個日期集合,包含begin到end中的所有日期List<LocalDate> dateList=new ArrayList<>();dateList.add(begin);while(!begin.equals(end)){begin=begin.plusDays(1);dateList.add(begin);}//將集合轉成字符串的同時在每個元素間加一個逗號String dateList1=StringUtils.join(dateList,",");turnoverReportVO.setDateList(dateList1);//2.封裝營業額數據//查詢對應日期的訂單的總營業額List<Double> moneyList=new ArrayList<>();for (LocalDate localDate : dateList) {//根據日期查詢狀態為已完成的訂單的營業額//00:00:00LocalDateTime beginTime=LocalDateTime.of(localDate, LocalTime.MIN);//23:59:59LocalDateTime endTime=LocalDateTime.of(localDate, LocalTime.MAX);Map map=new HashMap();map.put("begin",beginTime);map.put("end",endTime);map.put("status", Orders.COMPLETED);Double money=orderMapper.getSumByMap(map);if(money==null){money=0.0;}moneyList.add(money);}String moneyList1=StringUtils.join(moneyList,",");turnoverReportVO.setTurnoverList(moneyList1);return turnoverReportVO;}

用戶統計

ReportController:

@GetMapping("/userStatistics")@ApiOperation("用戶統計")public Result<UserReportVO> userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("用戶統計:{},{}",begin,end);UserReportVO userReportVO=reportService.getUserStatistics(begin,end);return Result.success(userReportVO);}

ReportServiceImpl:

//用戶數據統計public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {UserReportVO userReportVO=new UserReportVO();//1.封裝日期數據//先去得到一個日期集合,包含begin到end中的所有日期List<LocalDate> dateList=new ArrayList<>();dateList.add(begin);while(!begin.equals(end)){begin=begin.plusDays(1);dateList.add(begin);}//將集合轉成字符串的同時在每個元素間加一個逗號String dateList1=StringUtils.join(dateList,",");userReportVO.setDateList(dateList1);//2.封裝用戶總量數據List<Integer> totalList=new ArrayList<>();//3.封裝新增用戶數量數據List<Integer> newList=new ArrayList<>();for (LocalDate localDate : dateList) {//查詢用戶表createTime這一天的用戶的總量//00:00:00LocalDateTime beginTime=LocalDateTime.of(localDate, LocalTime.MIN);//23:59:59LocalDateTime endTime=LocalDateTime.of(localDate, LocalTime.MAX);Map map=new HashMap();map.put("end",endTime);Integer total=userMapper.countByMap(map);if(total==null){total=0;}totalList.add(total);map.put("begin",beginTime);Integer today= userMapper.countByMap(map);if(today==null){today=0;}newList.add(today);}String userList1=StringUtils.join(totalList,",");userReportVO.setTotalUserList(userList1);String list1=StringUtils.join(newList,",");userReportVO.setNewUserList(list1);return userReportVO;}

訂單統計

業務規則:

  • 兩條折線,一條代表總訂單數,另一條代表有效訂單數(狀態為已完成的訂單)
  • 展示訂單總數、有效訂單數、訂單完成率數據

ReportController:

@GetMapping("/ordersStatistics")@ApiOperation("訂單統計")public Result<OrderReportVO> orderStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("訂單統計:{},{}",begin,end);OrderReportVO orderReportVO=reportService.getOrderReportStatistics(begin,end);return Result.success(orderReportVO);}

ReportServiceImpl:

@Overridepublic OrderReportVO getOrderReportStatistics(LocalDate begin, LocalDate end) {OrderReportVO orderReportVO=new OrderReportVO();//1.封裝日期數據List<LocalDate> dateList=new ArrayList<>();dateList.add(begin);while(!begin.equals(end)){begin=begin.plusDays(1);dateList.add(begin);}//將集合轉成字符串的同時在每個元素間加一個逗號String dateList1=StringUtils.join(dateList,",");orderReportVO.setDateList(dateList1);//2.訂單總數List<Integer> totalOrder=new ArrayList<>();//3.有效訂單數List<Integer> realOrder=new ArrayList<>();//每天的訂單總數以及有效訂單數for (LocalDate localDate : dateList) {//00:00:00LocalDateTime beginTime=LocalDateTime.of(localDate, LocalTime.MIN);//23:59:59LocalDateTime endTime=LocalDateTime.of(localDate, LocalTime.MAX);Map map=new HashMap();map.put("begin",beginTime);map.put("end",endTime);Integer total=orderMapper.getByMap(map);if(total==null){total=0;}totalOrder.add(total);map.put("status",Orders.COMPLETED);Integer real=orderMapper.getByMap(map);if(real==null){real=0;}realOrder.add(real);}String totalOrder1=StringUtils.join(totalOrder,",");String realOrder1=StringUtils.join(realOrder,",");//計算時間區間內的訂單總數量Integer sum=0;for (Integer integer : totalOrder) {sum+=integer;}//計算時間區間內的有效訂單數量Integer real=0;for (Integer integer : realOrder) {real+=integer;}//計算訂單完成率double orderCompletionRate=0.0;if (sum!=0) {orderCompletionRate= (double) real /sum;}orderReportVO.setOrderCompletionRate(orderCompletionRate);orderReportVO.setOrderCountList(totalOrder1);orderReportVO.setValidOrderCountList(realOrder1);orderReportVO.setTotalOrderCount(sum);orderReportVO.setValidOrderCount(real);System.out.println(orderReportVO);return orderReportVO;}

銷量排名統計

ReportController:

@GetMapping("/top10")@ApiOperation("銷量排名top10")public Result<SalesTop10ReportVO> top10(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){log.info("銷量排名top10:{},{}",begin,end);SalesTop10ReportVO salesTop10ReportVO=reportService.getTop10(begin,end);return Result.success(salesTop10ReportVO);}

ReportServiceImpl:

public SalesTop10ReportVO getTop10(LocalDate begin, LocalDate end) {SalesTop10ReportVO salesTop10ReportVO=new SalesTop10ReportVO();//00:00:00LocalDateTime beginTime=LocalDateTime.of(begin, LocalTime.MIN);//23:59:59LocalDateTime endTime=LocalDateTime.of(end, LocalTime.MAX);List<GoodsSalesDTO> goodsSalesDTOList=orderMapper.getSalesTop10(beginTime,endTime);//遍歷取出DTO中的numa和number放到對應的集合中去List<String> nameList=new ArrayList<>();List<String> numberList=new ArrayList<>();for (GoodsSalesDTO goodsSalesDTO : goodsSalesDTOList) {nameList.add(goodsSalesDTO.getName());numberList.add(String.valueOf(goodsSalesDTO.getNumber()));}String nameLists=StringUtils.join(nameList,",");String numberLists=StringUtils.join(numberList,",");salesTop10ReportVO.setNameList(nameLists);salesTop10ReportVO.setNumberList(numberLists);return salesTop10ReportVO;}

OrderMapper.xml:

分析一下這里的SQL語句,因為我們要根據訂單狀態(對應orders表中的status)查訂單的名稱以及數量(對應order_details表中的number),所以涉及到聯表查詢。查詢前10,所以只需limit 0,10

	<!--統計銷量前10--><select id="getSalesTop10" resultType="com.sky.dto.GoodsSalesDTO">select od.name,sum(od.number) number from order_detail od,orders o where od.id=o.id and o.status=5<if test="begin!=null">and order_time &gt; #{begin}</if><if test="end!=null">and order_time &lt; #{end}</if>group by od.name order by number desc limit 0,10</select>

Day12 數據統計-Excel報表

工作臺

這里課程中的代碼是直接導入的,我還是選擇手敲一遍。

工作臺展示的數據:

  • 今日數據
  • 訂單管理
  • 菜品總覽
  • 套餐總覽
  • 訂單信息

為了簡便展示,這里我直接給出一個類中的全部代碼了,可以根據注釋理解。

  • WorkSpaceController
@RestController
@RequestMapping("/admin/workspace")
@Slf4j
@Api(tags = "工作臺相關接口")
public class WorkSpaceController {@Autowiredprivate WorkSpaceService workSpaceService;//查詢工作臺今日數據@GetMapping("/businessData")@ApiOperation("查詢工作臺今日數據")public Result<BusinessDataVO> businessData(){log.info("查詢工作臺今日數據");//獲取開始時間LocalDateTime beginTime=LocalDateTime.now().with(LocalTime.MIN);//獲取結束時間LocalDateTime endTime=LocalDateTime.now().with(LocalTime.MAX);BusinessDataVO businessDataVO=workSpaceService.getBusinessData(beginTime,endTime);return Result.success(businessDataVO);}//查詢訂單管理數據@GetMapping("/overviewOrders")@ApiOperation("查詢訂單管理數據")public Result<OrderOverViewVO> overViewOrders(){log.info("查詢訂單管理數據");return Result.success(workSpaceService.getOrderOverView());}//查詢菜品總覽@GetMapping("/overviewDishes")@ApiOperation("查詢菜品總覽")public Result<DishOverViewVO> overViewDishes(){return Result.success(workSpaceService.getDishOverView());}//查詢套餐總覽@GetMapping("/overviewSetmeals")@ApiOperation("查詢套餐總覽")public Result<SetmealOverViewVO> overViewSetmeal(){return Result.success(workSpaceService.getSetmealOvermeal());}
}
  • WorkSpaceService
public interface WorkSpaceService {BusinessDataVO getBusinessData(LocalDateTime beginTime, LocalDateTime endTime);OrderOverViewVO getOrderOverView();DishOverViewVO getDishOverView();SetmealOverViewVO getSetmealOvermeal();
}
  • WorkSpaceServiceImpl(這里很多方法我們都在OrderMapper中已經寫好了,直接調用即可)
@Service
public class WorkSpaceServiceImpl implements WorkSpaceService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate UserMapper userMapper;@Autowiredprivate DishMapper dishMapper;@Autowiredprivate SetmealMapper setmealMapper;//查詢工作臺今日數據public BusinessDataVO getBusinessData(LocalDateTime beginTime, LocalDateTime endTime) {BusinessDataVO businessDataVO=new BusinessDataVO();Map map=new HashMap();map.put("begin",beginTime);map.put("end",endTime);//訂單總數Integer total=orderMapper.getByMap(map);map.put("status",5);//營業額Double sum = orderMapper.getSumByMap(map);sum = sum == null? 0.0 : sum;//有效訂單數Integer real=orderMapper.getByMap(map);//平均客單價double average=0.0;//訂單完成率double complete=0.0;if(total!=0&&real!=0){complete= (double) real /total;average=sum/real;}//新增用戶數Integer newUser=userMapper.countByMap(map);businessDataVO.setTurnover(sum);businessDataVO.setNewUsers(newUser);businessDataVO.setOrderCompletionRate(complete);businessDataVO.setValidOrderCount(real);businessDataVO.setUnitPrice(average);return businessDataVO;}//查詢訂單管理數據@Overridepublic OrderOverViewVO getOrderOverView() {OrderOverViewVO orderOverViewVO=new OrderOverViewVO();Map map = new HashMap();map.put("begin", LocalDateTime.now().with(LocalTime.MIN));//待接單map.put("status", Orders.TO_BE_CONFIRMED);Integer status1=orderMapper.getByMap(map);//待派送map.put("status",Orders.CONFIRMED);Integer status2=orderMapper.getByMap(map);//已完成map.put("status",Orders.COMPLETED);Integer status3=orderMapper.getByMap(map);//已取消map.put("status",Orders.CANCELLED);Integer status4=orderMapper.getByMap(map);//全部訂單map.put("status",null);Integer status5=orderMapper.getByMap(map);orderOverViewVO.setWaitingOrders(status1);orderOverViewVO.setDeliveredOrders(status2);orderOverViewVO.setCompletedOrders(status3);orderOverViewVO.setCancelledOrders(status4);orderOverViewVO.setAllOrders(status5);return orderOverViewVO;}//查詢菜品總覽@Overridepublic DishOverViewVO getDishOverView() {DishOverViewVO dishOverViewVO=new DishOverViewVO();Integer on=dishMapper.onStatus();Integer off=dishMapper.offStatus();dishOverViewVO.setSold(on);dishOverViewVO.setDiscontinued(off);return dishOverViewVO;}//查詢套餐總覽@Overridepublic SetmealOverViewVO getSetmealOvermeal() {SetmealOverViewVO setmealOverViewVO=new SetmealOverViewVO();Integer on=setmealMapper.onStatus();Integer off=setmealMapper.offStatus();setmealOverViewVO.setSold(on);setmealOverViewVO.setDiscontinued(off);return setmealOverViewVO;}
}
  • DishMapper(這里是SQL語句少我使用這種方法,標準的應該是使用動態SQL)
	@Select("select count(id) from dish where status=1")Integer onStatus();@Select("select count(id) from dish where status=0")Integer offStatus();
  • SetmealMapper
	@Select("select count(id) from setmeal where status=1")Integer onStatus();@Select("select count(id) from setmeal where status=0")Integer offStatus();

Apache POI

簡介:Apache POI可以處理Office的各種文件格式。允許我們使用POI在Java程序中對Office文件進行讀寫操作。一般用于處理Excel文件。

實例:

寫入Excel文件:

		//在內存中創建一個excel文件XSSFWorkbook excel=new XSSFWorkbook();//在excel文件中創建一個sheet頁同時指定其名稱為infoXSSFSheet sheet=excel.createSheet("info");//創建行對象,行和列都從0開始,這里我們指定1表示是第二行XSSFRow row= sheet.createRow(1);//創建單元格并寫入內容row.createCell(1).setCellValue("姓名");row.createCell(2).setCellValue("愛好");row= sheet.createRow(2);//創建單元格并寫入內容row.createCell(1).setCellValue("張三");row.createCell(2).setCellValue("籃球");row= sheet.createRow(3);//創建單元格并寫入內容row.createCell(1).setCellValue("李四");row.createCell(2).setCellValue("游泳");//通過輸出流將內存中的Excel文件寫入到磁盤中FileOutputStream out=new FileOutputStream(new File("E:\\Takeout\\info.xlsx"));excel.write(out);out.close();excel.close();

讀取Excel文件:

		InputStream in=new FileInputStream(new File("E:\\Takeout\\info.xlsx"));//讀取磁盤上已經存在的Excel文件XSSFWorkbook excel=new XSSFWorkbook(in);//讀取Excel文件中第一個Sheet頁XSSFSheet sheet= excel.getSheetAt(0);//獲取Sheet頁中最后一行的的行號(有內容的最后一行)int lastRowNum=sheet.getLastRowNum();for (int i = 1; i <= lastRowNum; i++) {//獲取某一行XSSFRow row= sheet.getRow(i);//獲取單元格對象String stringCellValue1 = row.getCell(1).getStringCellValue();String stringCellValue2 = row.getCell(2).getStringCellValue();System.out.println(stringCellValue1+" "+stringCellValue2);}excel.close();in.close();

導出Excel報表

業務規則:

  • 導出Excel文件形式的報表文件
  • 導出進30天的運營數據

實現步驟:

  • 設計Excel模板文件
  • 查詢近30日的運營數據
  • 將查詢到的運營數據寫入模板文件內
  • 通過輸出流將Excel文件下載到客戶端瀏覽器

實現:

  • ReportController
	@GetMapping("/export")@ApiOperation("導出Excel報表")public Result export(HttpServletResponse response){log.info("導出Excel報表");reportService.export(response);return Result.success();}
  • ReportServiceImpl
	//導出運營數據報表@Overridepublic void export(HttpServletResponse response) {//1.查詢數據庫,獲取近30日的營業數據LocalDate dateBegin=LocalDate.now().minusDays(30);LocalDate dateEnd=LocalDate.now().minusDays(1);//查詢概覽數據BusinessDataVO businessDataVO=workSpaceService.getBusinessData(LocalDateTime.of(dateBegin,LocalTime.MIN),LocalDateTime.of(dateEnd,LocalTime.MAX));//2.通過POI將數據寫入Excel文件中InputStream in=this.getClass().getClassLoader().getResourceAsStream("template/運營數據報表模板.xlsx");try{//基于模板文件創建一個新的Excel文件XSSFWorkbook excel=new XSSFWorkbook(in);//獲取報表文件的Sheet頁XSSFSheet sheet= excel.getSheet("Sheet1");//填充概覽數據-時間sheet.getRow(1).getCell(1).setCellValue("時間:"+dateBegin+"到"+dateEnd);//填充概覽數據其他數據//第四行XSSFRow row= sheet.getRow(3);row.getCell(2).setCellValue(businessDataVO.getTurnover());row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());row.getCell(6).setCellValue(businessDataVO.getNewUsers());//第五行row= sheet.getRow(4);row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());row.getCell(4).setCellValue(businessDataVO.getUnitPrice());for (int i=0;i<30;i++){LocalDate date=dateBegin.plusDays(i);//查詢莫一天的數據BusinessDataVO businessDataVO1=workSpaceService.getBusinessData(LocalDateTime.of(date,LocalTime.MIN),LocalDateTime.of(date,LocalTime.MAX));//獲取某一行并填充數據row= sheet.getRow(7+i);row.getCell(1).setCellValue(businessDataVO1.toString());row.getCell(2).setCellValue(businessDataVO1.getTurnover());row.getCell(3).setCellValue(businessDataVO1.getValidOrderCount());row.getCell(4).setCellValue(businessDataVO1.getOrderCompletionRate());row.getCell(5).setCellValue(businessDataVO1.getUnitPrice());row.getCell(6).setCellValue(businessDataVO1.getNewUsers());}//3.通過輸出流將Excel文件下載到客戶端瀏覽器ServletOutputStream out= response.getOutputStream();excel.write(out);//關閉資源out.close();excel.close();}catch (Exception e){e.printStackTrace();}

這里我們需要注意的一個地方,這里老師沒有加上這個后綴,不加的話我這里會報錯:

在這里插入圖片描述
蒼穹外賣的學習就到這里啦,完結撒花!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/716858.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/716858.shtml
英文地址,請注明出處:http://en.pswp.cn/news/716858.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

代碼隨想錄算法訓練營第三十天| 回溯篇總結

文章目錄 前言一、組合問題二、切割問題三、子集問題四、排列問題五、性能分析總結 前言 回溯法就是暴力搜索&#xff0c;并不是什么高效的算法&#xff0c;最多再剪枝一下。 組合問題&#xff1a;N個數里面按一定規則找出k個數的集合 排列問題&#xff1a;N個數按一定規則全…

【黑馬程序員】STL之set和map容器

文章目錄 set/multiset容器set基本概念簡介區別 set的構造和賦值功能描述函數原型代碼示例運行結果 set的大小和交換功能描述函數原型代碼示例運行結果 set的插入和刪除功能描述函數原型代碼示例運行結果 set查找和統計函數原型代碼示例運行結果 set和multiset區別區別代碼示例…

JVM(6)

JMM JVM定義了一種Java內存模型來屏蔽掉各種硬件和操作系統的內存訪問差異,以實現讓Java程序在各種平臺下都能達到一致的內存訪問效果.在此之前,C/C直接使用物理硬件和操作系統的內存模型,因此,會由于不同平臺下的內存模型差異,有可能導致程序在一套平臺上并發完全正常,而在另…

深入解剖指針(4)

個人主頁&#xff08;找往期文章包括但不限于本期文章中不懂的知識點&#xff09;&#xff1a; 我要學編程(?_?)-CSDN博客 目錄 回調函數 qsort使用舉例 使用qsort函數排序整型數據 使用qsort排序結構數據 qsort函數的模擬實現 回調函數 回調函數就是一個通過函數指…

【Android12】Android性能調優工具SystemServerTiming日志

Android性能調優工具SystemServerTiming日志 性能優化、穩定性優化是Android系統優化的兩大方面&#xff0c;對于性能調試Android提供了很多工具&#xff0c;比如&#xff1a;bootchart、systrace、perfboot、log、dmsg等等。 SystemServerTiming是Android原生系統中一個日志…

《Spring Security 簡易速速上手小冊》第10章 未來趨勢與高級話題(2024 最新版)

文章目錄 10.1 云原生安全性趨勢10.1.1 基礎知識10.1.2 重點案例&#xff1a;保護微服務通信10.1.3 拓展案例 1&#xff1a;容器安全最佳實踐10.1.4 拓展案例 2&#xff1a;自動化安全審計和合規性檢查 10.2 反應式編程與 Spring Security10.2.1 基礎知識10.2.2 重點案例&#…

nginx-圖片模塊

./configure --with-http_image_filter_module location / {root html;index index.html index.htm;if ($arg_w "") {set $arg_w -;}if ($arg_h "") {set $arg_h -;}image_filter resize $arg_w $arg_h;image_filter_jpeg_quality 95; } 訪問: 1234…

CSS錐形漸變:conic-gradient()

畫一個扇形圖&#xff0c;使用常規方法可能很難畫&#xff0c;但是用錐形漸變的話非常好畫 <style>.pattern{width: 100px; height: 100px;border-radius: 50%;background: conic-gradient(yellow 30deg , black 30deg , black 90deg , yellow 90deg ,yellow 150d…

Git分布式版本控制系統——git學習準備工作

一、Git倉庫介紹 開發者可以通過Git倉庫來存儲和管理文件代碼&#xff0c;Git倉庫分為兩種&#xff1a; 本地倉庫&#xff1a;開發人員自己電腦上的Git倉庫 遠程倉庫&#xff1a;遠程服務器上的Git倉庫 倉庫之間的運轉如下圖&#xff1a; commit&#xff1a;提交&#xff…

Decoupled Knowledge Distillation解耦知識蒸餾

Decoupled Knowledge Distillation解耦知識蒸餾 現有的蒸餾方法主要是基于從中間層提取深層特征&#xff0c;而忽略了Logit蒸餾的重要性。為了給logit蒸餾研究提供一個新的視角&#xff0c;我們將經典的KD損失重新表述為兩部分&#xff0c;即目標類知識蒸餾&#xff08;TCKD&a…

c++之旅——第四彈

大家好啊&#xff0c;這里是c之旅第三彈&#xff0c;跟隨我的步伐來開始這一篇的學習吧&#xff01; 如果有知識性錯誤&#xff0c;歡迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 創作不易&#xff0c;希望大家多多支持哦&#xff01; 本篇文章的主…

如何對比 MySQL 主備數據的一致性?

隨著業務范圍的擴大&#xff0c;很多企業為了保障核心業務的高可用性&#xff0c;選擇了 MySQL 主從架構&#xff0c;這一套方案通常具備主備數據同步、數據備份與恢復、讀寫分離、高可用切換等特性&#xff0c;是一種相當成熟可靠的數據庫架構方案。然而這套方案在特定情況下可…

Redis小白入門教程

Redis入門教程 1. Redis入門1.1 Redis簡介1.2 Redis服務啟動與停止1.2.1 Redis下載1.2.2 服務啟動命令1.2.3 客戶端連接命令1.2.4 修改Redis配置文件 2. Redis數據類型2.1 五種常用數據類型介紹2.1.1 字符串操作命令2.1.2 哈希操作命令2.1.3 列表操作命令2.1.4 集合操作命令2.1…

雙周回顧#006 - 這三個月

斷更啦~~ 上次更新時間 2023/11/23, 斷更近三個月的時間。 先狡辯下&#xff0c;因為忙、著實忙。因為忙&#xff0c;心安理得給斷更找了個借口&#xff0c;批評下自己~~ 這三個月在做啥&#xff1f;跨部門援助&#xff0c;支援公司互聯網的 ToC 項目&#xff0c;一言難盡。 …

智能時代:人工智能引領未來創新

智能時代&#xff1a;人工智能引領未來創新 1. 人工智能的定義與特點 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是指模擬、延伸和擴展人類智能的理論、方法、技術及應用系統的一門交叉學科。其特點包括學習能力、推理能力、感知能力和交互能力…

【C語言】InfiniBand 驅動mlx4_ib_init和mlx4_ib_cleanup

一、中文講解 這兩個函數是Linux內核模塊中對于Mellanox InfiniBand 驅動程序初始化和清理的函數。 mlx4_ib_init()函數是模塊初始化函數&#xff0c;使用__init宏標注&#xff0c;表示該函數只在模塊加載時運行一次。 函數執行的步驟如下&#xff1a; 1. 通過alloc_ordered_w…

數據結構——lesson5棧和隊列詳解

hellohello~這里是土土數據結構學習筆記&#x1f973;&#x1f973; &#x1f4a5;個人主頁&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所屬專欄&#xff1a;數據結構學習筆記 &#x1f4a5;對于順序表鏈表有疑問的都可以在上面數據結構的專欄進行學習哦~感謝大家的觀看與…

ElasticSearch開篇

1.ElasticSearch簡介 1.1 ElasticSearch&#xff08;簡稱ES&#xff09; Elasticsearch是用Java開發并且是當前最流行的開源的企業級搜索引擎。能夠達到實時搜索&#xff0c;穩定&#xff0c;可靠&#xff0c;快速&#xff0c;安裝使用方便。 1.2 ElasticSearch與Lucene的關…

Angular項目升級的一般步驟?

升級Angular項目是一個重要的任務&#xff0c;可以帶來性能改進、新功能和安全性增強等好處。以下是升級Angular項目的一般步驟&#xff1a; 1、備份項目文件&#xff1a; 在進行升級之前&#xff0c;務必對整個項目進行備份&#xff0c;以防意外情況發生。 2、查看當前版本&…

如何快速遷移其他云服務器中的網站數據到騰訊云輕量應用服務器中?教你使用寶塔Linux面板遷移網站

要快速遷移其他云服務器中的網站數據到騰訊云輕量應用服務器中&#xff0c;可以遵循以下步驟&#xff1a; 準備遷移前的工作&#xff1a;首先&#xff0c;確保你已經有了從其他云服務器到騰訊云輕量應用服務器的數據備份。這一步是為了在遷移過程中避免數據丟失或損壞。 使用寶…