1. SpringBoot框架

SpringBoot框架可以简单的理解为是一个“增强版的SpringMVC框架,极大程度的简化了各种配置,默认就已经集成了绝大部分常用的依赖”。

2. 创建SpringBoot项目的方式

创建SpringBoot的方式主要有3种:

  • 基于SpringBoot的父级项目来创建子级项目;
  • 使用开发工具的创建向导进行创建,如果使用的是Eclipse,需要安装Spring Tools Suite插件,如果使用的是Intellijia IDEA则不需要安装任何插件,可以直接创建;
  • 通过https://start.spring.io网站创建项目,然后在开发工具中导入项目。

3. 创建SpringBoot项目

打开https://start.spring.io网站,确定以下参数:

  • 【Project】:Maven Project
  • 【Language】:Java
  • 【SpringBoot】:2.1.14
  • 【Group】:cn.tedu
  • 【Artifact】:sample
  • 【Name】:sample
  • 【Package Name】:cn.tedu.sample
  • 【Packaging】:war
  • 【Java】:8
  • 【Dependencies】:无

确定无误后,点击页面中的 Generate 按钮,将会开始自动下载,将得到sample.zip压缩包。

解压sample.zip将得到sample文件夹,这个文件夹就是创建好的SpringBoot项目,推荐将该文件放到Workspace中,便于统一管理。

在Eclipse中,通过Import > Existing Maven Projects导入项目,如果是第1次使用SpringBoot项目,可能本地仓库中没有相关的jar包,所以,会下载大量的依赖的jar包,在这个过程中,必须保证网络畅通,能够顺利的连接到Maven服务器,如果没有开始自动下载,可以对项目点击右键,选择Maven > Update Project以更新项目,甚至强制更新项目。

注意:根据开发工具安装插件的不同,项目结构中可能有一些额外的分支,或图标不同,并不影响正常开发和运行。

注意:如果使用较低的Eclipse,可能内置的是较低版本的Maven环境,在创建完SpringBoot项目后,pom.xml文件可能报错,但是,可以无视,并不影响开发和运行。

4. 启动SpringBoot项目

在生成好的项目中,默认,在src/main/java下就存在cn.tedu.sample包,这个包的名字是由创建项目时填写的GroupArtifact决定的,同时,这是当前SpringBoot项目默认已经配置的组件扫描的包,所以,后续自行创建的组件类必须放在这个包或其子孙包中!

【小结】默认就存在的包,不能随便修改名称,且推荐将所有类都放在这个包或其子孙包中。

cn.tedu.sample包下,默认就存在SampleApplication类,这个类的名称是根据创建项目时填写的Artifact决定的,这个类中有main()方法,运行该方法,就会启动整个项目!所以,SampleApplication也称之为当前项目的启动类

SpringBoot项目是内置Tomcat的,当启动项目时,就会将项目编译、打包,并部署到内置的Tomcat中,再启动这个Tomcat!

由于内置的Tomcat默认也是占用8080端口的,所以,在启动项目之前,必须将已经运行的Tomcat停止,也不可以反复启动项目!

另外,在src/test/java下也有cn.tedu.sample包,且包中已经有SampleApplicationTests测试类,类中有contextLoads()方法,该方法的方法体中并没有任何代码,通过单元测试执行该方法应该能通过测试。

在SpringBoot中执行单元测试时,会加载项目的所有环境(读取配置、加载Spring容器等),要求所有的单元测试类必须放在cn.tedu.sample包或其子孙包中,并且,测试类的声明之前必须添加和SampleApplicationTests类相同的注解!

使用SpringBoot 2.1.x系列版本时,单元测试类之前需要添加2个注解,使用SpringBoot 2.2.x系列版本时,只需要添加1个注解!无论使用哪个版本,参考默认即存在的单元测试类来配置注解即可!

5. 在项目中添加静态资源

静态资源:网页文件(.html文件)、图片文件、.css文件、.js文件等,放在服务器端,可以被客户端直接请求的文件。

在SpringBoot项目中,在src/main/resources下,默认就存在static文件夹,是专门用于存放静态资源的文件夹!

其实,静态资源也可以放到项目的webapp文件夹下,SpringBoot推荐将静态资源放在static下。

