SpringBoot 入门必学篇(一)

前言

这篇文章主要介绍SpringBoot的必学内容

  • SpringBoot项目搭建
  • MyBatis 整合
  • 实现分页
  • 实现文件上传

一、搭建SpringBoot项目

搭建项目前需要配置Java环境,Java环境配置可以在网上都可以找到的,这里就不做太多介绍。使用的开发工具是IntelliJ IDEA集成环境开发工具,其自带创建SpringBoot项目模板,特别方便。

下面就来说下创建的步骤:
(1) 选择菜单File -> New -> Project,弹出New Project 面板,左侧栏选择Spring Initializr,右边选择Default。


(2) 点击Next按钮,进入Project Metadata面板,依次填写Group、Artifact(必须都是小写字母)、Type选择Maven Project,其它基本都是自动选择和配置好的。

(3) 再点击Next按钮,进入Spring包选择面版,选择Dependencies栏中的Web中的Web依赖包,这个包里面编写了自动配置Web项的逻辑。

(4) 继续点Next按钮,进入Finish页面面板,如图14所示,这里可以修改项目名称、项目保存路径以及模块名称等,也可以不做任何修改,使用默认配置,点击Finish按钮完成,SpringBoot项目就创建完成。

(5) 运行。此时直接点击Run运行会提示错误,需要修改HellospringbootApplication代码后再点击右上角绿色Run按钮运行。代码中用到了三个注解,注解@RestController相当于@ResponseBody@Controller两个注解合在一起的作用,只返回retrun的内容,不会指向到对应的页面,如jsp页面。注解@SpringBootApplication相当于@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan三个注解合在器的作用,目的是开启自动配置。注解@RequestMapping作用是用来地址映射,注解在类上则作用在类上,注解在方法则作用在方法上,如果两个都存在则会叠加。

@RestController
@SpringBootApplication
public class HellospringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(HellospringbootApplication.class, args);
    }
    @RequestMapping("/")
    public String test() {
        return "Hello SpringBoot";
    }
}

(6) 测试。运行成功后,在浏览器输入http://localhost:8080,浏览器上显示Hello SpringBoot,表示搭建SpringBoot项目成功。

二、整合MyBatis

MyBatis是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。简单的说MyBatis就是类似Hibernate的ORM框架,相比之下要轻便、灵活的多,更易保证DB访问的性能。

整合MyBatis分为这么几个步骤:

(1) 在pom.xml文件里集成添加所需要的依赖包。Maven如果不是设置自动导入,右下角会出现Import Changes和Enable Auto-Import, 前者是手动点击导入改变的包,后者是设置为自动导入。

<!-- myBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>

<!-- mySql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- 数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.0</version>
</dependency>

(2) 配置application.yml。在resources文件夹下创建application.yml文件,在里面配置其服务器配置信息、spring配置信息以及mybatis配置信息,配置信息代码如下:

server: 
  port: 8088

spring:
  datasource:
      username: root
      password: root
      url: jdbc:mysql://localhost:3306/soaic?useUnicode=true&characterEncoding=utf-8
      driver-class-name: com.mysql.jdbc.Driver 
      type: com.alibaba.druid.pool.DruidDataSource
  application:
    name: hellospringboot
  http:
      encoding:
        charset: UTF-8
        force: true
  jackson:
      default-property-inclusion: non_null

mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: com.soaic.hellospringboot.entity

服务器端口号设置为8088,配置spring数据库连接信息和连接池,指定myBatis映射在mapper包下并以Mapper.xml命名结尾和entity包的路径,jackson这里配置的是过滤返回为null的数据。
(3) 开发entity。在com.soaic.hellospringboot包下创建entity包,该包下存放所有数据实体类,接着创建MyUser实体类,定义电影数据属性,并对其做get和set封装,代码如下:

public class MyUser {
    
