我的第一个springboot

我的第一个springboot

一、开发工具

  1. java编译器: IntelliJ IDEA 社区版免费使用
  2. 数据库服务:MySQL 社区版免费使用
  3. 数据库管理:MySQL Workbench 社区版免费使用

二、项目构建

IntelliJ IDEA可以直接构建项目,这里采用高效的在线构建方式 spring-initializr

界面如下:

2021-06-09_221430

我将分四个区域简单描述一下如何使用spring-initializr:

  1. 项目管理工具、开发语言等

    • Project:表示构建的工程的类型,即构建的工程所使用的项目管理工具,建议选择maven

    • Language:表示构建的工程所使用的语言,这里选择java

    • Spring Boot:表示使用的Spring Boot的版本,默认即可

  2. 项目基本信息

    • Group:Group id

    • Artifact:Artifact id

    • Name:项目名称

    • Description:项目描述

    • Package name:包名称

    • Packaging:打包类型

    • Java:JDK版本,推荐8.0

  3. 项目依赖,这些依赖信息在工程构建完成后,这些消息会出现在pom.xml中

    • Spring Web: Web框架
    • MyBatis Framework:一款优秀的持久层框架
    • MySQL Driver:mysql驱动
  4. 按钮组

    • GENERATECTRL: 导出构建文件

    • EXPLORECTRL : 预览构建文件

    • SPACESHARE: 分享构建链接

三、hello world

这个过程将用spring boot框架运行出第一个接口程序

  1. 使用IDE打开构建后的项目

    首次打开
  1. 修改配置文件,resource文件夹下application.properties(项目创建时自动生成这个文件的),为了语法简便,我们把application.properties改成application.yml,其编写内容如下:

    server:
      port: 8080  #tomcat端口
    
  1. 更新maven依赖,右侧打开maven工作区,点击刷新按钮即可

    maven
  1. 创建controller包,以及testController.java

    Controller
  1. 添加testController.java代码,以及相关注解,RequestMapping则为相应路由

    package com.zh.test.controller;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.*;
    import java.util.HashMap;
    import java.util.Map;
    
    @RestController
    @RequestMapping(value = "/test")
    public class testController {
    
        @RequestMapping(value = "/get")
        public String Get(){
            return "Hello world!";
        }
    }
    
  1. 选择testApplication,添加过滤数据库注解,springboot默认需要数据库

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    
  1. 选择testApplication,点击main函数旁边的运行按钮即可运行程序,下方如果出现端口号以及没有错误信息则表示正常。注意:数据库如果链接不上是不能运行的。

    run
  1. 进入浏览器,输入地址 http://127.0.0.1:8080/test/get 即可访问相关服务
succcess
  1. 至此,一个不含数据库操作的接口已经构建完成。如果你不满足于此,请往下看。

四、进阶-完整项目

完整的结构会涉及到MVC设计模式以及三层架构,这里采用的是三层架构+控制器的方式

MVC设计模式:视图View、模型Model、控制器Controller

三层架构分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL),再加上实体类库(Model)

1. 创建完整结构

在Application同级目录创建如下包:

  • comm:公共类

  • controller:控制器

  • domain:实体类库

  • mapper:数据访问层

  • service:业务逻辑层-接口

  • serviceImpl:业务逻辑层-接口实现

2.创建数据库表

以管理员信息为例,建表语句如下:

create table if not exists test.admins
(
    Guid varchar(50) charset utf8 not null
        primary key,
    NickName varchar(50) not null comment '登录名称',
    Name varchar(50) not null comment '用户名',
    Password varchar(20) not null comment '密码',
    Remark varchar(200) null comment '备注'
)
comment '管理员';

3.实体类库

示例:domain > Admins.java

package com.zh.test.domain;

import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;

/**
 * 管理员
 * zh
 * 2021-06-08
 */
public class Admins {

    private String guid;
    private String nickname;
    private String name;
    private String password;
    private String remark;

    public String getGuid() {
        return guid;
    }
    public void setGuid(String guid) {
        this.guid = guid;
    }
    public String getNickname() {
        return nickname;
    }
    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
}

4.数据访问层 mapper

示例:mapper > AdminsMapper.java

package com.zh.test.mapper;

import com.zh.test.domain.Admins;
import java.util.List;
import java.util.Map;