可以在static下创建index.html文件,文件内容可以随意设计。

然后,启动项目,打开浏览器,输入网址http://localhost:8080即可看到自行设计的网页。

在启动项目时,控制台中有如下日志:

Tomcat started on port(s): 8080 (http) with context path ''

可以看到,内部的Tomcat在部署当前项目时,设置的context path值是空字符串,所以,在访问项目的URL中,不需要添加项目名称!

由于此次尝试访问的资源是index.html,是默认的资源名,所以,在URL中也不必显式的添加资源名!

在SpringBoot项目中,在src/main/resources下,默认就存在application.properties文件,这个文件就是项目的配置文件。

可以在配置文件中修改Tomcat占用的端口,需要添加以下配置:

server.port=80

由于80端口是HTTP协议的默认端口,当修改为80端口后,重新启动项目(先停止,再启动),在浏览器通过http://localhost即可访问到此前的网页!

注意:如果使用的是Linux系列操作系统,或Mac OS等Unix衍生操作系统,这些操作系统对端口号的使用管理相对严格,默认情况下,不允许将端口号修改为80,除非另行在操作系统中进行设置,开放80端口的修改权限。

6. 使用控制器接收客户端的请求

src/main/javacn.tedu.sample包下创建子级的controller包,并在这个子包中创建HelloController控制器类,设计请求并处理:

package cn.tedu.sample.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
	
	@RequestMapping("hello")
    @ResponseBody
	public String hello() {
		return "SpringBoot真好用!!!";
	}

}

重启项目,在浏览器通过http://localhost/hello即可访问到以上控制器的方法。