    private Integer id;
    private String userName;
    private String password;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

(4) 开发mapper,在com.soaic.hellospringboot包下创建mapper包,该包存放所有Mapper映射接口,以及在resources包下创建mapper包,该包存放所有定义myBatis与mySQL数据库关联操作的xml文件,通过该文件可以对数据库进行增删改查操作,并以其对应的Mapper接口返回相关数据给调用者,注意的是这文件名需要以Mapper.xml结尾并以前一个mapper包下一一对应,否则会映射不了。

HellospringbootApplication类上添加@MapperScan("com.soaic.hellospringboot.mapper")扫描指定包下的所有mapper。

@RestController
@SpringBootApplication
@MapperScan("com.soaic.hellospringboot.mapper")
public class HellospringbootApplication {

}

com.soaic.hellospringboot.mapper包下创建MyUserMapper.java,并编写代码如下:

public interface MyUserMapper {

    Integer insertUser(MyUser user);

    Integer batchInsertUser(List<MyUser> users);

    MyUser deleteUser(Integer id);

    MyUser updateUser(MyUser user);

    MyUser selectUser(Integer id);

    List<MyUser> selectAllUser();

    @Select("select * from user_t where username like CONCAT('%',#{0},'%')")
    @ResultMap("com.soaic.hellospringboot.mapper.MyUserMapper.userMap")
    List<MyUser> selectUserByName(String name);

}

resources/mapper包下创建MyUserMapper.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.soaic.hellospringboot.mapper.MyUserMapper">