/**
 * AdminsMapper
 * zh
 * 2021-06-09
 */
public interface AdminsMapper {
    /**
     * 全字段插入
     */
    int insert(Admins record);

    /**
     * 对非空字段插入
     */
    int insertSelective(Admins record);

    /**
     * 对非空字段更新
     */
    int updateByPrimaryKeySelective(Admins record);

    /**
     * 全字段更新
     */
    int updateByPrimaryKey(Admins record);

    /**
     * 通过主键字段删除
     */
    int deleteByPrimaryKey(String Guid);

    /**
     * 通过主键字段查询
     */
    Admins selectByPrimaryKey(String Guid);

    /**
     * 获取序列值
     */
    Long getNextVal();

    /**
     * 获取数据
     */
    List<Admins> selectAllByMap(Map map);
}

5.业务逻辑层-接口

示例:service > IAdminsService.java

package com.zh.test.service;

import com.zh.test.domain.Admins;
import com.github.pagehelper.PageInfo;
import java.util.Map;
import java.util.List;

/**
 * AdminsService
 * zh
 * 2021-06-08
 */
public interface IAdminsService {

    /**
     * 新增
     */
    void add(Admins record) throws Exception;

    /**
     * 修改
     */
    void update(Admins record) throws Exception;

    /**
     * 删除
     */
    void delete(String Guid) throws Exception;

    /**
     * 获取分页数据
     */
    PageInfo getList(Map map) throws Exception;

    /**
     * 获取序列值
     */
    Long getNextVal() throws Exception;

    /**
     * 获取列表数据
     */
    List<Admins> selectAll(Map map) throws Exception;

    /**
     * 获取实体
     */
    Admins getModel(String Guid) throws Exception;

}

6.业务逻辑层-接口实现

示例:serviceImpl > AdminsServiceImpl.java

package com.zh.test.serviceImpl;

import com.zh.test.mapper.AdminsMapper;
import com.zh.test.domain.Admins;
import com.zh.test.service.IAdminsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.util.List;
import java.util.Map;

/**
 * AdminsServiceImpl
 * zh
 * 2021-06-08
 */
@Service
public class AdminsServiceImpl implements IAdminsService {

    @Autowired
    private AdminsMapper adminsMapper;


    /**
     * 获取序列值
     */
    @Override
    public Long getNextVal() throws Exception {
        return adminsMapper.getNextVal();
    }

    /**
     * 新增
     */
    @Override
    public void add(Admins record) throws Exception {
        adminsMapper.insertSelective(record);
    }

    /**
     * 修改
     */
    @Override
    public void update(Admins record) throws Exception {
        adminsMapper.updateByPrimaryKeySelective(record);
    }

    /**
     * 删除
     */
    @Override
    public void delete(String Guid) throws Exception {
        adminsMapper.deleteByPrimaryKey(Guid);
    }

    /**
     * 获取实体
     */
    @Override
    public Admins getModel(String Guid) throws Exception {
        return adminsMapper.selectByPrimaryKey(Guid);
    }

    /**
     * 获取列表
     */
    @Override
    public List<Admins> selectAll(Map map) throws Exception {
        return adminsMapper.selectAllByMap(map);
    }

    /**
     * 获取分页数据
     */
    @Override
    public PageInfo getList(Map map) throws Exception {
        int pageNum = 1;
        int pageSize = 10;
        if (!StringUtils.isEmpty(map.get("page"))) {
            pageNum = Integer.parseInt((String) map.get("page"));
        }
        if (!StringUtils.isEmpty(map.get("limit"))) {
            pageSize = Integer.parseInt((String) map.get("limit"));
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Admins> list = adminsMapper.selectAllByMap(map);
        PageInfo pageInfo = new PageInfo(list);
        return pageInfo;
    }
}

7.控制器

示例:controller > testController.java

注意:相关参数的注解

package com.zh.test.controller;

import com.zh.test.comm.BusinessException;
import com.zh.test.comm.CommonEnum;
import com.zh.test.comm.Response;
import com.zh.test.domain.Admins;
import com.zh.test.service.IAdminsService;
import io.swagger.annotations.ApiImplicitParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.WebRequest;
import java.beans.PropertyEditorSupport;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping(value = "/test")
public class testController {

    @Autowired
    private IAdminsService adminsService;
    private static final Logger logger = LoggerFactory.getLogger(testController.class);

