# miniProgramAPI **Repository Path**: zheng-hanjun/mini-program-api ## Basic Information - **Project Name**: miniProgramAPI - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-12-06 - **Last Updated**: 2023-12-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 搭建项目 打开idea,选择左上角的file -> new -> module,打开New Module窗口。在Generatorsz中选择Spring Initializr,在右侧,Language选java,Type选Maven。我用的Java17版本。 ![new module窗口1](markdownImg/NewModule1.png) 然后点击next,到下一环节。在Developer Tools选择Lombok,在SQL中选择余下的两项,见下图。 ![new module窗口2](markdownImg/NewModule2.png) ## Lombok 其中Lombok能够提供一些注释,能够少写很多代码。例如: ```java package com.laozheng.data.user; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data //setter,getter,toString @NoArgsConstructor //无参构造 @AllArgsConstructor //有参构造(id,openid,sessionKey,goodsNum) public class User { private int id; private String openid; private String sessionKey; private int goodsNum; public User(String openid, String session_key) { this.openid = openid; this.sessionKey = session_key; } } ``` 使用注释,就不用手动写getter,setter以及有参或无参构造了。 ## Mybatis Mybatis是持久层的框架,方便写SQL语句。在项目内创建mapper文件夹,里面创建interface mapper文件。 ![create mapper](markdownImg/mapper/createMapper.png) ```java import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; @Mapper public interface BaseMapper { @Select("sql语句") public String getSome(String name); } ``` 或者是用.xml映射sql语句。在resources文件夹内创建这个.xml文件,要确保包名、文件名一致。 ![createMapperXML](markdownImg/mapper/createMapperXML.png) xml文件内 ```xml ``` 既然有SQL语句了,那得连上数据库才能操控。 ### 连接数据库 在idea里有database选项卡,例如我的: ![](markdownImg/connectMysql/1.png) 打开它后开始连接数据库。 ![](markdownImg/connectMysql/2.png) ![](markdownImg/connectMysql/3.png) 这是在本地写代码的时候连数据库,打包后项目连接数据库根据配置文件连接。配置文件在resources文件夹。 其中前四行是连接数据库用的。 ```properties # application.properties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost或者服务器公网ip:端口号/数据库名 spring.datasource.username=用户名 spring.datasource.password=密码 # user-name => userName mybatis.configuration.map-underscore-to-camel-case=true #项目运行端口 默认8080 server.port=8081 ``` ### 将数据库的数据导出,再将数据导入到数据库 导出数据,如果**不是**导出所有的表,需要再数据库后面加上想要导出的表名。 ```cmd mysqldump -u用户名 -p密码 数据库名 > database.txt ``` 导入数据,导入的时候找的是“当前”目录下的database.txt ```cmd mysqldump -u用户名 -p密码 数据库名 < database.txt ``` 若云服务器中的mysql密码忘了 ### 修改mysql密码 用的是阿里云 ```cmd cd /etc/my.cnf vi my.cnf ``` 或进入到my.cnf中,按键盘字母o进入编辑模式,再[mysqld]下面添加skip-grant-tables,例如: ``` ... [mysqld] skip-grant-tables ... 然后按esc建退出编辑模式,输入“:”,在输入wq回车,保存退出。 :wq ``` 然后不知道密码也能操作数据库了改密码了 ```cmd mysql -uroot -p666 mysql> update user set authentication_string=password("新密码") where User='root' and Host="localhost"; myusql> flush provileges; mysql> exit; 或者 quit; ``` 密码就改好了,再将my.cnf添加的那句话按之前的步骤删除就行了。 ## SpringBoot ### 控制层 ![createController](markdownImg/controller/createController.png) 这里就是从前端接受数据,逻辑处理,需要的话从数据库获取数据返回给前端。 ```java import org.springframework.web.bind.annotation.*; import lombok.extern.slf4j.Slf4j; @Slf4j @RestController public class Controller { /** * */ @GetMapping("/api/test") public String aController() { log.info("通过注释@Slf4j能够直接使用log.info再Services中输出内容"); //启动后通过 http://localhost:8081/api/test 能获取返回的字符串 return "Hello World!!!"; } /** * 将参数通过路径传入到后端 */ @GetMapping("/api/getval/{val}") public String getVal(@PathVariable("val") String val) { //使用@PathVariable能够获取路径参数val; //注: val为空或者空字符的时候,会匹配不到。可以再写一个路径为"/api/getval/"的接口处理这种情况。 return val; } /** * post请求 * 获取请求头中的Authorization的token */ @PostMapping("/api/test") public Boolean someFn(@RequestHeader("Authorization") String token) { log.info(token); return true; } //... //有啥需求先百度看看有没有好用的注释 } ``` 如果想再这里操作数据库的话,需要用到之前的mapper。 ```java import org.springframework.web.bind.annotation.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import com.laozheng.service.UserService; @Slf4j @RestController public class Controller { //持久层 操作数据库 @Autowired private BaseMapper baseMapper; //业务层 操作数据库+逻辑处理+组装指定类型数据 private BaseServices baseServices; @GetMapping("/api/getdata") public String getData(@RequestParam("id") int id) { String str = baseServices.getStr(id); return str; } } ``` 使用@Autowired注释就不用在这里创建实例就能直接用了,前提是先将BaseMapper交给bean容器保管。 ```java import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Service; //使用@Service注释后就能再其他地方使用@Autowired直接导入了,不用写死耦合度也低 @Mapper @Service public interface BaseMapper {...} ``` ### 业务层(services) 在services文件夹内,把处理数据和操作数据库的逻辑都放在这里,控制层代码看起来就没那么乱了。 ```java import org.springframework.stereotype.Component; @Component public class BaseService { //操作数据库用的 @Autowired private BaseMapper baseMapper; public String test(int id) { //从数据库中根据id获取 str 并返回给控制层 String str = baseMapper.getStringById(id); return str; } } ``` ### 持久层(dao) 操作数据库的,把数据给业务层。 ### 拦截器 主要是应对需要验证token的接口,token过期的时候返回相同的内容,方便前端判断token过期。 #### 设置拦截器 ```java package com.laozheng.utils; import com.google.gson.Gson; import com.laozheng.data.Result; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerInterceptor; import java.io.PrintWriter; @Slf4j public class UserLoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader(JWTUtils.header); if(request.getMethod().equals("OPTIONS")) { log.info("****************OPTIONS方法******************"); return true; } response.setContentType("application/json;charset=UTF-8"); PrintWriter writer = response.getWriter(); Result result = new Result(HttpServletResponse.SC_UNAUTHORIZED,"token expired","token过期"); Gson gson = new Gson(); String jsonStr = gson.toJson(result); // 避免java.lang.IllegalStateException:getWriter() has already been called for this response response.reset(); //token不存在 if (token == null || token.isEmpty()) { log.info("传入token为空"); // response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token为空!"); writer.write(jsonStr); return false; } //验证token String sub = JWTUtils.validateToken(token); if (sub == null || sub.isEmpty()){ log.info("token验证失败"); // response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token验证失败!"); return false; } //更新token有效时间 (如果需要更新其实就是产生一个新的token) if (JWTUtils.isNeedUpdate(token)){ String newToken = JWTUtils.createToken(sub); response.setHeader(JWTUtils.header,newToken); } return true; } } ``` #### 注册拦截器 ```java package com.laozheng.config; import com.laozheng.utils.UserLoginInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvConfig implements WebMvcConfigurer { //注册拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new UserLoginInterceptor()) //需要拦截的请求 .addPathPatterns("/api/cart") //登录请求必须放行 .excludePathPatterns("/api/login"); } //axios请求后端收不到请求头中的Authorization,弄完还是收不到 @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .exposedHeaders("Authentication") .exposedHeaders("Authorization") .allowedHeaders("Authorization") .allowedOrigins("*") .allowCredentials(false) .allowedMethods("GET","POST","DELETE","PUT","PATCH") .maxAge(36000); } } ``` ## Maven 通过pom.xml管理依赖。比如说,想使用java-jwt这个包,直接在pom.xml文件里进行配置。 ```xml ... ... com.auth0 java-jwt 4.3.0 com.google.code.gson gson 2.8.9 org.springframework.boot spring-boot-starter-thymeleaf ... ``` # 实现的接口 ## 首页轮播图 | 请求地址 | 方法 | | ---------------- | ---- | | /api/home/swiper | GET | | 请求参数 | 无 | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": [ { "imgUrl": "https://g-search3.alicdn.com/img/bao/uploaded/i4/i2/1696169910/O1CN01PP66bi2N4po4OwKaa_!!0-item_pic.jpg", "openType": "navigate", "goodsId": 20, "navigatorUrl": "/pages/goods_detail/main?cate=1&goods_id=20", "cateId": 1 }, ... ] } ``` ## 首页分类导航 | 请求地址 | 方法 | | ------------- | ---- | | /api/home/nav | GET | | 请求参数 | 无 | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": [ { "id": 1, "name": "分类", "imgUrl": "https://ct-upimg.yx090.com/ju8hn6/shop/image/2023/05/16/9c7KLTpPnV4Ht0Ncp14ns1XWO4FKD4ylc2ErZJlh.png" }, { "id": 2, "name": "美食", "imgUrl": "https://p0.meituan.net/linglong/e2a59c3436128c5666d69c37d06439385017.png" }, { "id": 3, "name": "超市购", "imgUrl": "https://p0.meituan.net/linglong/cc241f8772329be64943235f78d2be784862.png" }, { "id": 4, "name": "母婴品", "imgUrl": "https://p1.meituan.net/linglong/3b49636fa96eb9eb97a3325decc358b56132.png@132w_96h_1e_1l" } ] } ``` ## 首页楼层数据 | 请求地址 | 方法 | | --------------- | ---- | | /api/home/floor | GET | | 请求参数 | 无 | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": [ { "floorTitle": { "name": "服装", "imgUrl": "https://m11.360buyimg.com/babel/s351x486_jfs/t20261110/232416/3/2641/63505/654efbf3F35170131/136de7b73fb5cb6b.png.webp" }, "floorProducts": [ { "name": "优质", "imgUrl": "https://m11.360buyimg.com/babel/s351x486_jfs/t1/236104/40/3340/74250/65570098F9bf6aba9/200726aa7c54bd1f.png.webp", "imgWidth": "232", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=服饰" }, { "name": "清仓", "imgUrl": "https://m11.360buyimg.com/babel/s351x486_jfs/t1/182430/28/41460/53722/655cd4b9Ff063eb3d/bdce8f684d4932bf.png.webp", "imgWidth": "232", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=服饰" }, { "name": "爆款", "imgUrl": "https://m11.360buyimg.com/babel/s351x486_jfs/t20261116/191147/38/39655/73727/655716c0Fee14b7f4/2bcb83066d56f56c.png.webp", "imgWidth": "233", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=服饰" }, { "name": "时尚", "imgUrl": "https://m11.360buyimg.com/babel/s351x486_jfs/t1/234118/12/3335/72464/6556c832F22148592/7a0cec754403a5c4.png.webp", "imgWidth": "232", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=服饰" }, { "name": "心动", "imgUrl": "https://m11.360buyimg.com/babel/s351x486_jfs/t20261110/232416/3/2641/63505/654efbf3F35170131/136de7b73fb5cb6b.png.webp", "imgWidth": "233", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=服饰" } ] }, { "floorTitle": { "name": "箱包配饰", "imgUrl": "https://m.360buyimg.com/babel/jfs/t1/197690/8/36225/122910/655b1030F43f5e450/48f2b25969177578.png" }, "floorProducts": [ { "name": "清新", "imgUrl": "https://m.360buyimg.com/babel/jfs/t1/161832/39/41540/133669/64f14782Ffbd6e7df/19a0b48ea5be6bcb.jpg", "imgWidth": "232", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=饰品" }, { "name": "复古", "imgUrl": "https://img14.360buyimg.com/n7/jfs/t23764/340/2083337198/258720/d0b916b8/5b72ef74Nfa727c63.jpg", "imgWidth": "233", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=饰品" }, { "name": "韩款", "imgUrl": "https://img12.360buyimg.com/n7/jfs/t21670/205/2610804093/270806/5bb3ebd1/5b5e6772Ne64b44b3.jpg", "imgWidth": "232", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=饰品" }, { "name": "水晶", "imgUrl": "https://img14.360buyimg.com/n7/jfs/t1/118669/22/38126/140495/64902562F0d52cd5d/c68ce318beb84321.jpg", "imgWidth": "233", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=饰品" }, { "name": "情侣", "imgUrl": "https://img13.360buyimg.com/n7/jfs/t1/94332/38/32093/132129/62fee955Ebd08660c/b1a20e4a4738bc6c.jpg", "imgWidth": "233", "openType": "navigate", "navigatorUrl": "/subpkg/goods_list/goods_list?query=饰品" } ] } ] } ``` ## 搜索建议 | 请求地址 | 方法 | | | ------------------- | ------ | -------- | | /api/search/suggest | GET | | | 请求参数 | 类型 | 是否必须 | | keywords | String | true | 返回数据:keywords = "a" ```javascript { "code": 200, "msg": "请求成功", "data": [ { "id": 3, "name": "稻草人(MEXICAN)长袖t恤男潮流男士打底衫上衣男青年圆领宽松休闲男装201灰色XL" }, { "id": 6, "name": "稻草人(MEXICAN)卫衣男春秋季潮流宽松长袖t恤青少年无帽圆领上衣服 雾霾蓝 XL" }, { "id": 7, "name": "啄木鸟(TUCANO)卫衣男士潮流宽松圆领长袖t恤学生时尚休闲套头上衣男 灰色 XL" }, .... ] } ``` ## 获取搜索历史 | 请求地址 | 方法 | | | ------------------- | ---- | -------- | | /api/search/history | GET | | | 请求参数 | 类型 | 是否必须 | | / | / | / | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": [ "a", "上衣", "裤" ] } ``` ## 清空搜索历史 | 请求地址 | 方法 | | | ------------------------ | ---- | -------- | | /api/search/clearhistory | GET | | | 请求参数 | 类型 | 是否必须 | | / | / | / | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": true } ``` ## 商品列表 | 请求地址 | 方法 | | | -------------- | ------ | -------- | | /api/goodslist | GET | | | 请求参数 | 类型 | 是否必须 | | keywords | String | true | | page | Number | true | | limit | Number | false | 返回数据:keywords="男装" page=1 limit = 10 ```javascript { "code": 200, "msg": "请求成功", "data": { "total": 27, "list": [ { "id": 3, "name": "稻草人(MEXICAN)长袖t恤男潮流男士打底衫上衣男青年圆领宽松休闲男装201灰色XL", "price": "68.00", "imgUrl": "https://img14.360buyimg.com/n7/jfs/t1/190971/16/36893/79345/64e5ff3aFa0d2e0d1/e3e6034325ab10b4.jpg", "shop": "稻草人(MEXICAN)男装京东自营旗舰店" }, { "id": 5, "name": "南极人外套男秋冬季潮流宽松休闲男士夹克加绒加厚棒球服厚棉服秋冬装男装衣服 小方块黑色 2XL 建议125-145斤", "price": "59.00", "imgUrl": "https://img12.360buyimg.com/n7/jfs/t1/203320/10/27633/97935/63317119E056e9da1/c1f4a6d45984b830.jpg", "shop": "南极人羽绒服旗舰店" }, { "id": 9, "name": "啄木鸟外套男士夹克秋冬季新款轻商务休闲中青年男装连帽上衣服免烫抗皱 JK9902白色【不加绒】 2XL(偏小,建议127-147斤)", "price": "99.00", "imgUrl": "https://img11.360buyimg.com/n7/jfs/t1/145031/25/38316/166187/64d090b5Ffa4b53f3/36749806d65b2ecd.jpg", "shop": "啄木鸟极澜专卖店" }, { "id": 13, "name": "啄木鸟外套男春秋款三合一冲锋衣男冬季新款休闲加绒夹克男装户外上衣服 深蓝单衣【可拆卸帽】 2XL(建议体重135-155斤)", "price": "79.00", "imgUrl": "https://img12.360buyimg.com/n7/jfs/t1/188330/15/31971/45162/63d887aeF09813401/30eb9d672dd5d1ab.png", "shop": "啄木鸟麦图专卖店" }, { "id": 16, "name": "YOOOURTHING男士休闲夹克青年时尚休闲连帽外套男薄款春秋季夹克男装 XZ1402-2130-卡其色 2XL【建议120-150斤】", "price": "49.00", "imgUrl": "https://img13.360buyimg.com/n7/jfs/t1/100084/4/36774/78306/6423d6a8F913e76ad/80a8cdf35c09e19c.jpg", "shop": "异月服饰专营店" }, { "id": 17, "name": "头号青年工装裤子男秋冬季加绒宽松胖子运动大码男装休闲裤男款 黑 5XL ", "price": "44.00", "imgUrl": "https://img12.360buyimg.com/n7/jfs/t1/164120/35/37742/124783/64b10c06F819d857d/e613440109ecc30f.jpg", "shop": "头号青年男装京东自营旗舰店" }, { "id": 21, "name": "【高端轻奢】罗蒙 休闲裤男秋冬季加绒加厚休闲裤男秋冬款2022新款长裤子男士宽松直筒冬季男装 宝蓝色【5036R加绒款】 28 腰围2尺10", "price": "399.00", "imgUrl": "https://img12.360buyimg.com/n7/jfs/t1/61705/14/20326/61303/633ffdd6E3cd1a6a3/51da3d9d78d10f30.jpg", "shop": "罗蒙聚美专卖店" }, { "id": 22, "name": "简男【纯棉2件装】长袖t恤男士纯棉秋衣男装外穿薄款春秋季打底衫上衣 KY卡其+R铁灰 XL建议130-150斤", "price": "59.00", "imgUrl": "https://img13.360buyimg.com/n7/jfs/t1/123556/17/36956/188649/64fc96a2F90fc72b5/28d553d67421311d.jpg", "shop": "尚衣服饰专营店" }, { "id": 25, "name": "【高端轻奢】罗蒙 秋冬款加绒加厚牛仔裤男修身直筒百搭男装高端弹力男士保暖长裤子 蓝色加绒款2045 32", "price": "588.00", "imgUrl": "https://img14.360buyimg.com/n7/jfs/t1/155702/8/33100/72199/637f8184Ecb6faa8b/fafeb4dc0a45d4aa.jpg", "shop": "罗蒙聚美专卖店" }, { "id": 29, "name": "皮尔卡丹羊羔绒外套捉绒衣秋冬季新款加绒加厚御寒保暖夹克男士摇粒绒男装 加绒LZH-922深蓝 XXL 135-150斤", "price": "138.00", "imgUrl": "https://img14.360buyimg.com/n7/jfs/t1/21988/19/18842/127393/6347a6f7Ecc7728ea/729c49acd349664e.jpg", "shop": "皮尔卡丹靓物专卖店" } ] } } ``` ## 商品信息 | 请求地址 | 方法 | | | ---------------- | ------ | -------- | | /api/goodsdetail | GET | | | 请求参数 | 类型 | 是否必须 | | id | Number | true | 返回数据:id = 29 ```javascript { "code": 200, "msg": "请求成功", "data": { "goodsId": 29, "name": "皮尔卡丹羊羔绒外套捉绒衣秋冬季新款加绒加厚御寒保暖夹克男士摇粒绒男装 加绒LZH-922深蓝 XXL 135-150斤", "price": "138.00", "shop": null, "imgList": [ "https://img14.360buyimg.com/n5/s50x66_jfs/t1/133194/25/30255/136667/6347a707Ead60571a/05aa471a901f26b4.jpg!cc_50x66", "https://img14.360buyimg.com/n5/s50x66_jfs/t1/87645/28/22899/95295/6347a709Eaac25bd0/42c542358e61687c.jpg!cc_50x66", "https://img14.360buyimg.com/n5/s50x66_jfs/t1/155849/12/31664/114988/6347a70cE8e3c50a1/1df09449d1e3636a.jpg!cc_50x66", "https://img14.360buyimg.com/n5/s50x66_jfs/t1/100730/20/32436/166457/6347a70fEa86986b7/5404d8a8578267db.jpg!cc_50x66", "https://img14.360buyimg.com/n5/s50x66_jfs/t1/27197/27/19444/172183/6347a715Ef98c345c/fbaff38eb9247548.jpg!cc_50x66" ], "color": [ "加绒LZH-922深灰", "加绒LZH-922酒红", "加绒LZH-922黑色", "加绒LZH-922深蓝", "常规BOB-921深灰", "常规BOB-921酒红", "常规BOB-921黑色", "常规BOB-921深蓝" ], "size": [ "M 90-105斤", "L 105-120斤", "XL 120-135斤", "XXL 135-150斤", "XXXL 150-165斤", "4XL 165-180斤", "5XL 180-195斤" ], "idx": [ "0", "1" ], "cateId": 101 } } ``` ## 获取token | 请求地址 | 方法 | | | ---------------- | ------ | -------- | | /api/goodsdetail | POST | | | 请求参数 | 类型 | 是否必须 | | code | String | true | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": ...... } ``` ## 获取购物车数据 | 请求地址 | 方法 | | | --------- | ---- | -------- | | /api/cart | GET | | | 请求参数 | 类型 | 是否必须 | | / | / | / | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": [ { id: "", name:"", price: "", count: "", state: "", imgUrl: "" } ] } ``` ## 更新购物车数据 | 请求地址 | 方法 | | | ---------------- | -------------------------------------------------- | -------- | | /api/cart/update | POST | | | 请求参数 | 类型 | 是否必须 | | data | {list: "购物车列表,具体内容看2.10",total:number} | true | 返回数据: ```javascript { "code": 200, "msg": "请求成功", "data": true } ``` # 使用thymeleaf返回html页面 ## 配置文件 ```properties spring.thymeleaf.check-template-location=false spring.thymeleaf.mode=HTML #classpath:一般来说就是对应的项目中:myproject/src/main/resources文件目录。 #classpath:/templates/就是将resources下的templates设置为静态文件目录 spring.thymeleaf.prefix= classpath:/templates/ spring.web.resources.static-locations=classpath:/static/ spring.thymeleaf.suffix= .html spring.thymeleaf.servlet.content-type= text/html spring.thymeleaf.cache= false spring.mvc.static-path-pattern=/** spring.thymeleaf.encoding=UTF-8 ``` ## 创建PageController ```java package com.laozheng.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class PageController { //范访问/index的时候就会返回templates下的README.html @RequestMapping("/index") public String index() { System.out.println("******************************获取README页面"); return "README"; } } ``` 也可以在拦截器中使用addVuewControllers ```java package com.laozheng.config; import com.laozheng.utils.UserLoginInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.*; @Configuration public class WebMvConfig implements WebMvcConfigurer { ... @Override public void addViewControllers(ViewControllerRegistry registry) { //比如访问http://localhost:8081的时候,就会返回README.html registry.addViewController("").setViewName("README"); } } ``` ## html页面中访问static文件夹下的文件 比如说 /src/java/main/resources/static 下有个images文件夹,想要使用里面的图片。因为在配置文件里已经设置了 ```properties spring.web.resources.static-locations=classpath:/static/ ``` 所以访问图片文件直接从images文件夹开始就行了。这样写就没有404报错了。 ```html ``` ## 将REAMME.md文件转换成html 我直接用的vscode的一个插件实现的,叫Markdown Preview Enhanced。 ![](markdownImg/markdownToHtml.png) 用vscode打开README.md文件,右键 -> MPE:打开侧边预览 ![](markdownImg/markdownToHtml2.png) 在预览页面右下角有一个菜单按钮,找到EXPORT -> HTML -> HTML(offline),然后再README.md文件所在位置就会生成一个README.html文件。 ![](markdownImg/markdownToHtml3.png) ## 设置README.html菜单栏默认显示 再body标签上添加 html-show-sidebar-toc="true" ```html ... ``` 删除link标签 ```html ``` 样式style标签中都有。 # 用宝塔面板部署 ## 安装java 打开宝塔面板,在左侧菜单栏选择网站 -> java 项目 -> java环境管理。 ![](markdownImg/btpanel/setJavaEnviroment.png) 安装好的jdk存放在 /usr/lib/jvm下,后面配置玩tomcat获取不到jdk的环境变量会用到这个路径。 ## 配置环境变量 编辑 /etc/profile文件 ![](markdownImg/btpanel/javaHomeEnviroment.png) 双击profile文件进行编辑,然后保存。 ![](markdownImg/btpanel/editProfile.png) jvm文件夹下的jdk文件名就是jdk-17.0.9,文件名不能错。之前看别人设置的jdk-17也没改,直接复用,结果耽误好长时间。 ![](./markdownImg/btpanel/jvmJDK.png) ## 安装tomcat java17用tomcat10,宝塔面板中只有9。 ![](markdownImg/btpanel/tomcatVersionInBT.png) 所以先从官网将对应版本的tomcat压缩包下载出来,在上传到面板中解压安装。 ![](markdownImg/btpanel/downloadTomcat.png) 在左侧菜单栏选择文件 根目录/www/server 将下载好的压缩包上传到这个位置。 ![](markdownImg/btpanel/uploadTomcat.png) 上传结束后开始解压,解压完成后就安装好了。 ![](markdownImg/btpanel/decompressionTomcat.png) ## 上传并运行java项目 运行前要确保宝塔面板和阿里云的想要运行的端口(8081)开放。 将java项目的jar包上传到 /www/wwwroot/java_project 下,然后进入终端,当前位置在 wwwroot 文件夹下,所以 cd java_project 就到jar包所在文件夹。 ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z ~]# ls rar db_shop.txt mylog.log nodejs bash_profile java_project NeteaseCloudMusicApi-master [root@iZ2zeclm8w2pszvogvyjd4Z ~]# cd java_project [root@iZ2zeclm8w2pszvogvyjd4Z java_project]# ls miniProgramAPI [root@iZ2zeclm8w2pszvogvyjd4Z java_project]# cd miniProgramAPI/ [root@iZ2zeclm8w2pszvogvyjd4Z miniProgramAPI]# ls miniProgramAPI.jar mylog.log ``` 在这里输入 java -jar miniProgranAPI 可以试试能不能正常启动项目。 ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z miniProgramAPI]# java -jar miniProgramAPI.jar . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-12-07T15:44:37.931+08:00 INFO 19957 --- [ main] com.laozheng.MiniProgramApiApplication : Starting MiniProgramApiApplication v0.0.1-SNAPSHOT using Java 17.0.9 with PID 19957 (/root/java_project/miniProgramAPI/miniProgramAPI.jar started by root in /root/java_project/miniProgramAPI) 2023-12-07T15:44:37.933+08:00 INFO 19957 --- [ main] com.laozheng.MiniProgramApiApplication : No active profile set, falling back to 1 default profile: "default" 2023-12-07T15:44:41.963+08:00 INFO 19957 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2023-12-07T15:44:41.994+08:00 INFO 19957 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-12-07T15:44:41.994+08:00 INFO 19957 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.15] 2023-12-07T15:44:42.454+08:00 INFO 19957 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2023-12-07T15:44:42.470+08:00 INFO 19957 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4398 ms 2023-12-07T15:44:45.712+08:00 INFO 19957 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2023-12-07T15:44:45.859+08:00 INFO 19957 --- [ main] com.laozheng.MiniProgramApiApplication : Started MiniProgramApiApplication in 9.193 seconds (process running for 11.253) ``` 配置文件里设置的端口是8081,上面显示在8080端口运行的,网上方法都试了端口号也改不了,最后也发现通过这个命令运行jar包,启动的tomcat也不是我装的。最后只能在命令后面加上 --server.port=8081才把端口号改掉了。 ```cmd java -jar /www/wwwroot/miniProgram/miniProgramAPI.jar --server.port=8081 ``` ## 将指令写入start.sh文件中 每次进入宝塔终端所处位置实在 /root 文件夹下,所以将文件放到这个位置。同时创建logs文件夹,用于存放输出的记录。 ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z ~]# ls db_shop.txt logs nodejs rar bash_profile java_project NeteaseCloudMusicApi-master start.sh ``` start.sh文件 ```sh java -jar java_project/miniProgramAPI/miniProgramAPI.jar --server.port=8081 > ~/logs/application.log 2>&1 ``` 然后输入指令,赋予文件可执行权限。每次测试直接执行./start.sh就好了。 ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z ~]# chmod +x start.sh ``` ## 让程序在后台一直运行 再创建一个nohupstart.sh。 ``` nohup java -jar java_project/miniProgramAPI/miniProgramAPI.jar --server.port=8081 > ~/logs/application.log 2>&1 & ``` ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z ~]# chmod +x nohupstart.sh [root@iZ2zeclm8w2pszvogvyjd4Z ~]# ./nohupstart.sh ``` 这样关闭终端,程序也保持运行状态。 ## 关闭nohup保持的进程 首先找到PID ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z ~]# netstat -tnlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:38716 0.0.0.0:* LISTEN 26056/python3 tcp 0 0 0.0.0.0:8100 0.0.0.0:* LISTEN 20884/java tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 20884/java tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 6035/mysqld tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 25488/nginx: worker tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 19336/java tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 1013/pure-ftpd (SER tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1583/sshd tcp6 0 0 :::3389 :::* LISTEN 28090/node /root/Ne tcp6 0 0 :::21 :::* LISTEN 1013/pure-ftpd (SER ``` 找到8081端口的PID为19336 ``` kill -15 19336 ``` # 遇到的问题 ## 在uni-app中axios在请求头中设置Authorization存放token,springboot拿不到 最后也不知道是哪里的问题,用postman设置好请求头发送后端就能收到。最后涉及到需要传token的请求,就用uni.request发送,后端能正常收到。 ## tomcat版本低 按照之前安装tomcat更改就行了 ## jdk版本低 在菜单栏网站选项下的java项目进行java环境配置选择jdk版本,实在不行手动下载。 ## jdk环境变量不对 在宝塔面板安装jdk17后,版本会显示17版本 ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z miniProgramAPI]# java -version java version "17.0.9" 2023-10-17 LTS Java(TM) SE Runtime Environment (build 17.0.9+11-LTS-201) Java HotSpot(TM) 64-Bit Server VM (build 17.0.9+11-LTS-201, mixed mode, sharing) ``` 当时安装17版本的jdk后显示的是 1.8.0.xx,因为第一次弄不太了解,从网上找的教程最后人家也没 java -version查看版本的步骤,不知道1.8版本的啥意思,我就误以为我配置好了。然后启动项目一直报 “**has been compiled by a more recent version of the Java Runtime** ”的错误,最后偶然看见看到一个输出jdk17版本信息的教程才知道当前用的jdk版本和实际安装的不是同一个。 之后以为没安装好,从新安装了一次结果还是一样依旧是 jdk 1.8。 在这耗了很长时间,突然想起来我最开始想运行jar包是通过xShell控制云服务器,那时候根据网上的教程在服务器中使用yum安装的jdk,可能就是环境变量指向的就是这个,才导致版本不对。 ## 配置.bashrc文件配置环境变量 ```cmd [root@iZ2zeclm8w2pszvogvyjd4Z ~]# vim .bashrc ``` ```cmd # .bashrc # User specific aliases and functions alias rm='rm -i' alias cp='cp -i' alias mv='mv -i' # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi #添加这三行配置jdk环境变量,如果本来就存在的话就更改路径 export JAVA_HOME="/usr/lib/jvm/jdk-17.0.9" export JRE_HOME="{JAVA_HOME}/lib:{JAVA_HOME}/bin:$PATH" export NVM_DIR="/www/server/nvm" # [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion alias php72='php72 -c /www/server/php/72/etc/php-cli.ini' ``` 最后esc -> :wq 保存不了,得 :wq!