- iOS Developer的全栈之路 - 运行SpringBoo
- iOS Developer的全栈之路 - cookie
- iOS Developer的全栈之路 - log
- iOS Developer的全栈之路 - Keycloak(1)
- iOS Developer的全栈之路 - Keycloak(4)
- iOS Developer的全栈之路 - Keycloak(9)
- iOS Developer的全栈之路 - Keycloak(3)
- iOS Developer的全栈之路 - Keycloak(10
- iOS Developer的全栈之路 - Keycloak(2)
- iOS Developer的全栈之路 - Keycloak(8)
在这一章里,我们基于第一章中的项目,让SpringBoot跑起来。
添加依赖
既然这是一个SpringBoot的项目,首先需要安装SpringBoot的依赖。在根项目的pom.xml文件中,添加配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath />
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.iossocket</groupId>
<artifactId>foodie-dev</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>foodie-dev-common</module>
<module>foodie-dev-pojo</module>
<module>foodie-dev-mapper</module>
<module>foodie-dev-service</module>
<module>foodie-dev-api</module>
</modules>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
- <properties>下添加了Encoding的方式,以及java的版本
- <parent>声明这个项目是基于springboot的,并指明了SpringBoot的版本
- <dependencies>声明了项目的基础依赖
3.1 spring-boot-starter-web web依赖
3.2 spring-boot-configuration-processor 提供对于其他配置文件的解析能力,默认情况下只支持yml文件,添加后可以支持xml等。
在这些依赖中都没有声明版本号,这些依赖的版本号都由<parent>标签下的spring-boot-starter-parent进行统一管理。如何查看这些被管理的版本号呢?进入org.springframework.boot的定义,再进入spring-boot-dependencies的定义即可查阅。
入口main
在api的module下创建两个类Application和HelloController,分别位于package:com.xxxx和com.xxxx.controller下
Application.java,main函数作为App的启动入口
package com.iossocket;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
HelloController.java,添加一个测试的url,路由为/hello
package com.iossocket.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello world";
}
}
mvn install后即可运行main函数,又有SpringBoot会默认内嵌一个Tomcat服务器,所有运行后可以直接通过浏览器打开localhost:8080/hello
查看运行效果。
SpringBoot通过注解摆脱了繁琐的配置,这里有几个基础的注解@SpringBootApplication
,@RestController
,@GetMapping("/hello")
,它们的作用是什么呢?建议动手撸一个简易版的SpringBoot,这里有一个课程 手写SpringMVC,剑指优秀开源框架灵魂,这里在附上我的项目我的项目代码仅供参考。
连接数据库
这里使用了mybatis作为orm框架,现在根项目的pom文件中添加mybatis以及MySQL的依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
...
<dependencies>
...
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
</dependencies>
</project>
关于mybatis-generator的使用方式可参考这里连接,并将生成好的
Users
,UsersMapper
,MyMapper
,UsersMapper.xml
拷贝至项目的相应目录。
- 首先先来看一下MyMapper所继承的父类,如
interface MyMapper<T> extends Mapper<T>,MySqlMapper<T>
这里有两个父类,Mapper<T>与MySqlMapper<T>,我们可以打开MySqlMapper<T>看一下:
interface MySqlMapper<T> extends InsertListMapper<T>,InsertUseGeneratedKeysMapper<T>{}
这里面又继承了了两个mapper,从类名上可以看得出来,是用于操作数据库的,这两个类里又分别包含了如下方法,简单归类一下:
insertList(list):数据批量插入,主键须自增
insertUseGeneratedKeys(record):插入表数据,主键须自增
很明显,在传统JavaWeb开发,这两个方法使用是没有问题的,但是我们的数据库表主键设计肯定是全局唯一的,所以不可能使用自增长id(如何设计全局唯一分布式主键,在后续章节里有具体的讲解),所以这两个方法在我们开发过程中是不会使用的,这一点需要注意噢~!
- 随后再来看一下Mapper<T>中所继承的父类,如下:
interface Mapper<T> extends BaseMapper<T>,ExampleMapper<T>,RowBoundsMapper<T>,
分别来看一下各个父类中的方法有些啥?
BaseMapper<T>
类 | 方法 | 说明 |
---|---|---|
单元格 | 单元格 | 单元格 |
BaseSelectMapper | T selectOne(T record) | 根据实体类中的属性查询表数据,返回单个实体 |
List select(T record) | 根据实体类中的属性查询表数据,返回符合条件的list | |
List selectAll() | 返回该表所有记录 | |
int selectCount(T record) | 根据条件查询记录数 | |
T selectByPrimaryKey(Object key) | 根据主键查询单挑记录 | |
boolean existsWithPrimaryKey(Object key) | 查询主键是否存在,返回true或false | |
BaseInsertMapper | int insert(T record) | 插入一条记录,属性为空也会保存 |
int insertSelective(T record) | 插入一条记录,属性为空不保存,会使用默认值 | |
BaseUpdateMapper | int updateByPrimaryKey(T record) | 根据实体类更新数据库,属性有null会覆盖原记录 |
int updateByPrimaryKeySelective(T record) | 根据实体类更新数据库,属性有null改属性会忽略 | |
BaseDeleteMapper | int delete(T record) | 根据实体类中属性多条件删除记录 |
int deleteByPrimaryKey(Object key) | 根据主键删除记录 |
ExampleMapper<T>
,Example类是用于提供给用户实现自定义条件的,也就是where条件,主要方法见如下表格:
类 | 方法 | 操作 |
---|---|---|
SelectByExampleMapper | List selectByExample(Object example) | 根据条件查询记录list |
SelectOneByExampleMapper | T selectOneByExample(Object example) | 根据条件查询单条记录 |
SelectCountByExampleMapper | int selectCountByExample(Object example) | 根据条件查询记录数 |
DeleteByExampleMapper | int deleteByExample(Object example) | 根据条件删除记录 |
UpdateByExampleMapper | int updateByExample(T record, @Param(“example”) Object example); | 根据条件更新数据,null会覆盖原数据 |
UpdateByExampleSelectiveMapper | int updateByExampleSelective(T record, Object example); | 根据条件更新数据,null会忽略 |
RowBoundsMapper<T>
,这个是用于做分页的,我们在后续阶段中会使用page-helper这个组件来替代这个分页实现。
小结
通用mapper所提供的CRUD方法对单表操作,大大提高开发效率,当然复杂的多表操作还是需要在mapper.xml中自己去编写sql代码实现。
小试牛刀
我们来让SpringBoot连接上数据库跑起来,首先我们先创建数据库及users表,创建数据库的方式,我们采用Navicat,连接上本地数据库,新建数据库foodie-shop-dev
,之后在左侧导航栏双击数据库,选中当前新建的数据库。
在顶级菜单中新建New Query
,写一个创建表的SQL,并执行。
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` varchar(64) NOT NULL COMMENT '主键id 用户id',
`username` varchar(32) NOT NULL COMMENT '用户名 用户名',
`password` varchar(64) NOT NULL COMMENT '密码 密码',
`nick_name` varchar(32) DEFAULT NULL COMMENT '昵称 昵称',
`real_name` varchar(128) DEFAULT NULL COMMENT '真实姓名',
`avatar` varchar(1024) NOT NULL COMMENT '头像',
`mobile` varchar(32) DEFAULT NULL COMMENT '手机号 手机号',
`email` varchar(32) DEFAULT NULL COMMENT '邮箱地址 邮箱地址',
`gender` int(11) DEFAULT NULL COMMENT '性别 性别 1:男 0:女 2:保密',
`birthday` date DEFAULT NULL COMMENT '生日 生日',
`created_time` datetime NOT NULL COMMENT '创建时间 创建时间',
`updated_time` datetime NOT NULL COMMENT '更新时间 更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
接下来为该表添加一条数据,执行
INSERT INTO `users` VALUES ('1908017YR51G1XWH', 'iossocket', 'Qpf0SxOVUjUkWySXOZ16kw==', 'imooc', NULL, 'http://122.152.205.72:88/group1/M00/00/05/CpoxxFw_8_qAIlFXAAAcIhVPdSg994.png', NULL, NULL, 2, '1900-01-01', '2019-08-14 23:44:30', '2019-08-14 23:44:30');
使用mybatis-generator,生成相应的entity, mapper以及配置文件,拷贝至相应目录,别忘了拷贝MyMapper哟。
之后就可以编写相应Service层的代码了:
package com.iossocket.service;
import com.iossocket.bo.LoginRequest;
import com.iossocket.bo.RegisterRequest;
import com.iossocket.pojo.Users;
public interface PassportService {
Boolean isUserExisting(String username);
}
package com.iossocket.service.impl;
import com.iossocket.mapper.UsersMapper;
import com.iossocket.pojo.Users;
import com.iossocket.service.PassportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
@Service
public class PassportServiceImpl implements PassportService {
@Autowired
private UsersMapper mapper;
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public Boolean isUserExisting(String username) {
Example userExample = new Example(Users.class);
Example.Criteria criteria = userExample.createCriteria();
criteria.andEqualTo("username", username);
Users users = mapper.selectOneByExample(userExample);
return !(users == null);
}
我们这里先写一个最简单的查看用户名是否可用的方法。有了service的支持,可用开始构建第一个endpoint啦,在controller层创建一个PassportController:
@RestController
@RequestMapping("/user")
@Slf4j
public class PassportController {
@Autowired
private PassportService passportService;
@GetMapping("/isUserExisting")
public JSONResult isUserExisting(@RequestParam(defaultValue = "") String username) {
if (StringUtils.isBlank(username)) {
return JSONResult.error("username can not be empty");
}
Boolean isExisting = passportService.isUserExisting(username);
return JSONResult.success(isExisting);
}
}
这里涉及到几个工具类,可用查阅源码。
运行项目,便通过postman查看结果了。
网友评论