    @RequestMapping(value = "/get")
    public String Get(){
        return "Hello world!";
    }

    /**
     * 获取分页数据
     */
    @ApiOperation(value = "获取分页数据")
    @PostMapping("/getData")
    public Response list(@RequestParam Map map) throws Exception {
        PageInfo pageInfo = adminsService.getList(map);
        return new Response().success(pageInfo.getList(), pageInfo.getTotal());
    }

    /**
     * 获取实体
     */
    @ApiOperation(value = "获取实体")
    @PostMapping("/getOne")
    public Response getOne(@ApiParam(value = "Guid") @RequestParam("Guid") String Guid) throws Exception {
        return new Response().success(adminsService.getModel(Guid));
    }

    /**
     * 保存
     */
    @ApiOperation(value = "保存")
    @PostMapping(value = "/add",produces = "application/json;charset=UTF-8")
    public Response Save(@RequestBody Admins record) throws Exception {
        Admins insertRecord = new Admins();
        BeanUtils.copyProperties(record, insertRecord);
        adminsService.add(insertRecord);
        return new Response().success();
    }

    /**
     * 修改
     */
    @ApiOperation(value = "修改")
    @PostMapping(value = "/edit",produces = "application/json;charset=UTF-8")
    public Response Edit(@RequestBody  Admins record) throws Exception {
        Admins updateRecord = new Admins();
        BeanUtils.copyProperties(record, updateRecord);
        adminsService.update(updateRecord);
        return new Response().success();
    }

    /**
     * 删除
     */
    @ApiOperation(value = "删除")
    @PostMapping("/delete")
    public Response remove(@ApiParam(value = "Guid") @RequestParam("Guid") String Guid) throws Exception {
        adminsService.delete(Guid);
        return new Response().success();
    }
}

8.数据访问层 mapperXml

示例:mapperXml > Admins.xml

resources 文件夹下创建包 mapperXml,application.yml中配置xml依赖

mybatis:
  mapper-locations: classpath:mapperXml/*.xml
<?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.zh.test.mapper.AdminsMapper">
    <resultMap id="BaseResultMap" type="com.zh.test.domain.Admins">
        <id column="Guid" property="guid" jdbcType="VARCHAR" />
        <result column="NickName" property="nickname" jdbcType="VARCHAR" />
        <result column="Name" property="name" jdbcType="VARCHAR" />
        <result column="Password" property="password" jdbcType="VARCHAR" />
        <result column="Remark" property="remark" jdbcType="VARCHAR" />
    </resultMap>

    <sql id="Base_Column_List">
        `Guid`,`NickName`,`Name`,`Password`,`Remark`
    </sql>
    <sql id="Base_Where">
        <if test="guid != null">(Guid like #{guid})and </if>
        <if test="nickname != null">(nickname like #{nickname})and </if>
        <if test="Name != null">(Name like #{Name})and </if>
        <if test="remark != null">(Remark like #{remark})and </if>
    </sql>

    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String">
        select
        <include refid="Base_Column_List"/>
        from admins
        where Guid = #{guid,jdbcType=VARCHAR}
    </select>

    <select id="getNextVal" resultType="java.lang.Long" useCache="false" flushCache="false">
        select SEQ_admins.nextval as id from dual
    </select>

    <select id="selectAllByMap" resultMap="BaseResultMap" parameterType="java.util.Map">
        select
        <include refid="Base_Column_List"/>
        from admins
        <trim prefix="WHERE" suffixOverrides="and|or">
            <include refid="Base_Where"/>
        </trim>
    </select>

    <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
        delete
        from  admins
        where Guid = #{guid,jdbcType=VARCHAR}
    </delete>

    <insert id="insert" parameterType="com.zh.test.domain.Admins" >
        insert into admins ( `Guid`,`NickName`,`Name`,`Password`,`Remark` )
        values (#{guid,jdbcType=VARCHAR},#{nickname,jdbcType=VARCHAR},#{name,jdbcType=VARCHAR},#{password,jdbcType=VARCHAR},#{remark,jdbcType=VARCHAR} )
    </insert>

    <insert id="insertSelective" parameterType="com.zh.test.domain.Admins" >
        insert into admins
        <trim prefix="(" suffix=")" suffixOverrides="," >
            <if test="guid != null" >`Guid`,</if>
            <if test="nickname != null" >`NickName`,</if>
            <if test="name != null" >`Name`,</if>
            <if test="password != null" >`Password`,</if>
            <if test="remark != null" >`Remark`,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
            <if test="guid != null" >#{guid,jdbcType=VARCHAR},</if>
            <if test="nickname != null" >#{nickname,jdbcType=VARCHAR},</if>
            <if test="name != null" >#{name,jdbcType=VARCHAR},</if>
            <if test="password != null" >#{password,jdbcType=VARCHAR},</if>
            <if test="remark != null" >#{remark,jdbcType=VARCHAR},</if>
        </trim>
    </insert>

    <update id="updateByPrimaryKey" parameterType="com.zh.test.domain.Admins" >
        update admins set
        `NickName` = #{nickname,jdbcType=VARCHAR},
        `Name` = #{name,jdbcType=VARCHAR},
        `Password` = #{password,jdbcType=VARCHAR},
        `Remark` = #{remark,jdbcType=VARCHAR}
        where Guid = #{guid,jdbcType=VARCHAR}
    </update>

    <update id="updateByPrimaryKeySelective" parameterType="com.zh.test.domain.Admins" >
        update admins
        <set >
            <if test="nickname != null" > `NickName` = #{nickname,jdbcType=VARCHAR},</if>
            <if test="name != null" > `Name` = #{name,jdbcType=VARCHAR},</if>
            <if test="password != null" > `Password` = #{password,jdbcType=VARCHAR},</if>
            <if test="remark != null" > `Remark` = #{remark,jdbcType=VARCHAR},</if>
        </set>
        where Guid = #{guid,jdbcType=VARCHAR}
    </update>
</mapper>

9.公共类 comm

示例:comm > Response.java 接口统一返回对象

package com.zh.test.comm;

/**
 * 自定义统一返回对象
 */
public class Response {
    private boolean IsError;
    private String ErrorMsg;
    private int Code;
    private Object Data;
    private long DataCount;

