springboot的简单应用

Mvc与三层架构

创建Spring项目

勾选web和mabais框架

配置yml文件,这里创建spring项目默认生成的是propertise文件,但是properties文件的格式看起来没有yml文件一目了然。yml文件配置数据库还有映射mapper层的xml文件以及设置日志级别,比如mapper层的日志级别是debug,而另外两层都是info。

server:port: 8080spring:profiles:active: devmain:allow-circular-references: truedatasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/elm?useSSL=true&allowPublicKeyRetrieval=true&serverTimezone=UTCusername: yournamepassword: yourpassmybatis:#mapper配置文件mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.zlh.entityconfiguration:#开启驼峰命名map-underscore-to-camel-case: truelogging:level:com:zlh:mapper: debugservice: infocontroller: info

建立如下的包,controller控制器是SpringBoot中负责处理http请求的组件,service是负责处理业务逻辑的组件,mapper是负责数据持久化的组件,由于在SpringMVC中,mapper要么通过xml文件来实现数据持久化,要么通过注解的方式进行,所以只需要一个mapper接口即可。由于需要查询商家及其食品,所以需要用到business和entity两个实体,在SpringBoot中其实使用DTO对象作为不同数据层之间传输对象的模式更为常见,这里由于业务简单,所以所有层之间都是采用的实体本身。Result负责封装返回结果,即在软件开发中所有的返回结果都应该是统一的格式。

       Result类,封装所有controller返回的结果,实现Serializable接口,让这个类能够被序列化(自动转换为json格式,http之间能够直接传输)。封装返回结果使用了大量的泛型的思想。方法是静态泛型方法,参数也是泛型参数。极大保证了灵活性。此外,响应码,响应信息,响应数据这个封装格式也是运用的最广泛的封装格式。

import lombok.Data;import java.io.Serializable;/*** this class is used to unify the return result* The Serializable interface is used to mark the class could be Serialized.* */
@Data
public class Result<T> implements Serializable {//the status codeprivate Integer code;//the response messageprivate String msg;//the response dataprivate T data;/*** The generic method can encapsulate the result into the Result class which can be auto serialized.* */public static <T> Result<T> success(){Result<T> result = new Result<>();result.code=1;return result;}/*** The generic method can encapsulate the result into the Result class which can be auto serialized.* @param object  could be any object.* */public static <T> Result<T> success(T object){Result<T> result = new Result<>();result.code = 1;result.data = object;return result;}/*** The generic method can encapsulate the result into the Result class which can be auto serialized.* @param msg The error message.* */public static <T> Result<T> error(String msg){Result<T> result = new Result<>();result.msg = msg;result.code=0;return result;}
}//of class Result

Springboot通过启动类来启动项目,第一个注解是将这个类注册为启动类,使用这个注解快速配置Springboot项目,并且启动main方法后,项目就会自动监听配置文件指定的端口。

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;@SpringBootApplication
@EnableTransactionManagement //use the annotation of the transaction.
@Slf4j
public class Application {/***The entrance of the program and the* */public static void main(String[] args) {SpringApplication.run(Application.class, args);log.info("server Started");}
}

 Controller类,由于项目是前后端分离开发的,所以我们需要解决跨域问题,否则游览器会拦截请求,这里简单的将本机的所有请求全部放行。@RestController注解将这个类标记为SpringMVC控制器的同时指定所有的方法返回值(全部通过序列化转为json格式)直接写入http请求体。@RequestMapping是指定这个控制器中所有方法的前缀名。在SpringBoot中,所有的bean都是通过注入的方式来实例化的,只需要将需要实例化的类或者接口使用@Bean注解或者@Service等注解标记即可。由于查询操作分为根据id查询和根据名称进行查询,而根据名称模糊匹配有可能出现多个商家匹配的情况,所以这里的返回类型是用的泛型。

