首先,本文适合已学习过JavaSE但急于用Java编写一个后端项目的同学,还没学过的同学出门菜鸟教程或者b站黑马程序员,尚硅谷也可。(三者任选其一即可)
其次,既然你已经学过了java语言,那么你大概率也接触了python语言,不难发现,相较于java的后端学习成本而言,python其实上手更容易,只需要一百行不到就可以实现绝大部分数据简单的增删改查,可以说路上抓一个人教他两个小时估计也能学会的程度。
那为什么我们还要选择Java,或者说为什么我们还要选择Spring框架呢?
以下简单列举Spring的优点:
规范性强。
mapper、service、controller等的开发规范,使得我们的开发思路更加清晰,在处理负责的操作,以及未来的对于更高水平的开发中,Java开发反而更加便捷。
spring生态环境十分诱惑,给我们提供了格式各类的服务,帮助我们解决无数的烦恼
java与数据库其实联系更加紧密,对于数据库优化上也提供了很多思路
…
但同样的,Java如今已经不再无敌,NodeJs、Go、kontlin…的异军突起,Java的地位也已不再稳固,不过用spring框架作为通往未来的桥梁其实也不乏是一种手段。
废话不多说,我们开始进入正题。
IDEA(推荐2020.3版本及其以上)、MYSQL环境、JDK 8环境、maven、流畅的网络(steam++跑一跑)、善于思考的大脑、细心的双眼以及会百度谷歌的双手(上述工具缺一不可)
OK我们现在正式开始
点击File->New->Project->Spring Initializr
稍等一会可能要
Group:指项目公司或者组织
Artifact:我们本次项目的名字(我们用library为例)
JavaVersion选择8
其他的会自己翻译就行
下一个界面选择
lombok、spring web、mysql Driver(在Dependencies上搜一搜就行)
Next&finsh
在scr.main.java.com.example.library目录下新建四个文件夹:
controller
控制层,用于接收前端传来的数据,经过处理后传入前端
entity
用于存放实体类,与数据库中的属性值基本保持一致。
mapper
持久层,数据库持久化操作,方法直接针对数据库
在很多地方也写作DAO层,原理相同。本文使用mybatis实现与mysql关联
service
业务逻辑层,对数据进行处理
在scr.main.resource下新建com->example->library->mapper目录
测试运行项目:运行LibraryApplication
正常情况下可以运行
在这里插入图片描述
我们的配置文件主要使用application.properties的格式,还有另一种形式为applicaiton.yml,两种形式实际上都可以,yml对于格式的规范性要求更高(比如说冒号后一定要加上space空格等)。
一台服务器的端口不能存在冲突,因此我们第一步可以从修改端口着手
在application.properties中添加:
server.port=1213
重启项目,端口已改变
2022-06-10 10:28:57.784 INFO 11068 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 1213 (http)
依赖是Maven中重要的部分,可以粗浅的理解成在python中导入一些实用的包。
依赖主要添加在maven的pom.xml中的:标签中
...
通常依赖的结构为:
<dependency>
<groupId>groupId>
<artifactId>artifactId>
<version>version>
dependency>
在controller目录新建BookController文件:
编写一个HelloSpringboot方法,返回前端一个String字符串
package com.example.library.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/Book")
public class BookController {
@GetMapping("/Hello")
public String HelloSpringboot(){
return "HelloSpirngboot";
}
}
@RestController是@Controller和@ResponseBody两个注解的结合体(所谓结合体即两个注解同时添加与只添加结合后的注解效果相同)
作用:实例化当前对象为一个控制器对象,并将类上所有方法的返回值转为json,响应给服务器
@RequestMapping
再次运行LibraryApplication:
在浏览器中打开:
http://localhost:1213/Book/Hello
输出字符: HelloSpirngboot 成功,如图
localhost:本地服务器
1213:端口号
Book/Hello:@RequestMapping获取而得
本次我们主要是使用MySQL数据库,一是使用广泛,二是我比较熟悉
再在表中新建一个table: book
CREATE TABLE `book` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) DEFAULT NULL,
`type` varchar(128) DEFAULT NULL,
`author` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf
ps:在实际开发中,往往会有复杂的逻辑,因此后期还需要不断的对table添加参数
mybatis: 基于Java的持久层框架 , 它支持定制化 SQL、存储过程以及高级映射。
在pom.xml
...
添加
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.0version>
dependency>
在application.properties中添加:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=010213
mybatis.type-aliases-package=com.gao.security.bean
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
不同的database要修改:
spring.datasource.url:将localhost:3306/library的library改成你想使用的database
spring.datasource.username=root #用户名
spring.datasource.password=010213 #密码
修改成你的数据库的用户名以及密码即可
修改好后我们就基本已经连接上了数据库
package com.example.library.entity;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String name;
private String type;
private String author;
}
@Data是lombok上的注解,包含了我们常用的getter、setter、toString、有参构造、无参构造等。
值得一提的是,虽然lombok让我们的代码看起来更加简介, 但很多公司都已经禁止员工使用,具体原因不在此展开讨论。
Java开发中,强制要求: 基本数据类型 都要使用 包装类 (比如用Integer而不是int,Boolean而不是boolean),对于异常处理和数据处理都有很大的帮助。
用于承载我们要用的sql语句:
以下我们用book的增删改查为例:
在com.example.library.mapper下:
package com.example.library.mapper;
import com.example.library.entity.Book;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface BookMapper {
List<Book> listBook();//查询所有的
void deleteById(Integer id); //通过书籍id删除
void Insert(Book book);//插入书籍
void updateById(Book book);//更新书籍
}
@Mapper告诉容器这个是一个mapper,让大家都能找到
在src/main/resources/com/example/library/mapper下添加BookMapper.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.library.mapper.BookMapper">
mapper>
添加resultMap标签BookResult
绑定Book实体类,便于增删改查
<resultMap type="com.example.demo.entity.Book" id="BookResult">
<id property="id" column="id" />
<result property="name" column="name"/>
resultMap>
listBook查询:
<select id="listBook" resultMap="BookResult">
select * from book;
select>
resultMap绑定BookResult,即返回的对象
insert新增:
<insert id="insert" parameterType="com.example.library.entity.Book" useGeneratedKeys="true" keyProperty="id">
insert into book(
<if test="name != null and name != ''">name,if>
<if test="type != null and type != ''">type,if>
<if test="author != null and author != ''">authorif>
)values(
<if test="name != null and name != ''">#{name},if>
<if test="type != null and type != ''">#{type},if>
<if test="author != null and author != ''">#{author}if>
)
insert>
delete删除
<delete id="deleteById" parameterType="int">
DELETE FROM book
WHERE id=#{id}
delete>
不做过多解释
update更新
<update id="updateById" parameterType="com.example.library.entity.Book">
update book
<set>
<if test="name != null and name != ''">name=#{name},if>
<if test="type != null and type != ''">type=#{type},if>
<if test="author != null and author != ''">author=#{author},if>
set>
where id = #{id}
update>
完整代码:
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.library.mapper.BookMapper">
<resultMap type="com.example.library.entity.Book" id="BookResult">
<id property="id" column="id" />
<result property="name" column="name"/>
resultMap>
<select id="listBook" resultMap="BookResult">
select * from book;
select>
<insert id="insert" parameterType="com.example.library.entity.Book" useGeneratedKeys="true" keyProperty="id">
insert into book(
<if test="name != null and name != ''">name,if>
<if test="name != null and name != ''">type,if>
<if test="name != null and name != '">authorif>
)values(
<if test="name != null and name != ''">#{name},if>
<if test="name != null and name != ''">#{type},if>
<if test="name != null and name != ''">#{author}if>
)
insert>
<delete id="deleteById" parameterType="int">
DELETE FROM book
WHERE id=#{id}
delete>
<update id="updateById" parameterType="com.example.library.entity.Book">
update book
<set>
<if test="name != null and name != ''">name=#{name},if>
<if test="type != null and type != ''">type=#{type},if>
<if test="author != null and author != ''">author=#{author},if>
set>
where id = #{id}
update>
mapper>
通常service层
规范的写法是先写BookService作为一个interface,再用BookServiceImpl作为实现类来实现BookService
不过很多框架下也有直接使用BookService作为实现类的例子,因此我们在这里节省时间就将Service作为实现类处理了
在com.example.library.service目录下新建BookService
先上代码:
package com.example.library.service;
import com.example.library.entity.Book;
import com.example.library.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookService {
@Autowired
private BookMapper bookMapper;
public List<Book> ListAll(){
return bookMapper.listBook();
}
public void deleteById(Integer id){
bookMapper.deleteById(id);
}
public void insert(Book book){
bookMapper.insert(book);
}
public void updateById(Book book){
bookMapper.updateById(book);
}
}
@Service注解,如@Controller和@Mapper一样,是告诉容器这是一个Service类,调用时便于查找。
@Autowired
private BookMapper bookMapper;
@Autowired 自动装配,在容器里可以找到,在这里便可以找出来了
@Mapper这个注解已经帮助我们将BookMapper的方法实现,在这里了直接用上便可。
controller层,本质上是将数据传输到service层中,一些异常处理按理说应该是放在service中处理,然后返回给controller层是否成功的信息。但由于我们处于起步阶段,可以直接粗暴的用异常处理来代替错误信息返回。如下是我们的代码
相信聪明的你已经能够轻易的看懂了,至于@GetMapping(查)、@PostMapping(增)、@DeleteMapping(删)、@PutMapping(改)的区别,具体解释在深入学习后自会了解
package com.example.library.controller;
import com.example.library.entity.Book;
import com.example.library.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ResponseBody
@Controller
@RequestMapping("/Book")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping("/Hello")
public String HelloSpringboot(){
return "HelloSpirngboot";
}
@GetMapping("listAll")
public List<Book> listAll(){
return bookService.ListAll();
}
@PostMapping("/insert")
public String insertBook(Book book){
try {
bookService.insert(book);
return "插入成功";
}catch (Exception e){
e.printStackTrace();
return "插入失败";
}
}
@PutMapping("/update")
public String update(Book book){
try {
bookService.updateById(book);
return "更新成功";
}catch (Exception e){
e.printStackTrace();
return "更新失败";
}
}
@DeleteMapping("/delteById")
public String deleteById(Integer id){
bookService.deleteById(id);
return "删除成功";
}
}
这里的接口并不是java中的interface而是指后端的接口。
knife4j我的理解是swagger的升级美化版,因此我给他取名叫美工刀
最后我们获得的界面是这样的
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>knife4j-spring-boot-starterartifactId>
<version>3.0.2version>
dependency>
同时,因为这是最后一个环节了,我将整个pom.xml献上
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.0version>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>libraryartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>libraryname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.0version>
dependency>
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>knife4j-spring-boot-starterartifactId>
<version>3.0.2version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>2.7.0version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
在com.example.library目录下新建config文件夹:
新建MvcConfig类
代码如下
package com.example.library.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
/**
* 静态资源访问路径映射
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
server.port=1213
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=010213
mybatis.type-aliases-package=com.gao.security.bean
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
最后运行即可。
接下来你就可以用JSON格式对你的代码进行测试了。
测试图片如下:
查询:
更新:
本文作者对于springboot也只是初窥门径,该项目与文档同时编写,因此可能会有很多照顾不及之处,希望体谅,随后我会将代码上传到gitee/github上,有兴趣的同学可以下载观看。有发现问题与错误欢迎联系本人。