一、Spring的优缺点
优点
开源,轻量级,非侵入式的一站式框架,简化企业级应用开发。
控制反转(IOC),依赖注入(DI)降低了组件之间的耦合性,实现了软件各层之间 的解耦。
面向切面(AOP),利用它可以很容易实现一些拦截,如事务控制等。
spring 对于主流的应用框架提供了很好的支持,例如mybatis。
spring 提供有自己的mvc实现。
不足
虽然spring 的组件代码是轻量级的,但它的配置却是重量级的。虽然spring 引入了注解功能,但是仍然需要编写大量的模板化配置文件.
例如:目前大多数都是用注解进行配置,但每次都需要我们在spring全局配置文件中进行配置,十分麻烦
<!--在全局变量中 开启AOP自动代理注解--> <aop:aspectj-autoproxy/> <!-- 开启注解事务管理--> <tx:annotation-driven transaction-manager="transactionManager"/> <!--开启web注解--> <mvc:annotation-driven></mvc:annotation-driven>
项目的依赖管理也是一件耗时耗力的事情,在环境搭建时,需要分析要导入大量库的坐标,而且还需要分析导入与之有依赖关,一旦选错依赖的版本,随之而 来的不兼容问题就会严重阻碍项目的开发进度。
例如;
<!--jackson--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.14.2</version> </dependency> <!--生成token--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </dependency> <!-- lombok组件(自动生成get、set方法)--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency> <!-- spring-aop--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.2.2.RELEASE</version> </dependency> <!--springWeb--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.2.RELEASE</version> </dependency> </dependencies>
引入
Spring Boot 对上述spring的缺点进行的改善和优化,基于约定优于配置的思 想.可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入 到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目 周期
二、SpringBoot概述
1、SpringBoot介绍
Spring Boot 是由Pivotal 团队提供的在spring框架基础之上开发的框架, 其设计目的是用来简化应用的初始搭建以及开发过程
Spirng Boot 本身并不提供Spring框架的核心特性以及扩展功能,只是用 于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具
Spring Boot 以约定大于配置的核心思想(把开发中默认的做法直接进行简化),从而使开发人员不再需要定义样板化的配置。它集成了大量常用的第三方库配置(自动将相关的基础性的依赖集成进来),SpringBoot 应用中这些第三方库几乎可以零配置的开箱即用, 通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域成为领导者
2、SpringBoot 特点
创建独立的spring应用程序
直接内嵌tomcat、jetty和undertow
提供了固定化的“starter”配置,以简化构建配置
尽可能的自动配置spring和第三方库
提供产品级的功能,如:安全指标、运行状况监测和外部化配置等
绝对不会生成代码,并且不需要XML配置
3、springBoot 的核心功能
起步依赖
起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
自动配置
Spring Boot 的自动配置是一个运行时(更准确地说,是应用程序启动时) 的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的
三、springBoot的搭建
1、创建一个普通的maven项目
2、将pow.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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wbc.ssm</groupId>
<artifactId>news</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<!--依赖的父级工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
<relativePath/>
</parent>
<!--添加基本的springweb依赖-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--SpringBoot 集成 mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!--打包插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.6</version>
</plugin>
</plugins>
</build>
</project>
3、创建基本包目录,在包下创建一个启动类
package com.wbc.news;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.wbc.news.dao")
public class NewsApplication {
/*springboot启动类*/
public static void main(String[] args) {
SpringApplication.run(NewsApplication.class);
}
}
(选)设置一个启动logo
在线生成启动logo: https://www.bootschool.net/ascii-art 下载存放在resources目录下即可.
4、配置Spring Boot 配置文件
配置文件格式有两种,一种为properties格式,一种yaml格式
1、application.properties
以键值对的方式进行配置,这里不做演示
server.port=8182
2、application.yml
yml 配置示例 server: port: 8080
yaml 基本语法:
语法结构:
key:
空格value;
以此来表示一对键值对(空格不能省略);
以空格的缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级 的;
字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号;
以#作为注释符号
#配置内置服务器端口 server: port: 8182 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/ssmd?serverTimezone=Asia/Shanghai username: root password: Wbc11280 type: com.alibaba.druid.pool.DruidDataSource initialSize: 5 #初始化时建立物理连接的个数 maxActive: 20 #最大连接池数量 mybatis: type-aliases-package: com.wbc.news.model mapper-locations: classpath:mapper/*Mapper.xml configuration: map-underscore-to-camel-case: true cache-enabled: true
5、导入一些常用的基本类以及第一个Admin模型及其相关层处理
admin类
package com.wbc.news.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Date;
@Component
public class Admin implements Serializable {
/*开启缓存需要返回的model类实现序列化接口Serializable*/
private int id;
private String account;
private String password;
@DateTimeFormat(pattern = "yyyy-MM-dd")//接收前端提交数据的日期格式
@JsonFormat(pattern = "yyyy-MM-dd")//后端向前端转json时的日期格式
private Date birthday;
//lombok组件 在编译期间动态生成get、set方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", account='" + account + '\'' +
", password='" + password + '\'' +
'}';
}
}
loginDao
package com.wbc.news.dao;
import com.wbc.news.model.Admin;
import java.util.List;
public interface LoginDao {
List<Admin> login();
}
loginService逻辑处理层
package com.wbc.news.service;
import com.wbc.news.dao.LoginDao;
import com.wbc.news.model.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class LoginService {
@Autowired
LoginDao loginDao;
public List<Admin> login() {
List<Admin> admins = loginDao.login();
return admins;
}
}
loginController控制层
package com.wbc.news.web;
import com.wbc.news.model.Admin;
import com.wbc.news.model.Result;
import com.wbc.news.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(path = "loginCtl")
public class LoginController {
/*@Value("${admin.account}")
private String account;*/
@Autowired
private LoginService loginService;
@PostMapping(path = "login")
public String login() {
System.out.println("login");
return "success";
}
//通过对象接收 result返回值
@PostMapping(path = "login1")
public Result login5(Admin admin, @RequestHeader("adminToken") String adminToken){
System.out.println(adminToken);
List<Admin> admins = loginService.login();
Result result = new Result(200,"success",admins);
return result;
}
@GetMapping(path = "test")
public String test(){
System.out.println("test");
return "test";
}
}
统一异常处理
package com.wbc.news.util;
import com.wbc.news.model.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
/*统一异常处理*/
@ExceptionHandler(Exception.class)
public Result globalException(Exception e) {
Result result = new Result(500,e.getMessage(),null);
return result;
}
}
Result模型
package com.wbc.news.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
@Component
/*
lombok 自动生成set get toString equals hashCode
*/
@Data
@AllArgsConstructor//生成满参构造方法
@NoArgsConstructor//构造无参构造方法
public class Result {
private int code;
private String message;
private Object data;
}
Token拦截器
package com.wbc.news.Interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wbc.news.model.Result;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AdminTokenInterceptor implements HandlerInterceptor {
/*
拦截器处理方法
当请求达到处理器前,进入到拦截器进行处理
返回true--离开拦截器向后执行到达处理器
返回flase--不再向后执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String adminToken = request.getHeader("adminToken");
if (adminToken.equals("123456")) {
return true;
}
else {
System.out.println("adminToken:"+adminToken);
Result result = new Result(401,"adminToken验证失败",null);
response.getWriter().write(new ObjectMapper().writeValueAsString(result));
}
return false;
}
}
拦截器配置
package com.wbc.news.config;
import com.wbc.news.Interceptor.AdminTokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class WebConfig implements WebMvcConfigurer{
/*配置拦截器*/
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration inter = registry.addInterceptor(new AdminTokenInterceptor());//添加拦截器
inter.addPathPatterns("/**"); //管理员需要拦截过滤地址
inter.excludePathPatterns("/loginCtl/login1");//放行地址
inter.excludePathPatterns("/loginCtl/login");//放行地址
//inter.addPathPatterns("/user/**"); //用户需要拦截过滤地址
}
}
6、通过StringBoot启动项运行测试
运行成功