package com.zlh.controller;import com.zlh.pojo.entity.Business;
import com.zlh.result.Result;
import com.zlh.service.BusinessService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;@CrossOrigin(origins = {"http://localhost:8082", "null"})//allow all request from localhost.
@RestController//write the returned object into the http response
@RequestMapping("/business")//map the web request,here is public url of all method of this controller.
@Slf4j//the log of this class
public class businessController {//use this annotation,your class must use the Bean annotation or your implementation class of the//interface must use the used the corresponding annotation.@Autowired//auto-injectionprivate BusinessService businessService;/****/@PostMapping("/query/{param}")public  Result<?> query(@PathVariable String param){log.info("查询商家信息,查询参数为:{}",param);Business business = new Business();List<Business> businessesList = new ArrayList<>();try{Integer.parseInt(param);business=businessService.queryById(param);return Result.success(business);}catch (Exception e){businessesList=businessService.queryByName(param);for (Business b:businessesList) System.out.println(b);return Result.success(businessesList);}}//of query/**** */@PostMapping("/insert")public Result insert(@RequestBody Business business){log.info("注册商家信息,注册参数为:{}",business);businessService.insert(business);return Result.success();}//of insert
}//of class businessController

 由于没有设计相应的dto和功能都是简单的查找和插入,这里的业务层设计比较简单,直接注入mapper接口然后调用相关方法即可。

 

import com.zlh.mapper.BusinessMapper;
import com.zlh.pojo.entity.Business;
import com.zlh.service.BusinessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class BusinessServiceImpl implements BusinessService {//inject businessMapper@Autowiredprivate BusinessMapper businessMapper;@Overridepublic void insert(Business business) {business.setBusinessImg("图片正在加载中");businessMapper.insert(business);}//of insert@Overridepublic Business queryById(String param) {return businessMapper.queryById(param);}//of queryById@Overridepublic List<Business> queryByName(String param) {return businessMapper.queryByName(param);}//of queryByName
}//of class BusinessServiceImpl

Mapper层

Mapper层负责实现数据持久化,简单的sql语句直接使用相应的注解,复杂语句使用xml文件。这里全部采用的是xml文件(并不是所有语句都很复杂,只是适应写配置文件)。

import com.zlh.pojo.entity.Business;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;@Mapper
public interface BusinessMapper {List<Business> queryByName(String name);Business queryById(String id);void insert(Business business);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zlh.mapper.BusinessMapper"><resultMap id="BusinessWithFood" type="com.zlh.pojo.entity.Business"><id property="businessId" column="businessId"/><result property="businessName" column="businessName"/><result property="businessAddress" column="businessAddress"/><result property="businessExplain" column="businessExplain"/><result property="businessImg" column="businessImg"/><result property="orderTypeId" column="orderTypeId"/><result property="starPrice" column="starPrice"/><result property="remarks" column="remarks"/><collection property="foods" column="businessId" foreignColumn="businessId" ofType="com.zlh.pojo.entity.Food"select="getFoodByBusinessId"/></resultMap><select id="queryById" resultMap="BusinessWithFood">SELECT * FROM elm.business WHERE businessId = #{id}</select><select id="getFoodByBusinessId" resultType="com.zlh.pojo.entity.Food" parameterType="long">select * FROM elm.food WHERE businessId=#{businessId}</select><select id="queryByName" resultMap="BusinessWithFood">select * from elm.business where businessName like CONCAT('%',#{name},'%')</select><insert id="insert" parameterType="com.zlh.pojo.entity.Business" useGeneratedKeys="true" keyProperty="businessId">insert into elm.business (businessName, businessAddress, businessExplain,businessImg, orderTypeId, starPrice, deliveryPrice)VALUES (#{businessName}, #{businessAddress}, #{businessExplain},#{businessImg},#{orderTypeId},#{starPrice}, #{deliveryPrice})</insert>
</mapper>

 

查询操作由于要返回商家和食品两个实体的内容。我开始想到的是sql语句里面的连接,但三个连接查询出来的结果全都有问题,后面想到了上课学的association,但是assocaition适应于一对一的关系,这里明显是一对多的关系(一个菜品对应一个店铺,一个店铺对应多个菜品,数据比较极端),所以查资料找到了collection来处理这种一对多的关系。首先要在Business里面加上一个food的列表,泛型指定为Food类型,Food类就对应food这张表。

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Food {private long foodId;private String foodName;private String foodExplain;private String foodImg;private float foodPrice;private long businessId;private String remarks;
}

再写一个resultMap,里面对应的是Business这个实体的属性,而collection与food这个列表对应,指定food的外键还有查询food的方法,这个select方法在执行这个resultMap时会自动加载执行。但是在这个方法中要指定resultMap。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zlh.mapper.BusinessMapper"><resultMap id="BusinessWithFood" type="com.zlh.pojo.entity.Business"><id property="businessId" column="businessId"/><result property="businessName" column="businessName"/><result property="businessAddress" column="businessAddress"/><result property="businessExplain" column="businessExplain"/><result property="businessImg" column="businessImg"/><result property="orderTypeId" column="orderTypeId"/><result property="starPrice" column="starPrice"/><result property="remarks" column="remarks"/><collection property="foods" column="businessId" foreignColumn="businessId" ofType="com.zlh.pojo.entity.Food"select="getFoodByBusinessId"/></resultMap><select id="queryById" resultMap="BusinessWithFood">SELECT * FROM elm.business WHERE businessId = #{id}</select><select id="getFoodByBusinessId" resultType="com.zlh.pojo.entity.Food" parameterType="long">select * FROM elm.food WHERE businessId=#{businessId}</select><select id="queryByName" resultMap="BusinessWithFood">select * from elm.business where businessName like CONCAT('%',#{name},'%')</select><insert id="insert" parameterType="com.zlh.pojo.entity.Business" useGeneratedKeys="true" keyProperty="businessId">insert into elm.business (businessName, businessAddress, businessExplain,businessImg, orderTypeId, starPrice, deliveryPrice)VALUES (#{businessName}, #{businessAddress}, #{businessExplain},#{businessImg},#{orderTypeId},#{starPrice}, #{deliveryPrice})</insert>
</mapper>

结果图

根据id查询

根据名称模糊查询

插入

 