在SpringBoot项目中,默认已经将DispatcherServlet映射的路径设置为/*,也就是所有资源(当然,staticwebapp这些文件夹已经被设置静态资源文件夹,所以,允许直接访问),所以,在使用@RequestMapping注解配置请求路径时,不需要使用.do或其它后缀,当然,添加了后缀也可以,只要访问时保持一致即可。

在SpringBoot项目中,已经将所以可以设置的编码全部设置成了UTF-8,所以,SpringBoot项目默认是完全支持中文的!

当确定服务器端的响应方式是“响应正文”时,在控制器类之前原本添加的@Controller可以替换为@RestController,该注解相当于@Controller + @ResponseBody,当类的声明之前使用的是@RestController时,该类中的每一个方法都不需要再添加@ResponseBody即可“响应正文”。

7. 连接数据库

SpringBoot项目默认并没有集成数据库和数据库编程的框架所依赖的jar包,需要在创建项目时就勾选相关的依赖,或在创建项目之后再在pom.xml中添加相关的代码:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>

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

有许多依赖的使用中,SpringBoot框架都会自动的选取较高版本的依赖,并不需要在pom.xml中指定所使用的版本,例如以上mysql-connector-java就没有指定版本号!当然,如果一定要使用某个特定的版本,自行添加<version>节点进行配置也是可以的,则会使用所指定的版本!

一旦添加以上依赖后,当启动项目时,就会自动加载连接数据库的配置信息,如果尚且没有配置,则会启动失败!所以,必须在application.properties中添加配置:

spring.datasource.url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root

当添加以上配置后,再次启动SpringBoot就不会报错了,即使以上配置信息是错误的,也不会报错!因为启动项目时只会“加载信息”,并不会“直接数据库”,所以,以上配置中,只要基本格式是正确的即可!

可以在src/test/java下编写单元测试,通过单元测试尝试连接数据库,以检查以上配置信息是否正确!则在cn.tedu.sample包下的SampleApplicationTests测试类中,添加以下代码进行测试:

@Autowired
public DataSource dataSource;

@Test
public void getConnection() throws SQLException {
    Connection conn = dataSource.getConnection();
    System.err.println(conn); // 使用err只是为了输出红色的日志,便于观察。
}

在使用SpringBoot框架编程时,凡在传统的SSM系列框架中通过getBean()可以获取的对象,都可以通过添加自动装配的注解来装配值!

8. 使用MyBatis实现数据库编程

【目标】向用户数据表中插入用户数据。

cn.tedu.sample包下创建entity子包,专门用于存放实体类,并在这个包中创建User类:

public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String phone;
    private String email;
}

cn.tedu.sample包下创建mapper子包,专门用于存放使用MyBatis编程时创建的接口,并在这个包中创建UserMapper接口,并在接口中添加抽象方法:

Integer addnew(User user);

然后,需要在启动类SampleApplication的声明之前补充@MapperScan注解,以指定接口的位置!

src/main/resources下创建mappers文件夹,专门用于存放配置SQL语句的XML文件,并在这个文件夹,粘贴得到UserMapper.xml,并在其中配置以上抽象方法映射的SQL语句:

<?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="cn.tedu.sample.mapper.UserMapper">

	<insert id="addnew">
		INSERT INTO t_user (
			username, password, age, phone, email
		) VALUES (
			#{username}, #{password}, #{age}, #{phone}, #{email}
		)
	</insert>

</mapper>

然后,还需要在application.properties中添加配置,以指定XML文件的位置:

mybatis.mapper-locations=classpath:mappers/*.xml

全部完成后,可以通过单元测试来检验以上代码是否可以正确执行,可以在src/test/java下的cn.tedu.sample包下创建子级的mapper包,并在这个包下创建UserMapperTests测试类,并参考原有的SampleApplicationTests类添加注解:

package cn.tedu.sample.mapper;

import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTests {

}

然后,在测试类中编写并执行单元测试方法:

package cn.tedu.sample.mapper;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import cn.tedu.sample.entity.User;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTests {
	
	@Autowired
	public UserMapper userMapper;
	
	@Test
	public void addnew() {
		User user = new User();
		user.setUsername("SpringBoot");
		user.setPassword("1234");
		user.setAge(28);
		user.setPhone("13900139008");
		user.setEmail("springboot@baidu.com");
		Integer rows = userMapper.addnew(user);
		System.err.println("rows=" + rows);
	}

}

【目标】根据用户名查询用户数据

需要执行的SQL语句大致是:

select * from t_user where username=?

则在UserMapper接口中添加抽象方法:

User findByUsername(String username);

并在UserMapper.xml中配置映射:

<select id="findByUsername" resultType="cn.tedu.sample.entity.User">
	SELECT * FROM t_user WHERE username=#{username}
</select>

完成后,在UserMapperTests中编写并执行单元测试:

@Test
public void findByUsername() {
    String username = "test";
    User user = userMapper.findByUsername(username);
    System.err.println(user);
}

9. 完成用户注册功能

当用户尝试注册时,会先在页面中填写注册信息,然后点击按钮提交请求!请求会被服务器端的控制器所接收,但是,控制器并不负责处理增删改查,所以,会将数据交给UserMapper来执行!

接下来,需要开发控制器的功能,先在cn.tedu.sample下创建util子包,并在这个包中创建通常的响应JSON结果的类型:

public class JsonResult<T> {
    private Integer state;
    private String message;
    private T data;
}

cn.tedu.sample.controller包中创建UserController控制器类,在类的声明之前添加@RestController@RequestMapping("user")注解,并声明持久层对象:

@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    private UserMapper userMapper;
}

然后,在类中添加处理“注册”请求的方法:

// http://localhost/user/reg?username=jsd2020&password=5678&age=19&phone=13700137777&email=jsd@baidu.com
@RequestMapping("reg")
public JsonResult<Void> reg(User user) {
    // 准备返回值对象
    JsonResult<Void> jsonResult = new JsonResult<Void>();
    // 根据参数user中的username查询数据库
    User result = userMapper.findByUsername(user.getUsername());
    // 判断查询结果是否为null
    if (result == null) {
        // 是:没有找到匹配的数据,则用户名没有被占用,允许注册,则执行注册,并返回注册成功
        userMapper.addnew(user);
        jsonResult.setState(1);
    } else {
        // 否:找到了匹配的数据,则用户名已经被占用,不允许注册,则返回注册失败
        jsonResult.setState(2);
        jsonResult.setMessage("注册失败!尝试注册的用户名已经被占用!");
    }
    // 返回
    return jsonResult;
}

完成后,重新启动项目,并打开浏览器,输入网址进行测试。

最后,再完成页面部分,先在static下创建注册页面,在页面中,通过ajax向服务器提交异步请求,并处理返回的结果: