springboot的简单应用

news2024/9/21 10:46:02

Mvc与三层架构

创建Spring项目

勾选web和mabais框架

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

server:
  port: 8080

spring:
  profiles:
    active: dev
  main:
    allow-circular-references: true
  datasource:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/elm?useSSL=true&allowPublicKeyRetrieval=true&serverTimezone=UTC
      username: yourname
      password: yourpass

mybatis:
  #mapper配置文件
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.zlh.entity
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

logging:
  level:
    com:
      zlh:
        mapper: debug
        service: info
        controller: 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 code
    private Integer code;
    //the response message
    private String msg;
    //the response data
    private 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-injection
    private 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
    @Autowired
    private BusinessMapper businessMapper;
    @Override
    public void insert(Business business) {
        business.setBusinessImg("图片正在加载中");
        businessMapper.insert(business);
    }//of insert

    @Override
    public Business queryById(String param) {
        return businessMapper.queryById(param);
    }//of queryById

    @Override
    public 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.coloradmin.cn/o/1935808.html

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

相关文章

刚起步的家庭海外仓:涉及到的全部业务优化流程

对于家庭海外仓来说&#xff0c;最难的阶段应该就是刚起步的时候。对业务流程不熟悉&#xff0c;也没有客户积累&#xff0c;本身的预算又十分有限。 在这个情况下应该注意什么&#xff0c;怎样才能顺利的开展业务&#xff1f;今天我们就针对这个问题详细的梳理了一下家庭海外…

尚品汇-(二十一)

目录&#xff1a; &#xff08;1&#xff09;使用redis实现分布式锁 &#xff08;2&#xff09;优化之设置锁的过期时间 &#xff08;3.&#xff09;优化之UUID防误删 &#xff08;4&#xff09;优化之LUA脚本保证删除的原子性 &#xff08;1&#xff09;使用redis实现分布…

go语言编程 小试牛刀 goroutine和reflect知识点

&#xff08;一&#xff09;goroutine package _caseimport "fmt"// sum 函数计算整数切片 values 的总和&#xff0c;并将结果发送到 resultChan 通道中 func sum(values []int, resultChan chan int) {sum : 0for _, value : range values {sum value}resultChan…

HarmonyOS NEXT学习——@Styles、@Extend、stateStyles

Styles装饰器 定义组件重用样式 仅支持通用属性和通用事件不支持参数可以定义全局和组件内使用&#xff0c;全局使用需要加function // 全局 Styles function functionName() { ... }// 在组件内 Component struct FancyUse {Styles fancy() {.height(100)} }组件内Styles的优…

智能一体式闸门在灌区中的应用

在现代化的农业灌溉领域&#xff0c;智能一体式闸门作为一种集自动化、智能化、高效能于一体的先进设备&#xff0c;正逐渐在灌区管理中发挥着重要作用。 灌区是农业生产的重要基地&#xff0c;其水资源的管理和利用直接关系到农作物的生长和产量。然而&#xff0c;传统的闸门管…

旋转中的图片视觉差效果

Hello&#xff0c;亲爱的宝子们&#xff1f;最近我一个前端架构师却临时顶替产品经理的工作&#xff0c;导致最近一周实在太忙了&#xff0c;都没有来得及更新文章。在这里想大家道歉了&#xff01;也想厚颜无耻的问问大家想我了吗&#xff1f;(●◡●) 今天给大家带来一个非常…

Vue 使用 Element UI 组件库

https://andi.cn/page/621589.html

RAG介绍

一&#xff0c;RAG概述 RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;是一种结合了信息检索与生成任务的技术&#xff0c;它通过将外部知识库与大模型的生成能力相结合&#xff0c;提高了生成内容的准确性和丰富性。以下是关于RAG应用的…

【产品那些事】固件安全-关于OTA升级包分析