 htmnl页面,有些功能为了考试修改了一部分,可能会有bug。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>商家查询与添加</title><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body><h2>商家查询</h2><input type="text" id="searchInput" placeholder="输入商家ID或名称"><button onclick="queryMerchant()">查询</button><div id="result"></div><h2>商家添加</h2><form id="addForm"><input type="text" name="businessName" placeholder=""><input type="text" name="businessAddress" placeholder="商家地址"><input type="text" name="businessExplain" placeholder="商家描述"><input type="text" name="orderTypeId" placeholder="点餐分类"><button type="button" onclick="addMerchant()">添加</button></form><script>function queryMerchant() {  var param = $('#searchInput').val();    $.ajax({    url: 'http://localhost:8080/business/query/' + encodeURIComponent(param),    type: 'POST',   success: function(data) {    var book = Array.isArray(data.data) ? data.data : [data.data]; //将所有商家的信息统一转为数组形式来渲染if(book[0]==null){$('#result').html('没有找到对应的商家信息');   }else{var resultDiv = $('#result');  resultDiv.empty(); // 清空原来的表格$.each(book, function(index, book) {  // 商家信息表格  var businessTable = $('<table class="business-table"></table>');  var businessHeader = $('<thead><tr><th>ID</th><th>名称</th><th>价格</th><th>作者</th><th>出版社Id</th></tr></thead>');  var businessBody = $('<tbody><tr><td>' + book.id + '</td><td>' + book.bookName + '</td><td>' + book.price +'</td><td>' + book.author +'</td><td>' + book.press_id +'</td></tr></tbody>');  businessTable.append(businessHeader).append(businessBody);  resultDiv.append(businessTable);  });  // 如果所有商家都没有foods,则显示提示信息if (resultDiv.find('.foods-table tbody tr').length === 0) {   }  }},  error: function(jqXHR, textStatus, errorThrown) {  // 处理请求失败的情况  $('#result').html('<p>请求失败: ' + textStatus + ', ' + errorThrown + '</p>');  }  });  
}function addMerchant() {var formData = $('#addForm').serializeArray(); // 序列化表单数据并转换为数组var jsonData = {};for (var i = 0; i < formData.length; i++) {jsonData[formData[i].name] = formData[i].value;}$.ajax({url: 'http://localhost:8080/business/insert',type: 'POST',contentType: 'application/json', data: JSON.stringify(jsonData), success: function(data) {alert('商家添加成功!');},error: function(xhr, status, error) {console.error("添加失败: " + error);}});}</script>
</body>
</html>

 

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

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

相关文章

去中心化技术的变革力量:探索Web3的潜力

随着区块链技术的发展和应用&#xff0c;去中心化技术正成为数字世界中的一股强大变革力量。Web3作为去中心化应用的新兴范式&#xff0c;正在重新定义人们对于数据、互联网和价值交换的认知。本文将探索去中心化技术的基本概念、Web3的核心特征及其潜力应用&#xff0c;展示其…

WebRTC音视频-环境搭建

目录 期望效果 1:虚拟机和系统安装 2:WebRTC客户端环境搭建 2.1&#xff1a;VScode安装 2.2&#xff1a;MobaXterm安装 3:WebRTC服务器环境搭建 3.1&#xff1a;安装openssh服务器 3.2&#xff1a;安装Node.js 3.3&#xff1a;coturn穿透和转发服务器 3.3.1&a…

Docker 镜像使用和安装

​ 1、简介 Docker是一个开源的应用容器引擎&#xff1b;是一个轻量级容器技术&#xff1b; Docker支持将软件编译成一个镜像&#xff1b;然后在镜像中各种软件做好配置&#xff0c;将镜像发布出去&#xff0c;其他使用者可以直接使用这个镜像&#xff1b; 运行中的这个镜像…

vue2 使用代码编辑器插件 vue-codemirror

vue 使用代码编辑器插件 vue-codemirror 之前用过一次&#xff0c;当时用的一知半解的&#xff0c;所以也没有成文&#xff0c;前几天又因为项目有需求&#xff0c;所以说有用了一次&#xff0c;当然&#xff0c;依旧是一知半解&#xff0c;但是还是稍微写一下子吧&#xff01;…

双非一本嵌入式方向怎么学?

双非一本&#xff08;非“985”和“211”工程重点建设的本科院校&#xff09;的学生在学习嵌入式方向时&#xff0c;可以通过以下步骤和策略来系统地学习和提升自己。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学…

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(二)-定义和缩写

引言 3GPP TS 23.256 技术规范&#xff0c;主要定义了3GPP系统对无人机&#xff08;UAV&#xff09;的连接性、身份识别、跟踪及A2X&#xff08;Aircraft-to-Everything&#xff09;服务的支持。 3GPP TS 23.256 技术规范&#xff1a; 【免费】3GPPTS23.256技术报告-无人机系…

前端JS特效第46集:js-实现响应式节庆活动砸金蛋效果

js-实现响应式节庆活动砸金蛋效果&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>响应式节庆活动砸金蛋…

Diffusion【1】:SDSeg——基于Stable Diffusion的单步扩散分割!

文章目录 前言AbstractIntroductionMethodsLatent EstimationConcatenate Latent FusionTrainable Vision Encoder ExperimentDatasets and Evaluation MetricsImplementation DetailsExperimental SettingsInference Stage Main ResultsComparison with State-of-the-ArtsComp…

组队学习——支持向量机

本次学习支持向量机部分数据如下所示 IDmasswidthheightcolor_scorefruit_namekind 其中ID&#xff1a;1-59是对应训练集和验证集的数据&#xff0c;60-67是对应测试集的数据&#xff0c;其中水果类别一共有四类包括apple、lemon、orange、mandarin。要求根据1-59的数据集的自…

在RK3568上如何烧录MAC?

这里我们用RKDevInfoWriteTool 1.1.4版本 下载地址&#xff1a;https://pan.baidu.com/s/1Y5uNhkyn7D_CjdT98GrlWA?pwdhm30 提 取 码&#xff1a;hm30 烧录过程&#xff1a; 1. 解压RKDevInfoWriteTool_Setup_V1.4_210527.7z 进入解压目录&#xff0c;双击运行RKDevInfo…

24暑假算法刷题 | Day16 | LeetCode 513. 找树左下角的值,112. 路径总合,106. 从中序和后序遍历序列构造二叉树

目录 513. 找树左下角的值题目描述题解 112. 路径总合题目描述题解 106. 从中序和后序遍历序列构造二叉树题目描述题解 513. 找树左下角的值 点此跳转题目链接 题目描述 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至…

虚继承(C++)

目录 菱形继承 虚继承 虚继承原理 虚继承使用注意事项&#xff1a; 不要把所有的遗憾都留给未来&#xff0c;趁年轻出去走走&#xff0c; 让我们用心去感受这个世界&#xff0c;用脚步去丈量这个世界的距离。 这里是来自M--Y的专栏&#xff1a;C启&#xff08;&#xff09;航…

SAP ABAP 批导函数(封装版)

EXCEL批导函数相信大家熟悉的不能再熟悉了&#xff0c;但是特殊场景不同函数对工作的影响真的很大。 整理本篇文章是因为公司电脑统一使用了加密系统&#xff0c;通过先前的统一函数无法直接上传&#xff0c;每次都要先另存为TEXT文本后上传&#xff0c;用户体验非常差&#x…

持续集成01--Git版本管理及基础应用实践

前言 本系列文章旨在深入探讨持续集成/持续部署&#xff08;Continuous Integration/Continuous Deployment, CI/CD&#xff09;流程中的各个环节&#xff0c;而本篇将聚焦于Git版本管理及其基本应用。通过本文&#xff0c;读者将了解到Git的基本原理、安装配置、基本命令以及如…

GuLi商城-商品服务-API-品牌管理-品牌分类关联与级联更新

先配置mybatis分页&#xff1a; 品牌管理增加模糊查询&#xff1a; 品牌管理关联分类&#xff1a; 一个品牌可以有多个分类 一个分类也可以有多个品牌 多对多的关系&#xff0c;用中间表 涉及的类&#xff1a; 方法都比较简单&#xff0c;就不贴代码了

无线物联网新时代,RFID拣货标签跟随潮流

拣选技术的演变历程&#xff0c;本质上是从人力操作向自动化、智能化转型的持续进程。近期&#xff0c;“货寻人”技术成为众多企业热烈追捧的对象&#xff0c;它可以根据企业的特定需求&#xff0c;从众多拣选方案中选出最优解。那么&#xff0c;在采用“货到人”拣选技术时&a…

【python】OpenCV—Scanner

文章目录 1、需求描述2、代码实现3、涉及到的库函数cv2.arcLengthcv2.approxPolyDPskimage.filters.threshold_localimutils.grab_contours 4、完整代码5、参考 1、需求描述 输入图片 扫描得到如下的结果 用OpenCV构建文档扫描仪只需三个简单步骤: 1.边缘检测 2.使用图像中…

VS code配置docker远程连接

一 前置条件 1、本地已安装docker 2、服务端docker已配置Docker配置远程连接 二 VScode安装docker扩展 三 执行docker命令 1、切换到远程docker节点 docker context create remote-docker --docker "hosthttp://192.168.6.9:2375" 2、使用远程节点 docker cont…

PyTorch 深度学习实践-逻辑斯蒂回归

视频指路 参考博客笔记 参考笔记二 用来分类的模型 说明&#xff1a;1、 逻辑斯蒂回归和线性模型的明显区别是在线性模型的后面&#xff0c;添加了激活函数(非线性变换) ​ 2、分布的差异&#xff1a;KL散度&#xff0c;cross-entropy交叉熵 现在损失函数衡量不是距离而是分布…

学习react-环境手脚架页面路由

1. 搭建环境 安装node和npm 在下面网址下载node&#xff0c;并安装 https://nodejs.cn/ #检测是否ok node -v npm -v安装react npm install -g create-react-app2. 创建手脚架&#xff08;TypeScript&#xff09; create-react-app my-app --template typescript cd my-a…