Java网约车项目实战:实现抢单功能详解
在网约车项目中,抢单功能是非常关键的一部分,它决定了司机能否及时响应乘客的订单,提高整个平台的运营效率。本文将详细介绍如何使用Java来实现网约车项目的抢单功能,并提供一个完整的代码示例,以便读者能够直接运行和参考。
一、项目背景与需求分析
1.项目背景
随着移动互联网的快速发展,网约车已成为人们日常出行的重要选择。一个高效的网约车平台,除了需要提供良好的用户注册、登录、下单等功能外,还需要确保司机能够迅速响应乘客的订单,即实现抢单功能。
2.需求分析
- 乘客端:乘客可以发布订单,并查看订单状态(如待抢单、已抢单、已完成等)。
- 司机端:司机可以查看当前附近的订单,并选择抢单。抢单成功后,司机需前往乘客指定的地点接乘客。
- 后台管理:管理员可以查看所有订单和司机的状态,进行必要的调度和管理。
二、技术选型与架构设计
1.技术选型
- 后端:Java(Spring Boot框架)
- 数据库:MySQL
- 缓存:Redis(用于实现分布式锁,确保抢单操作的原子性)
- 前端:Vue.js(乘客端和司机端界面)
- 通信协议:HTTP/HTTPS(使用RESTful API进行前后端通信)
2.架构设计
- 乘客端:负责接收乘客的输入,将订单信息发送到后端服务器。
- 司机端:显示附近的订单列表,提供抢单功能,将抢单请求发送到后端服务器。
- 后端服务器:处理乘客和司机的请求,存储订单信息,管理司机状态,实现抢单逻辑。
- 数据库:存储乘客、司机、订单等信息。
- Redis:用于实现分布式锁,确保在并发情况下只有一个司机能够成功抢单。
三、数据库设计
1.乘客表(passenger)
字段名 | 类型 | 备注 |
---|---|---|
id | INT | 主键,自增 |
name | VARCHAR | 乘客姓名 |
phone | VARCHAR | 乘客手机号 |
password | VARCHAR | 乘客密码 |
address | VARCHAR | 乘客地址 |
2.司机表(driver)
字段名 | 类型 | 备注 |
---|---|---|
id | INT | 主键,自增 |
name | VARCHAR | 司机姓名 |
phone | VARCHAR | 司机手机号 |
password | VARCHAR | 司机密码 |
status | INT | 司机状态(0:空闲,1:已抢单) |
3.订单表(order)
字段名 | 类型 | 备注 |
---|---|---|
id | INT | 主键,自增 |
passenger_id | INT | 乘客ID |
start_address | VARCHAR | 起始地址 |
end_address | VARCHAR | 目的地址 |
status | INT | 订单状态(0:待抢单,1:已抢单,2:已完成) |
driver_id | INT | 抢单司机ID(为空表示待抢单) |
四、后端实现
1.创建Spring Boot项目
使用Spring Initializr创建一个Spring Boot项目,选择所需的依赖(如Spring Web、Spring Data JPA、MySQL Driver等)。
2.配置数据库连接
在application.properties
文件中配置数据库连接信息:
spring.datasource.url=jdbc:mysql://localhost:3306/ride_sharing?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
3.创建实体类
// Passenger.java
@Entity
public class Passenger {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String phone;private String password;private String address;// Getters and Setters
}// Driver.java
@Entity
public class Driver {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String phone;private String password;private Integer status = 0; // 0: 空闲, 1: 已抢单// Getters and Setters
}// Order.java
@Entity
public class Order {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Long passengerId;private String startAddress;private String endAddress;private Integer status = 0; // 0: 待抢单, 1: 已抢单, 2: 已完成private Long driverId; // 为空表示待抢单// Getters and Setters
}
4.创建Repository接口
// PassengerRepository.java
public interface PassengerRepository extends JpaRepository<Passenger, Long> {}// DriverRepository.java
public interface DriverRepository extends JpaRepository<Driver, Long> {}// OrderRepository.java
public interface OrderRepository extends JpaRepository<Order, Long> {}
5.实现抢单逻辑
为了实现抢单功能的原子性,我们需要使用Redis来实现分布式锁。以下是实现抢单逻辑的Service类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate DriverRepository driverRepository;@Autowiredprivate StringRedisTemplate redisTemplate;private static final String LOCK_KEY = "order_lock:";private static final int LOCK_EXPIRE_TIME = 10; // 锁过期时间(秒)@Transactionalpublic String grabOrder(Long driverId, Long orderId) {// 使用Redis实现分布式锁String lockKey = LOCK_KEY + orderId;Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", LOCK_EXPIRE_TIME, TimeUnit.SECONDS);if (lock == null || !lock) {return "抢单失败,订单已被其他司机抢单";}try {// 查询订单信息Optional<Order> optionalOrder = orderRepository.findById(orderId);if (!optionalOrder.isPresent()) {return "订单不存在";}Order order = optionalOrder.get();if (order.getStatus() != 0) {return "抢单失败,订单状态异常";}// 更新订单状态和司机IDorder.setStatus(1);order.setDriverId(driverId);orderRepository.save(order);// 更新司机状态Optional<Driver> optionalDriver = driverRepository.findById(driverId);if (optionalDriver.isPresent()) {Driver driver = optionalDriver.get();driver.setStatus(1);driverRepository.save(driver);}return "抢单成功";} finally {// 释放锁redisTemplate.delete(lockKey);}}public List<Order> getNearbyOrders(Double latitude, Double longitude) {// 根据经纬度查询附近的订单(这里简化处理,只返回所有待抢单订单)return orderRepository.findAllByStatus(0);}
}
6.创建Controller类
将OrderController
类的getNearbyOrders
方法补充完整,并确保其逻辑与抢单功能相匹配。此外,为了更贴近实际需求,getNearbyOrders
方法应当能够基于司机的位置(纬度和经度)来筛选附近的订单,尽管在实际应用中这通常涉及更复杂的地理空间查询。但在此示例中,为了简化,我们将仅返回所有待抢单的订单,并在注释中指出应如何实现更复杂的逻辑。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("/api/orders")
public class OrderController {@Autowiredprivate OrderService orderService;@PostMapping("/grab")public String grabOrder(@RequestParam Long driverId, @RequestParam Long orderId) {return orderService.grabOrder(driverId, orderId);}@GetMapping("/nearby")public List<Order> getNearbyOrders(@RequestParam Double latitude, @RequestParam Double longitude) {// 在实际应用中,这里应该包含基于地理位置的查询逻辑,// 例如使用数据库中的地理空间索引或第三方地理空间搜索服务。// 但为了简化示例,我们仅返回所有待抢单的订单。// 注意:在生产环境中,直接返回所有待抢单订单可能不是最佳实践,// 因为这可能会暴露过多信息给司机,并增加后端服务器的负载。// 假设我们有一个方法来根据司机的位置计算附近订单的半径(例如5公里)// 但由于我们简化了地理空间查询,所以这里不实现这个方法。// 返回一个筛选后的订单列表,仅包含状态为“待抢单”的订单// 在实际应用中,这里应该有一个更复杂的查询,基于司机的位置和订单的位置return orderService.getNearbyOrders(0); // 0 表示待抢单状态// 注意:上面的调用中我们传递了状态码0作为参数,但在OrderService的getNearbyOrders方法中// 我们实际上并没有使用这个参数来进行筛选(因为我们的示例简化了地理空间查询)。// 在实际的OrderService实现中,你应该修改这个方法以接受状态码作为参数,并据此来筛选订单。// 例如:return orderRepository.findAllByStatusAndWithinRadius(0, latitude, longitude, radius);// 这里的withinRadius方法是一个假设的方法,用于执行地理空间查询。}
}
将OrderController
类的getNearbyOrders
方法补充完整,并确保其逻辑与抢单功能相匹配。此外,为了更贴近实际需求,getNearbyOrders
方法应当能够基于司机的位置(纬度和经度)来筛选附近的订单,尽管在实际应用中这通常涉及更复杂的地理空间查询。但在此示例中,为了简化,我们将仅返回所有待抢单的订单,并在注释中指出应如何实现更复杂的逻辑。
7. 配置安全性(如Spring Security)
为了保障系统的安全性,通常需要配置用户认证和授权。
配置类:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/orders/grab/**").authenticated() // 需要认证才能访问抢单接口.anyRequest().permitAll().and().formLogin().permitAll().and().logout().permitAll();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}
8. 创建Service类
Service类用于处理业务逻辑,比如验证司机资格、更新订单状态等。
OrderService.java:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.Optional;@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate DriverRepository driverRepository;@Transactionalpublic boolean grabOrder(Long orderId, Long driverId) {Optional<Order> optionalOrder = orderRepository.findById(orderId);if (!optionalOrder.isPresent() || optionalOrder.get().getStatus() != OrderStatus.AVAILABLE) {return false;}Optional<Driver> optionalDriver = driverRepository.findById(driverId);if (!optionalDriver.isPresent()) {return false;}Order order = optionalOrder.get();order.setDriver(optionalDriver.get());order.setStatus(OrderStatus.GRABBED);orderRepository.save(order);return true;}
}
9. 配置消息队列(如RabbitMQ或Kafka)
对于抢单功能,使用消息队列可以提高系统的并发处理能力和响应速度。
RabbitMQ配置类:
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitMQConfig {public static final String QUEUE_NAME = "orderQueue";@BeanQueue queue() {return new Queue(QUEUE_NAME, true);}@BeanSimpleMessageListenerContainer container(ConnectionFactory connectionFactory,MessageListenerAdapter listenerAdapter) {SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.setQueueNames(QUEUE_NAME);container.setMessageListener(listenerAdapter);return container;}@BeanMessageListenerAdapter listenerAdapter(OrderService orderService) {return new MessageListenerAdapter(orderService, "processOrder");}@BeanRabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {return new RabbitTemplate(connectionFactory);}
}
OrderService中添加处理消息的方法:
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class OrderService {// 之前的代码...@Autowiredprivate RabbitTemplate rabbitTemplate;public void publishOrder(Order order) {rabbitTemplate.convertAndSend(RabbitMQConfig.QUEUE_NAME, order);}public void processOrder(Order order) {// 逻辑处理,比如将订单状态更新为已分配等// 这里可以调用grabOrder方法或其他逻辑}
}
10. 单元测试
编写单元测试来验证你的抢单逻辑。
OrderServiceTest.java:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {@Mockprivate OrderRepository orderRepository;@Mockprivate DriverRepository driverRepository;@InjectMocksprivate OrderService orderService;@Testpublic void testGrabOrderSuccess() {Order order = new Order();order.setId(1L);order.setStatus(OrderStatus.AVAILABLE);Driver driver = new Driver();driver.setId(1L);when(orderRepository.findById(1L)).thenReturn(Optional.of(order));when(driverRepository.findById(1L)).thenReturn(Optional.of(driver));boolean result = orderService.grabOrder(1L, 1L);assertTrue(result);verify(orderRepository, times(1)).save(any(Order.class));}@Testpublic void testGrabOrderOrderNotFound() {when(orderRepository.findById(1L)).thenReturn(Optional.empty());boolean result = orderService.grabOrder(1L, 1L);assertFalse(result);verify(orderRepository, never()).save(any(Order.class));}// 更多测试...
}
11. 日志记录
使用日志记录库(如SLF4J和Logback)来记录关键操作。
在application.properties中配置Logback:
properties复制代码logging.level.com.example.ridesharing=DEBUG
在Service类中记录日志:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;@Service
public class OrderService {private static final Logger logger = LoggerFactory.getLogger(OrderService.class);// 之前的代码...@Transactionalpublic boolean grabOrder(Long orderId, Long driverId) {logger.debug("Attempting to grab order {} by driver {}", orderId, driverId);Optional<Order> optionalOrder = orderRepository.findById(orderId);if (!optionalOrder.isPresent() || optionalOrder.get().getStatus() != OrderStatus.AVAILABLE) {logger.debug("Order {} is not available or does not exist", orderId);return false;}Optional<Driver> optionalDriver = driverRepository.findById(driverId);if (!optionalDriver.isPresent()) {logger.debug("Driver {} does not exist", driverId);return false;}Order order = optionalOrder.get();order.setDriver(optionalDriver.get());order.setStatus(OrderStatus.GRABBED);orderRepository.save(order);logger.debug("Order {} successfully grabbed by driver {}", orderId, driverId);return true;}
}
12. 部署和运维
最后,考虑如何部署和运维你的应用,包括使用Docker进行容器化、配置CI/CD管道等。
这些步骤和代码示例提供了一个完整的框架,用于实现一个包含抢单功能的网约车项目。当然,根据具体需求,你可能需要调整或添加更多的功能。
五、前端实现
在Java网约车项目实战中实现抢单功能的前端部分,通常可以使用前端框架如React、Vue.js或Angular来构建用户界面。为了简单起见,这里我们使用React和Redux来实现一个基本的前端应用,该应用允许司机查看订单并抢单。
1.项目结构
假设项目结构如下:
my-ridesharing-app/
├── public/
│ ├── index.html
│ └── ...
├── src/
│ ├── actions/
│ │ └── orderActions.js
│ ├── components/
│ │ ├── OrderList.js
│ │ ├── OrderItem.js
│ │ └── App.js
│ ├── reducers/
│ │ └── orderReducer.js
│ ├── store/
│ │ └── index.js
│ ├── index.js
│ └── ...
├── package.json
└── ...
2.安装依赖
首先,确保你已经安装了Node.js和npm,然后在项目根目录下运行以下命令来初始化React项目并安装必要的依赖:
npx create-react-app my-ridesharing-app
cd my-ridesharing-app
npm install redux react-redux redux-thunk axios
3.实现前端代码
(1) src/store/index.js
- 配置Redux Store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';const store = createStore(rootReducer, applyMiddleware(thunk));export default store;
(2)src/reducers/orderReducer.js
- 定义Reducer
const initialState = {orders: [],loading: false,error: null,
};const fetchOrdersSuccess = (state, action) => ({...state,orders: action.payload,loading: false,error: null,
});const fetchOrdersFailure = (state, action) => ({...state,loading: false,error: action.payload,
});const grabOrderSuccess = (state, action) => {const updatedOrders = state.orders.map(order =>order.id === action.payload.id ? { ...order, grabbed: true } : order);return {...state,orders: updatedOrders,};
};const orderReducer = (state = initialState, action) => {switch (action.type) {case 'FETCH_ORDERS_REQUEST':return {...state,loading: true,};case 'FETCH_ORDERS_SUCCESS':return fetchOrdersSuccess(state, action);case 'FETCH_ORDERS_FAILURE':return fetchOrdersFailure(state, action);case 'GRAB_ORDER_SUCCESS':return grabOrderSuccess(state, action);default:return state;}
};export default orderReducer;
(3)src/actions/orderActions.js
- 定义Action Creators
import axios from 'axios';export const fetchOrders = () => async dispatch => {dispatch({ type: 'FETCH_ORDERS_REQUEST' });try {const response = await axios.get('/api/orders'); // 假设后端API地址dispatch({ type: 'FETCH_ORDERS_SUCCESS', payload: response.data });} catch (error) {dispatch({ type: 'FETCH_ORDERS_FAILURE', payload: error.message });}
};export const grabOrder = orderId => async dispatch => {try {const response = await axios.post(`/api/orders/${orderId}/grab`); // 假设后端API地址dispatch({ type: 'GRAB_ORDER_SUCCESS', payload: response.data });} catch (error) {console.error('Grab order failed:', error.message);}
};
(4)src/components/OrderItem.js
- 订单项组件
import React from 'react';
import { useDispatch } from 'react-redux';
import { grabOrder } from '../actions/orderActions';const OrderItem = ({ order }) => {const dispatch = useDispatch();const handleGrab = () => {dispatch(grabOrder(order.id));};return (<div><h3>{order.passengerName}</h3><p>Pickup: {order.pickupLocation}</p><p>Dropoff: {order.dropoffLocation}</p><button onClick={handleGrab} disabled={order.grabbed}>{order.grabbed ? 'Grabbed' : 'Grab Order'}</button></div>);
};export default OrderItem;
(5) src/components/OrderList.js
- 订单列表组件
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchOrders } from '../actions/orderActions';
import OrderItem from './OrderItem';const OrderList = () => {const dispatch = useDispatch();const { orders, loading, error } = useSelector(state => state.orders);useEffect(() => {dispatch(fetchOrders());}, [dispatch]);if (loading) return <div>Loading...</div>;if (error) return <div>Error: {error}</div>;return (<div><h2>Orders</h2>{orders.map(order => (<OrderItem key={order.id} order={order} />))}</div>);
};export default OrderList;
(6)src/components/App.js
- 主应用组件
import React from 'react';
import OrderList from './OrderList';
import { Provider } from 'react-redux';
import store from '../store';const App = () => (<Provider store={store}><div className="App"><h1>Ridesharing App</h1><OrderList /></div></Provider>
);export default App;
(7) src/index.js
- 入口文件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import reportWebVitals from './reportWebVitals';ReactDOM.render(<React.StrictMode><App /></React.StrictMode>,document.getElementById('root')
);reportWebVitals();
4.后端API
注意,上面的代码假设后端API存在,并且提供了以下两个端点:
(1)GET /api/orders
- 获取所有未被抓取的订单。
(2)POST /api/orders/:orderId/grab
- 抓取指定订单。
你需要在后端实现这些API端点,并确保它们能够返回正确的数据。
5.运行应用
在项目根目录下运行以下命令来启动React应用:
bash复制代码npm start
这将启动开发服务器,并在浏览器中打开你的应用。你应该能看到一个订单列表,并且可以点击“Grab Order”按钮来抓取订单。
以上就是一个简单的React前端实现,用于在网约车项目中实现抢单功能。你可以根据实际需求进一步扩展和优化这个应用。
在Java网约车项目实战中,实现抢单功能是一个核心且复杂的部分。除了你提到的几个主要部分(项目背景与需求分析、技术选型与架构设计、数据库设计、后端实现、前端实现)外,通常还需要包含以下关键内容,以确保项目的完整性和健壮性:
六、系统测试
- 单元测试:针对后端实现的各个模块,编写单元测试代码,确保每个模块的功能正常。
- 集成测试:将各个模块集成在一起后,进行整体测试,确保系统整体功能正常。
- 压力测试:模拟高并发场景,测试系统在抢单等高并发操作下的性能和稳定性。
- 安全测试:测试系统的安全性,确保用户数据和订单信息不会被泄露或篡改。
七、性能优化
- 代码优化:对后端代码进行优化,提高代码的执行效率和可读性。
- 数据库优化:对数据库进行查询优化、索引优化等,提高数据库的查询速度和响应能力。
- 缓存策略:使用Redis等缓存技术,减少对数据库的访问压力,提高系统的响应速度。
八、部署与运维
- 系统部署:将系统部署到服务器或云平台上,确保系统能够正常运行。
- 运维监控:对系统进行监控,及时发现并处理系统异常和故障。
- 日志管理:对系统日志进行管理,确保日志的完整性和可读性,方便后续的问题排查和性能分析。
九、文档编写
- 技术文档:编写详细的技术文档,包括系统的架构设计、数据库设计、接口文档等,方便后续的开发和维护。
- 用户手册:编写用户手册,指导用户如何使用系统,包括系统的功能介绍、操作流程等。
十、项目总结与反思
- 项目总结:对整个项目进行总结,包括项目的完成情况、遇到的问题及解决方案等。
- 经验反思:对项目的经验进行反思,总结在项目开发过程中的得失,为后续的项目开发提供参考。
综上所述,一个完整的Java网约车项目实战,除了实现抢单功能的核心部分外,还需要考虑系统测试、性能优化、部署与运维、文档编写以及项目总结与反思等关键内容。这些内容对于确保项目的成功交付和后续维护具有重要意义。
相关文章:
Java网约车项目实战:实现抢单功能详解
在网约车项目中,抢单功能是非常关键的一部分,它决定了司机能否及时响应乘客的订单,提高整个平台的运营效率。本文将详细介绍如何使用Java来实现网约车项目的抢单功能,并提供一个完整的代码示例,以便读者能够直接运行和…...

SSRF服务端请求Gopher伪协议白盒测试
前言 是什么SSRF? 这个简单点说就是 服务端的请求伪造 就是这个如果是个 请求图片的网站 他的目的是请求外部其他网站的 图片 但是 SSRF指的是让他请求本地的图片 再展示出来 请求的是他的服务器上的图片 SSRF(Server-Side Request Forgery:服务器端请求伪造) …...

html+css+js网页设计 美食 家美食1个页面
htmlcssjs网页设计 美食 家美食1个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1…...

初学stm32---高级定时器输出n个pwm波
目录 高级定时器简介:(F1) 高级定时器框图 重复计数器特性 高级定时器输出指定个数PWM实验原理 高级定时器输出指定个数PWM实验配置步骤 相关HAL库函数介绍 关键结构体介绍 高级定时器简介:(F1) 1.高级定时器 :TIM1/TIM8 2.主要特性&…...

旅游管理系统|Java|SSM|VUE| 前后端分离
【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7 4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html 5⃣️数据库可…...

imgproxy图像处理的高效与安全
摘要 imgproxy作为一个高效且安全的独立服务器,为图像处理提供了全新的解决方案。它不仅简化了图像调整和转换的过程,还极大地提升了处理速度,确保了整个流程的安全性。通过集成imgproxy,用户可以轻松优化网页上的图像,提高加载速度,改善用户体验。本文将深入探讨imgpro…...
LLM并行计算的论文
LLM并行计算的论文 基础并行计算方法相关 《Gpipe: Efficient Training of Giant Neural Networks using Pipeline Parallelism》:提出了Gpipe这种流水线并行方法,通过将数据批量进一步等分成若干microbatch,并以流水线的方式执行,减少计算中空泡的比例,极大地拓展了模型…...

Linux 搭建 nginx+keepalived 高可用 | Nginx反向代理
注意:本文为 “Linux 搭建 nginxkeepalived (主备双主模式) 高可用 | Nginx反向代理” 相关文章合辑。 KeepalivedNginx实现高可用(HA) xyang0917 于 2016-09-17 00:24:15 发布 keepalived 的 HA 分为抢占模式和非抢占模式,抢占…...
Spring Boot 项目中 Maven 剔除无用 Jar 引用的最佳实践
目录 引言Maven 依赖管理的基础概念 2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机制 无用依赖的常见问题与影响剔除无用 Jar 引用的常见方法 4.1 识别无用依赖4.2 使用 Maven 的 dependency:analyze 插件4.3 配置 scope 以优化依赖范围4.4 使用 exclude 排除传递依赖4.5 分析…...

useWhyDidYouUpdate详解
目录 API Params demo演示 源码 useWhyDidYouUpdate是ahooks库中的一个hook函数,用于帮助开发者排查是哪个属性改变导致了组件的 rerender。 API type IProps Record<string, any>;useWhyDidYouUpdate(componentName: string, props: IProps): void; …...
c++入门——c++输入cin和输出cout的简单使用
c输入cin、输出cout 1 cin2 cout3 cin和cout说明 c在c语言的输入、输出函数的基础上进行了封装。 1 cin c可以理解为控制台,in可以理解为输入。 参考代码: void f(){int a;float b;double c;char d;cin>>a>>b>>c>>d;//这里和…...

Spring Cloud LoadBalancer (负载均衡)
目录 什么是负载均衡 服务端负载均衡 客户端负载均衡 Spring Cloud LoadBalancer快速上手 启动多个product-service实例 测试负载均衡 负载均衡策略 自定义负载均衡策略 什么是负载均衡 负载均衡(Load Balance,简称 LB) , 是高并发, 高可用系统必不可少的关…...

微服务-1 认识微服务
目录 1 认识微服务 1.1 单体架构 1.2 微服务 1.3 SpringCloud 2 服务拆分原则 2.1 什么时候拆 2.2 怎么拆 2.3 服务调用 3. 服务注册与发现 3.1 注册中心原理 3.2 Nacos注册中心 3.3 服务注册 3.3.1 添加依赖 3.3.2 配置Nacos 3.3.3 启动服务实例 …...

基于51单片机的交通灯带拐弯proteus仿真
地址: https://pan.baidu.com/s/1cgqRHMHp9VJet4vs5LiG5A 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C52/AT89C51是一款经典的8位单片机,是意法半导体(STMicroelectro…...
1229java面经
1,Java中synchronized关键字是否是可重入的? 可重入的定义 可重入是指当一个线程已经获取了某个对象的锁,在该锁没有释放的情况下,如果这个线程再次请求获取这个对象的锁,是可以成功获取的,而不会出现自己把自己锁死的情况。简单…...
MySQL中查看表结构
1. 使用 DESCRIBE 或 DESC 命令 DESCRIBE(或其简写 DESC)是最简单和最直接的方法,可以显示表的列信息。 语法: DESCRIBE table_name; -- 或者 DESC table_name;示例: 假设有一个名为 employees 的表,可以…...

python利用selenium实现大麦网抢票
大麦网(damai.cn)是中国领先的现场娱乐票务平台,涵盖演唱会、音乐会、话剧、歌剧、体育赛事等多种门票销售。由于其平台上经常会有热门演出,抢票成为许多用户关注的焦点。然而,由于票务资源的有限性,以及大…...

FME教程:一键批量调换图斑X、Y坐标,解决因为坐标弄反了,导致GIS弹窗提示“范围不一致”警告问题
目录 一、实现效果 二、实现过程 1.读取数据 2.提取坐标 3.调换图斑的X、Y坐标 4.输出成果 5.模板的使用 三、总结 在工作中有时候会出现因为失误导致图斑的X、Y坐标弄反,在GIS中打开是会提示“范围不一致”警告的弹窗警告,如果重做工作量非常大…...

OpenCV-Python实战(4)——图像处理基础知识
一、坐标 在 OpenCV 中图像左上角坐标为(0,0),竖直向下为 Y(height) ;水平向右为 X(width)。 二、生成图像 2.1 灰度图像 img np.zeros((h,w), dtype np.uint8) i…...
音视频入门基础:MPEG2-PS专题(1)——MPEG2-PS官方文档下载
一、引言 MPEG2-PS(又称PS,Program Stream,程序流,节目流)是一种多路复用数字音频、视频等的封装容器。MPEG2-PS将一个或多个分组但有共同的时间基准的基本数据流 (PES)合并成一个整体流。它是…...

Qt自定义步骤引导按钮
1. 步骤引导按钮 实际在开发项目过程中,由一些流程比较繁琐,为了给客户更好的交互体验,往往需要使用step1->step2这种引导对话框或者引导按钮来引导用户一步步进行设置;话不多说,先上效果 2. 实现原理 实现起来…...

贝叶斯神经网络(Bayesian Neural Network)
最近在研究贝叶斯神经网络,一些概念一直搞不清楚,这里整理一下相关内容,方便以后查阅。 贝叶斯神经网络(Bayesian Neural Network) 贝叶斯神经网络(Bayesian Neural Network)1. BNN 的核心思想2. BNN 的优化目标3. BNN 的结构与特点4. BNN 的训练过程5. BNN 的优缺点6. …...
Direct Preference Optimization: Your Language Model is Secretly a Reward Model
DPO直接偏好优化:你的语言模型实际上是一个奖励模型 前言知识储备 什么是用户偏好数据目的:用于指导模型行为,使其输出更符合特定用户或者用户群体期望和喜好的信息。 用户偏好数据通常反映了用户对特定内容、风格、观点或者互动方式的倾向。 用户偏好数据的收集通常涉及直…...

如何通过 Kafka 将数据导入 Elasticsearch
作者:来自 Elastic Andre Luiz 将 Apache Kafka 与 Elasticsearch 集成的分步指南,以便使用 Python、Docker Compose 和 Kafka Connect 实现高效的数据提取、索引和可视化。 在本文中,我们将展示如何将 Apache Kafka 与 Elasticsearch 集成以…...

嵌入式系统 第十二讲 块设备和驱动程序设计
• 块设备是Linux三大设备之一(另外两种是字符设备,网络设备),块 设备也是通过/dev下的文件系统节点访问。 • 块设备的数据存储单位是块,块的大小通常为512B至32KB不等。 • 块设备每次能传输一个或多个块,…...

攻防世界web第六题upload
这是题目,可以看出是个上传文件的题目,考虑文件上传漏洞,先随便上传一个文件试试,要求上传的是图片。 可以看到上传成功。 考虑用一句话木马解决,构造文件并修改后缀为jpg,然后上传。 <?php eval($_POST[attack])…...
人工智能-Python网络编程-HTTP
用Python创建自己的HTTP服务器 方案一 HTTP-Python官方 python -m http.server 80 方案二 HTTP-概念版 import socketIPV4_ADDR 192.168.124.7 IPV4_PORT 8888# TCP 服务端程序必须绑定端口号,否则客户端找不到这个 TCP 服务端程序 class ServerSocket(obje…...

探索仓颉编程语言:功能、实战与展望
目录 引言 一.使用体验 二.功能剖析 1.丰富的数据类型与控制结构 2.强大的编程范式支持 3.标准库与模块系统 4.并发编程能力 三.实战案例 1.项目背景与目标 2.具体实现步骤 (1).导入必要的模块 (2).发送 HTTP 请求获取网页内容 (3).解析 HTML 页面提取文章信息 (…...

Unity-Editor扩展显示文件夹大小修复版 FileCapacity.cs
实战中是这样的,大项目, 容易定位美术大资产 (原版的代码有问题,每次点运行都会卡顿,大项目20S) //但其实获整个项目内容,1G都没有,有够省的(10年前的中型项目,一直有出DLC) using System; using System.Collections; using System.Collections.Generic; using Sy…...

BLE core 内容整理解释
本文内容比较杂散,只是做记录使用,后续会整理的有条理些 link layer 基本介绍 **Link Layer Control(链路层控制)**是蓝牙低功耗(BLE)协议栈的核心部分,负责实现设备间可靠、安全、低功耗的数…...