    <resultMap id="userMap" type="com.soaic.hellospringboot.entity.MyUser">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="username" property="userName" jdbcType="VARCHAR" />
        <result column="password" property="password" jdbcType="VARCHAR" />
    </resultMap>

    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id" parameterType="com.soaic.hellospringboot.entity.MyUser">
        insert into user_t (username, password)
        values(#{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR})
    </insert>

    <insert id="batchInsertUser" useGeneratedKeys="true" keyProperty="id">
        insert into user_t (username, password) values
        <foreach item="item" collection="list" separator=",">
            (#{item.username}, #{item.password})
        </foreach>
    </insert>

    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user_t
        where id = #id
    </delete>

    <update id="updateUser" parameterType="com.soaic.hellospringboot.entity.MyUser">
        update user_t
        set username = #{userName, jdbcType=VARCHAR}, password = #{password, jdbcType=VARCHAR}
    </update>

    <select id="selectUser" parameterType="java.lang.Integer" resultMap="userMap">
        select * from user_t
        where id = #{id,jdbcType=INTEGER}
    </select>

    <select id="selectAllUser" resultMap="userMap">
        select * from user_t
    </select>

</mapper>

以上代码,主要实现了对user_t表的增删改查、批量添加以及用注解方式根据username模糊查询。要注意的是,id中不能有相同名字,接口中不能有相同方法名,否则会报错。
其它功能可以详细查看myBatis中文官方文档:http://www.mybatis.org/mybatis-3/zh/index.html

(5) 开发services。在com.soaic.hellospringboot包下创建services包,并创建MyUserServices.java文件。该包下存放调用Mapper接口的服务,供后面定义的controller提供使用。

@Service
public class MyUserServices {

    @Resource
    private MyUserMapper userMapper;

    public Integer insertUser(MyUser user) {
        return userMapper.insertUser(user);
    }

    public Integer insertUser(List<MyUser> users) {
        return userMapper.batchInsertUser(users);
    }

    public MyUser deleteUser(Integer id) {
        return userMapper.deleteUser(id);
    }

    public MyUser updateUser(MyUser user) {
        return userMapper.updateUser(user);
    }

    public MyUser selectUser(Integer id) {
        return userMapper.selectUser(id);
    }

    public List<MyUser> selectUser() {
        return userMapper.selectAllUser();
    }

    public List<MyUser> selectUserByName(String name) {
        return userMapper.selectUserByName(name);
    }

}

(6) 开发controller。在com.soaic.hellospringboot包下创建controller包,并创建MyUserController.java。该包下存放所有接口控制器,所有接口都在控制器中定义。

@RestController
@RequestMapping("/user")
public class MyUserController {

    @Autowired
    private MyUserServices myUserServices;

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String register(HttpServletRequest request) {
        try {
            String userName = request.getParameter("username");
            String password = request.getParameter("password");

            MyUser user = new MyUser();
            user.setUserName(userName);
            user.setPassword(password);
            return myUserServices.insertUser(user)+"";
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    @RequestMapping("/findAllUser")
    public List<MyUser> findAllUser() {
        return myUserServices.selectUser();
    }
}

以上代码实现了两个接口:
http://localhost:8088/user/register注册接口,请求方式为POST,代码中通过HttpServletRequest来获取请求参数,GET方式也可以通过它来获取。
http://localhost:8088/user/findAllUser获取所有用户接口,请求方式默认为GET。
其它接口实现大家可以自己试着实现以下,实现方法其实都差不多,这里就不做太多实现。

(7) 运行测试。运行直接点击右上角绿色小图标就可以运行项目了。测试/user/findAllUser接口可以在浏览器上直接测试,测试/user/register接口,由于该接口采用的请求方式是POST,所以就不能直接用浏览器测试了。这里推荐大家使用IDEA里自带的测试工具HTTP Client来测试。
打开方式:菜单栏 > tools > HTTP Client > Test RESTfull Web Service


可以看到左边可以添加头Headers,中间添加参数Parameters,右边可以添加文本、文件等,最后点击左上角绿色小图标就可以执行了,是不是特别方便。

三、接口分页实现

在进行接口开发中,分页查询是必不可少的功能,这里我们使用PageHelper分页插件来进行实现,使用它来进行分页特别简单方便。

(1) 在pom.xml中添加依赖库。查看maven中pagehelper的版本:https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter

<!-- 分页 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>

(2) 在application.yml中配置分页插件。

# 分页插件配置
pagehelper:
 helperDialect: mysql
 reasonable: true
 supportMethodsArguments: true
 params: count=countSql
 page-size-zero: false

(3) 添加PageModel,这里默认页码数pageNum为第一页,默认一页数量pageSize为10个。

public class PageModel {

    private int pageNum = 1;
    private int pageSize = 10;

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
}

(4) 添加PageBean继承PageInfo, 这里主要是为了自定义返回分页数据,注解@JsonIgnore作用是忽略掉该字段,注解JsonProperty作用是更换返回字段key。

public class PageBean<T> extends PageInfo<T> {
    public PageBean(List<T> list){
        super(list);
    }
    @JsonIgnore
    @Override
    public int getSize() {
        return super.getSize();
    }
    @JsonIgnore
    @Override
    public int getStartRow() {
        return super.getStartRow();
    }
    @JsonIgnore
    @Override
    public int getEndRow() {
        return super.getEndRow();
    }
    @JsonIgnore
    @Override
    public int getPrePage() {
        return super.getPrePage();
    }
    @JsonIgnore
    @Override
    public int getNextPage() {
        return super.getNextPage();
    }
    @JsonIgnore
    @Override
    public boolean isIsFirstPage() {
        return super.isIsFirstPage();
    }
    @JsonIgnore
    @Override
    public boolean isIsLastPage() {
        return super.isIsLastPage();
    }
    @JsonIgnore
    @Override
    public boolean isHasNextPage() {
        return super.isHasNextPage();
    }
    @JsonIgnore
    @Override
    public boolean isHasPreviousPage() {
        return super.isHasPreviousPage();
    }
    @JsonIgnore
    @Override
    public int getNavigatePages() {
        return super.getNavigatePages();
    }
    @JsonIgnore
    @Override
    public int[] getNavigatepageNums() {
        return super.getNavigatepageNums();
    }
    @JsonIgnore
    @Override
    public int getNavigateFirstPage() {
        return super.getNavigateFirstPage();
    }
    @JsonIgnore
    @Override
    public int getNavigateLastPage() {
        return super.getNavigateLastPage();
    }
    @JsonIgnore
    @Override
    public int getPages() {
        return super.getPages();
    }
    @JsonProperty("items")
    @Override
    public List<T> getList() {
        return super.getList();
    }
    @JsonProperty("items")
    @Override
    public void setList(List<T> list) {
        super.setList(list);
    }
}

(4) 添加ResponseResult,这里主要是为了返回数据时统一格式,msg是返回消息,code是返回状态码,data是返回的结果数据。

public class ResponseResult<T> {

    private String msg;
    private Integer code;
    private T data;

    public ResponseResult() {}
    
    public ResponseResult(Integer code, String msg, T data) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResponseResult{" +
                ", msg='" + msg + '\'' +
                ", code=" + code +
                ", data=" + data +
                '}';
    }
}

(5) 修改MyUserControllerfindAllUser方法。

    @RequestMapping("/findAllUser")
    public ResponseResult<PageBean> findAllUser(PageModel pageModel) {
        ResponseResult<PageBean> responseResult;
        try {
            PageHelper.startPage(pageModel.getPageNum(), pageModel.getPageSize());
            PageHelper.orderBy("id asc");
            List<MyUser> myUsers = myUserServices.selectUser();
            PageBean<MyUser> pageBean = new PageBean<>(myUsers);
            responseResult = new ResponseResult<>(200, "success", pageBean);
        } catch (Exception e) {
            e.printStackTrace();
            responseResult = new ResponseResult<>(501, "failure", null);
        }
        return responseResult;
    }

以上代码修改了几个地方,1)方法中添加了PageModel参数,目的是为了接收页码pageNum和页数量pageSize值。2)调用PageHelperstartPage方法,并把页码和页数量传进去,设置分页。3)再调用PageHelperorderBy方法设置排序可以设置降序desc和升序asc。4)实例一个PageBean对象并把myUsers对象传到构造方法中,这时实例化的pageBean其实就是分页好的数据。5)这里我们多做一步操作,再实例一个ResponseResult对象,传入codemsgpageBean对象,最后返回。这时接口拿到的数据就是统一json格式数据了。