    public Response success(){
        this.success(1,1);
        return this;
    }
    public Response success(Object obj){
        this.success(obj,1);
        return this;
    }
    public Response success(Object obj,long count){
        this.setIsError(false);
        this.setCode(1);
        this.setData(obj);
        this.setDataCount(count);
        return this;
    }
    public Response error(String obj){
        error(0,obj);
        return this;
    }
    public Response error(int code,String obj){
        this.setCode(code);
        this.setIsError(true);
        this.setErrorMsg(obj);
        return this;
    }
    public long getDataCount() {
        return DataCount;
    }
    public void setDataCount(long dataCount) {
        DataCount = dataCount;
    }
    public boolean getIsError() {
        return IsError;
    }
    public void setIsError(boolean isError) {
         IsError=isError;
    }
    public int getCode() {
        return Code;
    }
    public void setCode(int code) {
        Code = code;
    }
    public Object getData() {
        return Data;
    }
    public void setData(Object data) {
        Data = data;
    }
    public void setError(boolean error) {
        IsError = error;
    }
    public String getErrorMsg() {
        return ErrorMsg;
    }
    public void setErrorMsg(String errorMsg) {
        ErrorMsg = errorMsg;
    }
}

10.Show Time

至此一个完整的数据库增删改查基础功能完成。里面涉及到的一些其他具体操作,将在后续相关文章中发布。以上代码皆为真实案例拷贝,如遇无法运行请检查mave及相关配置,或继续阅读下面注意事项及参考链接。

贴上完整的项目结构:

full

五、尽请期待

后续可能将会发布以下相关文章,尽请期待:

  • 全局异常捕获

  • 动态application配置

  • mybatismybatis相关用法

  • 路由权限控制器

  • 前后端整体发布流程

六、注意事项

  1. pom.xml 相关配置
        <!--第三方依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.4</version>
        </dependency>
        <!--引入swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>
  1. 对象参数无法传递

    注意相关注解,对象参数需要相应注解才能识别:@RequestBody

  1. 无法启动

    • 请检查数据库连接:必须要正确
    • 请检查端口占用情况
  1. 过滤数据库注解

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

七、参考链接

授人以鱼不如授人以渔

https://blog.csdn.net/u014453898/article/details/84659349

https://blog.csdn.net/lihua5419/article/details/81536629

https://www.cnblogs.com/telwanggs/p/9459685.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容