文章目录 前言什么是OTA?升级包(固件)的类型和架构案例tp-link路由器升级包怎么解包分析?binwalk安装及使用ubi_reader安装及使用unsquashfs安装及使用某车企OTA升级包通用Android OTA解包相关分区第二层解包前言 什么是OTA? OTA(Over-the-Air)是一种通过无线通信网络(…

go的Mutex实现原理及演进

下面的这个是对于昨天晚上读的几篇关于go中锁的文章知识点的总结 文章目录 1. 引言1.1 并发编程的挑战1.2 Mutex 的角色1.3 Mutex 设计的演进1.4 技术追求的美妙 引言部分详细解释引言部分注意点引言部分流程图 2. Mutex 架构演进2.1 初版 Mutex 设计2.2 性能优化 - 给新人机会…

【ffmpeg】一篇文章搞定YUV

文章目录 前言YUV是什么&#xff1f;YUV的用途YUV采样格式采样格式是什么YUV采样格式有哪些YUV采样格式的区别 YUV与RGBRGB 颜色空间YUV 颜色空间RGB 与 YUV 的比较RGB 转 YUV 公式YUV 转 RGB 公式注意事项 YVU数据计算通用公式4:4:4 采样格式4:2:2 采样格式4:2:0 采样格式实例…

win10删除鼠标右键选项

鼠标右键菜单时&#xff0c;发现里面的选项特别多&#xff0c;找一下属性&#xff0c;半天找不到。删除一些不常用的选项&#xff0c;让右键菜单变得干净整洁。 1、按下键盘上的“winR”组合按键&#xff0c;调出“运行”对话框&#xff0c;输入“regedit”命令&#xff0c;点击…

达梦数据库的系统视图v$rapply_log_task

达梦数据库的系统视图v$rapply_log_task 达梦数据库的V$RAPPLY_LOG_TASK视图是一个动态性能视图&#xff0c;主要用于在备库上查询。该视图需要在备库上查询&#xff08;DMDSC 备库需要在控制节点&#xff08;重演节点&#xff09;上查询&#xff09;&#xff0c;用于查询备库…

专业PDF编辑工具:Acrobat Pro DC 2024.002.20933绿色版,提升你的工作效率!

软件介绍 Adobe Acrobat Pro DC 2024绿色便携版是一款功能强大的PDF编辑和转换软件&#xff0c;由Adobe公司推出。它是Acrobat XI系列的后续产品&#xff0c;提供了全新的用户界面和增强功能。用户可以借助这款软件将纸质文件转换为可编辑的电子文件&#xff0c;便于传输、签署…

RocketMQ单结点安装/Dashboard安装

目录 1.安装NameServer 2.安装Broker 3.使用自带工具测试数据发送 4.使用DashBoard进行查看 5.关闭相关设备 前置条件&#xff1a;两台虚拟机CentOS Linux release 7.5.1804(ps:当然也可以都部署在一台机器上) RocketMq属于天生集群。需要同时启动nameServer和Broker进行…

STP(802.1D)

802.1D&#xff1a;也成为生成树协议&#xff08;Spanning Tree Protocol&#xff0c;STP&#xff09;&#xff0c;是一种工作在数据链路层的通信协议 作用&#xff1a;防止交换机冗余链路产生的环路&#xff0c;确保以太网中无环路的逻辑拓扑结构&#xff0c;从而避免广播风暴…

MacBook电脑远程连接Linux系统的服务器方法

一、问题简介 Windows 操作系统的电脑可使用Xshell等功能强大的远程连接软件。通过连接软件&#xff0c;用户可以在一台电脑上访问并控制另一台远程计算机。这对于远程技术支持、远程办公等场景非常有用。但是MacBook电脑的macOS无法使用Xshell。 在Mac上远程连接到Windows服…

昇思25天学习打卡营第18天 | 基于MindSpore的GPT2文本摘要

昇思25天学习打卡营第18天 | 基于MindSpore的GPT2文本摘要 文章目录 昇思25天学习打卡营第18天 | 基于MindSpore的GPT2文本摘要数据集创建数据集数据预处理Tokenizer 模型构建构建GPT2ForSummarization模型动态学习率 模型训练模型推理总结打卡 数据集 实验使用nlpcc2017摘要数…

详解MLOps,从Jupyter开发到生产部署

大家好&#xff0c;Jupyter notebook 是机器学习的便捷工具&#xff0c;但在应用部署方面存在局限。为了提升其可扩展性和稳定性&#xff0c;需结合DevOps和MLOps技术。通过自动化的持续集成和持续交付流程&#xff0c;可将AI应用高效部署至HuggingFace平台。 本文将介绍MLOps…

网安播报|Python 的 GitHub 核心资源库 token 意外曝光,风险巨大

1、Python 的 GitHub 核心资源库 token 意外曝光&#xff0c;风险巨大 网络安全专家发现了意外泄露的 GitHub token&#xff0c;能以最高权限访问 Python 语言、Python 软件包索引&#xff08;PyPI&#xff09;和 Python 软件基金会&#xff08;PSF&#xff09;存储库。如果该 …