调用接口http://localhost:8088/user/findAllUser?pageNum=1&pageSize=10,返回数据如下:

{
    "msg":"success",
    "code":200,
    "data":{
        "total":2,
        "pageNum":1,
        "pageSize":10,
        "items":[
            {
                "id":1,
                "userName":"soaic",
                "password":"123456"
            },
            {
                "id":2,
                "userName":"admin",
                "password":"123456"
            }
        ]
    }
}

四、实现文件上传接口

文件上传也是很api必不可少的功能了,有单个文件上传,也有多个文件和文本一起请求,步骤如下:
(1) 在pom.xml中添加依赖库。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.3</version>
</dependency>

(2) 在contoller包中添加UploadFileController

@RestController
@RequestMapping("/upload")
public class UploadFileController {

    @RequestMapping(value = "/file", method = RequestMethod.POST)
    public ResponseResult<String> uploadFile(@RequestParam("file") MultipartFile multipartFile) {
        try {
            System.out.println("multipartFile"+multipartFile);
            String filePath = "/Users/soaic/"+multipartFile.getOriginalFilename();
            FileUtils.writeByteArrayToFile(new File(filePath), multipartFile.getBytes());
            return new ResponseResult<>(200, "upload success" , filePath);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult<>(501, "upload failure", e.getMessage());
        }
    }

    @RequestMapping(value = "/batchFile", method = RequestMethod.POST)
    public ResponseResult<String> uploadFiles(HttpServletRequest request) {
        try {
            String content = request.getParameter("content");
            System.out.println("content="+content);
            //获取上传的文件数组
            List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
            for (MultipartFile file:files) {
                FileUtils.writeByteArrayToFile(new File("/Users/soaic/"+file.getOriginalFilename()), file.getBytes());
            }
            return new ResponseResult<>(200, "upload success",null);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult<>(501, "upload failure", e.getMessage());
        }
    }
}

以上代码实现了两个接口:一个是单文件上传,另一个是多文件上传并携带参数。单文件上传是通过multipartFile对象来接收文件,并通过FileUtils工具类调用writeByteArrayToFile方法保存文件。多文件上传是通过HttpServletRequest对象调用getFiles方法来获取MultipartFile集合。
(3) 测试。文件上传测试,这里推荐一个新的测试工具Advanced REST Client,用着还是挺不错的,大家可以试试。下载地址:https://install.advancedrestclient.com/install

以上代码都已放在github上,地址:https://github.com/soaic/HelloSpringBoot

这篇文章主要介绍了SpringBoot的项目搭建、整合MyBatis、分页接口实现和文件上传接口。下一篇文章会介绍配置Https、配置拦截器、页面转向、资源指向、事务处理等等,希望大家多多关注。

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

推荐阅读更多精彩内容