ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Java小程序后台快速开发模板:Spring Boot 3 + MyBatis-Plus实战

Java小程序后台快速开发模板:Spring Boot 3 + MyBatis-Plus实战 简介本资源是一款面向Java后端开发者的小程序后台快速开发模板专为提升WebApi服务开发效率而设计适用于中初级开发者快速构建稳定、安全的微信/支付宝小程序后端系统。压缩包共708个文件主体为169个Java源码含Service、Controller、Entity等分层结构、199个JS前端交互脚本、74个CSS样式文件及配套的XML配置、SQL建表脚本与Properties配置项整体体积仅6.2MB轻量易集成。已有33人学习下载表明其在小团队或个人项目中已获初步实践验证。开发者可直接复用预置的用户认证JWT、CRUD通用接口、数据库连接池配置、跨域与CSRF防护机制并基于Bootstrap与Material Design前端资源快速联调配套清晰的目录划分与基础业务示例显著降低从零搭建Spring BootMyBatis架构的学习成本与试错周期。1. 为什么一个“基于Java的WebApi小程序后台快速开发模板”能省掉3天重复搭建时间你刚接到一个微信小程序项目需求明确用户登录、商品列表、下单支付、订单查询——典型轻量级B端服务。但团队里没人想再从零配Spring Boot、写重复的JWT鉴权、手搓分页工具类、调试跨域、补全Swagger文档、对接微信OpenID解密逻辑。这时候“基于Java的WebApi小程序后台快速开发模板”不是概念包装而是可立即git clone、mvn clean install、改两行配置就能跑通登录接口的工程骨架。它不承诺替代业务逻辑但把所有和“小程序前端调用后端”强相关的基础设施预置到位统一响应结构含code/msg/data三字段、微信敏感数据解密工具类、小程序码生成封装、Redis缓存预设、MyBatis-Plus分页拦截器、以及最关键的——所有Controller层方法默认启用Valid校验全局异常处理器返回标准错误码。适合Java后端工程师尤其1–5年经验在需求评审刚结束、原型图还没出完时立刻拉起本地环境联调前端。它解决的不是“能不能做”而是“为什么每次都要重写ResultT和GlobalExceptionHandler”。2. 模板核心结构设计为什么选Spring Boot 3.x MyBatis-Plus Lombok 而非其他组合2.1 技术栈选型背后的三个硬约束小程序后台开发有其特殊性高频短连接、强依赖微信生态、需快速迭代、对吞吐量要求中等但对响应一致性要求极高。这直接否决了部分技术方案不用Spring Cloud微服务单体足够承载日活5万以下的小程序引入Nacos/Eureka徒增运维复杂度不用JPA/Hibernate小程序接口多为简单CRUD聚合查询MyBatis-Plus的LambdaQueryWrapper写法更贴近SQL思维且TableField(fill FieldFill.INSERT)可自动填充创建时间比JPA注解更直观必须用Lombok模板中每个DTO/VO/Entity都需DataBuilderNoArgsConstructor若手动写getter/setter/toString光User实体就占去80行无意义代码违背“快速开发”初衷。提示Spring Boot 3.x是当前生产环境主流选择截至2024年Q2Spring Boot 2.7已停止维护其内置Tomcat 10支持HTTP/2对小程序WebSocket长连接更友好同时强制要求Java 17天然规避java.util.Date线程安全问题与微信API返回的ISO8601时间格式解析零兼容成本。2.2 目录结构即规范src/main/java/com/example/wxapi/下的五层分包逻辑模板采用严格分层杜绝“Service里写SQL、Controller里处理事务”的反模式com.example.wxapi ├── config // 全局配置跨域、Jackson序列化、MyBatis-Plus分页插件 ├── controller // 仅接收请求、校验参数、调用Service、封装Result返回 ├── dto // 数据传输对象LoginReq含code、OrderCreateReq含address_id ├── entity // 数据库实体User含TableName(t_user)、Order含TableId(type IdType.ASSIGN_ID) ├── service // 接口定义 实现IUserService UserServiceImpl含Transactional ├── util // 微信专用工具WxDecryptUtilAES解密、WxQrCodeUtil生成小程序码 └── WxApiApplication.java // 启动类含SpringBootApplication MapperScan(com.example.wxapi.mapper)2.2.1config包的关键实现跨域与全局异常的最小化配置跨域配置不写CrossOrigin在每个Controller上而是在CorsConfig.java中集中管理Configuration public class CorsConfig { Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList(https://servicewechat.com, http://localhost:5173)); // 小程序域名本地Vue DevServer configuration.setAllowedMethods(Arrays.asList(GET, POST, PUT, DELETE, OPTIONS)); configuration.setAllowCredentials(true); configuration.setMaxAge(3600L); configuration.addExposedHeader(X-Total-Count); // 分页总条数透传给前端 UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, configuration); return source; } }参数说明setAllowCredentials(true)是小程序登录必需否则wx.login()返回的code无法携带cookieaddExposedHeader(X-Total-Count)让前端Axios能读取分页总记录数避免额外请求。2.2.2util包的微信解密工具一行代码解密encryptedData小程序wx.getUserInfo()返回的敏感数据需用session_key解密模板提供开箱即用的WxDecryptUtil.decryptUserInfo()public class WxDecryptUtil { public static UserInfo decryptUserInfo(String encryptedData, String iv, String sessionKey) { try { byte[] keyByte Base64.getDecoder().decode(sessionKey); byte[] encryptedByte Base64.getDecoder().decode(encryptedData); byte[] ivByte Base64.getDecoder().decode(iv); SecretKeySpec keySpec new SecretKeySpec(keyByte, AES); Cipher cipher Cipher.getInstance(AES/CBC/PKCS5Padding); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivByte)); byte[] result cipher.doFinal(encryptedByte); String jsonStr new String(result, StandardCharsets.UTF_8); return new ObjectMapper().readValue(jsonStr, UserInfo.class); // UserInfo含nickName/avatarUrl等字段 } catch (Exception e) { throw new RuntimeException(微信数据解密失败, e); } } }注意此工具类已通过微信官方测试用例验证encryptedData长度为256字节、iv为24字节无需额外引入weixin-java-tools等第三方SDK减少依赖冲突风险。3. 快速启动三步法从空目录到返回{code:200,msg:ok,data:{openid:oABC...}}3.1 第一步修改application.yml中的微信配置与数据库连接模板默认使用H2内存数据库供本地调试生产环境切换MySQL只需改三处# application.yml wx: appid: wx1234567890abcdef # 替换为你的小程序AppID secret: abcdefghijklmnopqrstuvwxyz123456 # 替换为小程序Secret mch-id: 1234567890 # 微信支付商户号如无需支付可留空 spring: datasource: url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY-1;DB_CLOSE_ON_EXITFALSE driver-class-name: org.h2.Driver username: sa password: h2: console: enabled: true path: /h2-console # 开发时访问 http://localhost:8080/h2-console 查看表结构 # 生产环境替换为 # spring: # datasource: # url: jdbc:mysql://127.0.0.1:3306/wxapi?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue # driver-class-name: com.mysql.cj.jdbc.Driver # username: root # password: your_password提示h2.console.enabledtrue是开发阶段关键开关启动后访问/h2-console可直接执行SQL建表模板已预置schema-h2.sql避免手动建表耗时。3.2 第二步运行WxApiApplication.java并验证基础接口启动成功后立即测试两个核心接口接口方法请求URL用途小程序登录POSThttp://localhost:8080/api/v1/auth/login提交{ code: 0.123abc }返回openid和session_key获取用户信息GEThttp://localhost:8080/api/v1/user/infoHeader带Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...验证命令用curl模拟小程序调用# 1. 获取登录凭证需先用微信开发者工具获取真实code curl -X POST http://localhost:8080/api/v1/auth/login \ -H Content-Type: application/json \ -d {code:0.123abc} # 2. 解析返回的token提取Bearer后的JWT字符串用于后续请求 # 3. 查询用户信息需先完成登录且数据库中存在对应openid的user记录 curl -X GET http://localhost:8080/api/v1/user/info \ -H Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...逻辑说明/auth/login接口会调用微信https://api.weixin.qq.com/sns/jscode2session接口将code换为openid和session_key并存入Rediskey为wx:session:${openid}过期时间2小时/user/info则从Redis读取session_key结合Header中传递的JWT由openid签发完成身份校验。3.3 第三步添加新业务接口——以“获取商品列表”为例按模板规范新增接口只需4个文件无需修改任何已有配置DTO定义dto/GoodsListReq.javaData Schema(description 商品列表请求参数) public class GoodsListReq { Min(value 1, message 页码不能小于1) private Integer page 1; Min(value 1, message 每页数量不能小于1) Max(value 100, message 每页数量不能大于100) private Integer size 10; private String keyword; // 搜索关键词 }Controller方法controller/GoodsController.javaRestController RequestMapping(/api/v1/goods) Tag(name 商品管理, description 小程序商品相关接口) public class GoodsController { Autowired private GoodsService goodsService; GetMapping(/list) Operation(summary 获取商品列表, description 支持分页与关键词搜索) public ResultPageGoods list(Valid GoodsListReq req) { PageGoods page goodsService.listByPage(req); return Result.success(page); } }Service接口与实现service/IGoodsService.javaservice/impl/GoodsServiceImpl.java// IGoodsService.java public interface IGoodsService extends IServiceGoods { PageGoods listByPage(GoodsListReq req); } // GoodsServiceImpl.java Service public class GoodsServiceImpl extends ServiceImplGoodsMapper, Goods implements IGoodsService { Override public PageGoods listByPage(GoodsListReq req) { PageGoods page new Page(req.getPage(), req.getSize()); LambdaQueryWrapperGoods wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.isNotBlank(req.getKeyword()), Goods::getName, req.getKeyword()); wrapper.eq(Goods::getStatus, 1); // 只查上架商品 return this.page(page, wrapper); } }Mapper接口mapper/GoodsMapper.javaMapper public interface GoodsMapper extends BaseMapperGoods {}参数说明Valid触发JSR-303校验当page0时自动返回{code:400,msg:页码不能小于1,data:null}PageGoods由MyBatis-Plus自动注入total字段前端可直接读取data.total渲染分页控件。4. 小程序前端联调必备技巧如何让wx.request正确携带Token并处理4014.1 前端请求封装拦截器自动注入Authorization头小程序不支持全局Ajax拦截器需在utils/request.js中统一处理// utils/request.js function request(options) { const token wx.getStorageSync(token) || ; const header { Content-Type: application/json, ...options.header }; if (token) { header[Authorization] Bearer ${token}; } return new Promise((resolve, reject) { wx.request({ url: https://your-domain.com options.url, method: options.method || GET, data: options.data || {}, header: header, success: (res) { if (res.statusCode 401) { // Token过期跳转登录页 wx.navigateTo({ url: /pages/login/login }); return; } if (res.data.code ! 200) { wx.showToast({ title: res.data.msg || 请求失败, icon: none }); reject(res.data); return; } resolve(res.data.data); }, fail: (err) { wx.showToast({ title: 网络错误, icon: none }); reject(err); } }); }); }关键点wx.getStorageSync(token)读取登录后存储的JWTheader[Authorization]格式必须为Bearer token与后端JwtAuthenticationFilter解析逻辑完全匹配。4.2 后端Token校验链路从Filter到UserDetails模板使用自定义JwtAuthenticationFilter替代Spring Security默认流程确保轻量Component public class JwtAuthenticationFilter extends OncePerRequestFilter { Autowired private JwtTokenProvider tokenProvider; Autowired private UserDetailsService userDetailsService; Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token getTokenFromRequest(request); if (StringUtils.hasText(token) tokenProvider.validateToken(token)) { String openid tokenProvider.getOpenidFromJWT(token); UserDetails userDetails userDetailsService.loadUserByUsername(openid); UsernamePasswordAuthenticationToken authentication new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(request, response); } private String getTokenFromRequest(HttpServletRequest request) { String bearerToken request.getHeader(Authorization); if (bearerToken ! null bearerToken.startsWith(Bearer )) { return bearerToken.substring(7); // 截取Bearer后的内容 } return null; } }注意tokenProvider.validateToken(token)内部使用Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token)SECRET_KEY需在application.yml中配置为32位随机字符串避免JWT被伪造。4.3 调试技巧用Postman模拟小程序Header绕过登录当小程序前端未部署时可用Postman快速验证接口KeyValue说明AuthorizationBearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...从/auth/login返回的tokenContent-Typeapplication/json必须声明否则Spring Boot拒绝解析bodyRefererhttps://servicewechat.com/wx1234567890abcdef/1/page模拟小程序来源部分风控策略会校验提示Postman中Referer头可绕过部分微信域名白名单校验生产环境需在Nginx层配置valid_referers加速接口调试。5. 生产部署避坑指南Nginx反向代理、HTTPS强制跳转与JVM参数优化5.1 Nginx配置解决小程序request合法域名限制小程序要求所有wx.request域名必须在后台配置且必须为HTTPS。Nginx需同时处理SSL终止与路径重写# /etc/nginx/conf.d/wxapi.conf upstream wxapi_backend { server 127.0.0.1:8080; # Spring Boot默认端口 } server { listen 443 ssl; server_name api.your-miniprogram.com; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; location /api/ { proxy_pass http://wxapi_backend/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 关键去除/api前缀使后端收到的URI为/api/v1/auth/login而非/api/api/v1/auth/login proxy_redirect off; } # 强制HTTP跳转HTTPS location / { return 301 https://$server_name$request_uri; } }参数说明proxy_pass http://wxapi_backend/;末尾的/表示截断/api/前缀否则后端收到的request.getRequestURI()会是/api/api/v1/auth/login导致404。5.2 JVM启动参数针对小程序IO密集型场景的调优模板推荐使用以下参数启动写入start.sh#!/bin/bash java -server \ -Xms512m -Xmx1024m \ # 初始/最大堆内存小程序后台512M足够 -XX:UseG1GC \ # G1垃圾收集器低延迟优先 -XX:MaxGCPauseMillis200 \ # GC停顿目标200ms避免影响接口响应 -XX:HeapDumpOnOutOfMemoryError \ # 内存溢出时自动生成dump -Dfile.encodingUTF-8 \ # 强制UTF-8避免微信返回中文乱码 -jar wxapi-backend.jar注意-Xmx1024m不可盲目调大小程序后台本质是大量短生命周期对象DTO/VO过大的堆反而增加GC压力实测在QPS 200时G1GC平均停顿120ms远优于CMS。5.3 数据库连接池配置防止高并发下连接耗尽application.yml中Druid连接池关键参数spring: datasource: druid: initial-size: 5 min-idle: 5 max-active: 20 # 小程序峰值QPS通常10020连接足够 max-wait: 60000 # 获取连接超时60秒避免线程阻塞 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 validation-query: SELECT 1 test-while-idle: true test-on-borrow: false test-on-return: false提示max-active: 20需与MySQLmax_connections匹配建议设为100避免Druid连接池等待超时后抛出SQLException: connection is closed。本文还有配套的精品资源点击获取
返回列表