Spring Boot 是 Pivotal 团队在 Spring 的基础上提供的一套全新的开源框架,其目的是为了简化 Spring 应用的搭建和开发过程。Spring Boot 去除了大量的 XML 配置文件,简化了复杂的依赖管理。
springboot配置文件名称是固定的:
- application.properties 语法结构:key=value
- application.yaml. 语法结构:key:空格 value
1.3 Spring boot核心配置文件(application.properties)org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools
#更改项目的端口号 server.port=8090
改变banner
1.4 Spring boot核心配置文件(application.yaml)#key:空格value
server:
port: 8091
#对象
student:
name: songyaxuan
age: 18
#行内写法
students: {name: liuyaowen,age: 16}
#数组
pets:
-cat
-dog
pet: [cat,dog]
yaml可以给实体类赋值
原来用@value给实体类赋值:
@Component
public class Dog {
@Value("鼠标")
private String name;
@Value("1")
private Integer age;
}
@SpringBootTest
class SpbootApplicationTests {
@Autowired
private Dog dog;
@Test
void contextLoads() {
System.out.println(dog);
}
}
现在通过yaml赋值:
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private Integer age;
private Boolean happy;
private Date birth;
private Map maps;
private List
server:
port: 8091
person:
name: songysxuan
age: 18
happy: true
birth: 2004/03/04
maps: {k1: v2,k2: v2}
lists:
-music
-liu
dog:
name: shubiao
age: 1
@SpringBootTest
class SpbootApplicationTests {
@Autowired
private Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
绑定指定配置文件并给实体类属性赋值:
tnt.properties:
name=shidaishaoniantuan age=2
Person.java:
@Component
@PropertySource(value = "classpath:tnt.properties")
public class Person {
//yaml支持el表达式
@Value("${name}")
private String name;
@Value("${age}")
private Integer age;
}
测试类:
@SpringBootTest
class SpbootApplicationTests {
@Autowired
//private Dog dog;
private Person person;
@Test
void contextLoads() {
System.out.println(person.getName());
System.out.println(person.getAge());
}
}
1.5 Springboot Web开发
需要解决的问题:
- 导入静态资源
- 首页定制
- jap–模版引擎thymeleaf
- 装配扩展springMVC
- 增删改查
- 拦截器
导入依赖:
org.webjars jquery 3.4.1
访问静态资源:
http://localhost:8080/webjars/jquery/3.4.1/jquery.js
或者创建目录(优先级:resource>statis>public)
在templates目录下的所有页面,只能通过controller来跳转!
@RestController
public class IndexController {
@RequestMapping("/index")
public String index(){
return "index";
}
}
1.5.3 模版引擎thymeleaf
导入依赖:
org.springframework.boot spring-boot-starter-thymeleaf
导入依赖以后只需要将html放入templates中,就可以通过controller访问来。
html文件中引入:
Title
1.5.4 装配扩展MVC
先创建一个包config,在里面写一个类
//扩展mvc,implements WebMvcConfigurer并且不可以加注解@EnableWebMvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//请求/candy时页面跳转到hello页面
registry.addViewController("/candy").setViewName("hello");
}
}
1.6 项目实战
1.6.1 准备工作
引入Lombok:
org.projectlombok lombok
@Data:使用这个注解可以省去实体类中大量的get()、 set()、 toString()等方法。
@AllArgsConstructor:有参构造
@NoArgsConstructor:无参构造
注意:以上注解都是在Lombok中的!!!
package com.candy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
//有参构造
@AllArgsConstructor
//无参构造
@NoArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
导入模板:
编写实体类和dao层:
Employee.java:
package com.candy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;//0女1男
private Department department;
private Date birth;
}
DepartmentDao.java:
package com.candy.dao;
import com.candy.pojo.Department;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class DepartmentDao {
private static Map departments = null;
static {
departments = new HashMap();//创建一个部门表
departments.put(101,new Department(101,"教学部"));
departments.put(102,new Department(102,"市场部"));
departments.put(103,new Department(103,"教研部"));
departments.put(104,new Department(104,"运营部"));
departments.put(105,new Department(105,"财务部"));
}
//获得所有部门信息
public Collection getDepartments(){
return departments.values();
}
//通过id得到部门
public Department getDepartmenrById(Integer id){
return departments.get(id);
}
}
EmployeeDao.java:
package com.candy.dao;
import com.candy.pojo.Department;
import com.candy.pojo.Employee;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Repository
public class EmployeeDao {
private static Map employees = null;
@Autowired
private DepartmentDao departmentDao;
static {
employees = new HashMap();//创建一个员工表
employees.put(1001,new Employee(1001,"马嘉祺","11@qq.com",1,new Department(101,"教学部"),new Date()));
employees.put(1002,new Employee(1002,"丁程鑫","12@qq.com",1,new Department(101,"教学部"),new Date()));
employees.put(1003,new Employee(1003,"宋亚轩","13@qq.com",1,new Department(102,"市场部"),new Date()));
employees.put(1004,new Employee(1004,"刘耀文","14@qq.com",1,new Department(102,"市场部"),new Date()));
employees.put(1005,new Employee(1005,"张真源","15@qq.com",1,new Department(103,"教研部"),new Date()));
employees.put(1006,new Employee(1006,"严浩翔","16@qq.com",1,new Department(104,"运营部"),new Date()));
employees.put(1007,new Employee(1007,"贺峻霖","17@qq.com",1,new Department(104,"运营部"),new Date()));
}
//主键自增
private static Integer initId = 1008;
//增加一个员工
public void add(Employee employee){
if (employee.getId()==null){
employee.setId(initId++);
} employee.setDepartment(departmentDao.getDepartmenrById(employee.getDepartment().getId()));
employees.put(employee.getId(),employee);
}
//查询所有员工
public Collection getAll(){
return employees.values();
}
//根据ID查询员工
public Employee getEmploeeById(Integer id){
return employees.get(id);
}
//删除员工
public void del(Integer id){
employees.remove(id);
}
}
1.6.2 首页实现
先配置路径,可以访问index(在config的MyMvcConfig.java):
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("index.html").setViewName("index");
}
}
导入thymeleaf在模板中,并按照规则修改标签中的属性
#关闭thymeLeaf缓存 spring.thymeleaf.cache=false
1.6.3 页面国际化Signin Template for Bootstrap
实现页面中文和英文语言切换!!!
先在resource目录下创建一个包:
然后在application.properties中写好配置文件的路径:
#配置文件的位置 spring.messages.basename=i18n.login
在前端页面中使用语法取值:
为了实现中文和English的按钮,我们自己需要自定义国际化,自己写一个类:
package com.candy.comfig;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocalResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
String language = request.getParameter("l");
Locale locale = Locale.getDefault();//如果没有就使用默认的
//如果请求链接携带了国际化的参数
if (!StringUtils.isEmpty(language)){
String[] split = language.split("_");
locale = new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
然后在mymvcconfig中注册:
//自定义国际化
@Bean
public LocaleResolver localeResolver(){
return new MyLocalResolver();
}
注意:需要先在idea设置的file encoding中将编码语言全部设置为utf-8,否则可能会乱码。
1.6.4 登陆功能实现在前端页面中设置按钮请求:
在controller层写跳转方法:
@RequestMapping("toLogin")
public String toLogin(){
return "login";
}
最后在拦截之后设置登陆请求:
1.9.4 实现用户认证用户认证放在Realm中
先去controller中添加处理登陆过程:
@RequestMapping("/login")
public String login(String username,String password,Model model){
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登陆数据
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try{
subject.login(token);//执行登陆的方法
return "index";
}catch (UnknownAccountException e){//用户名不存在
model.addAttribute("msg","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e){//密码不存在
model.addAttribute("msg","密码错误");
return "login";
}
}
然后去静态页面绑定数据:
最后去Realm中模拟数据并添加认证:
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("认证了");
//用户名、密码
String name = "root";
String password = "123";
UsernamePasswordToken userToken = (UsernamePasswordToken)token;
if (!userToken.getUsername().equals(name)){
return null;//抛出异常 UnknownAccountException
}
//密码认证 shiro做
return new SimpleAuthenticationInfo("",password,"");
}
测试:
1.9.5 整合mybatis导入依赖:
org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.1 mysql mysql-connector-java runtime log4j log4j 1.2.17 com.alibaba druid 1.2.7 org.projectlombok lombok 1.16.10
新建一个application.yaml:
spring:
datasource:
username: root
password: root12345
url: jdbc:mysql://localhost:3306/mybts?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
# 配置初始化大小、最小、最大线程数
initialSize: 5
minIdle: 5
# CPU核数+1,也可以大些但不要超过20,数据库加锁时连接过多性能下降
maxActive: 20
# 最大等待时间,内网:800,外网:1200(三次握手1s)
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最大空间时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
# 设置从连接池获取连接时是否检查连接有效性,true检查,false不检查
testOnBorrow: false
# 设置从连接池归还连接时是否检查连接有效性,true检查,false不检查
testOnReturn: false
# 可以支持PSCache(提升写入、查询效率)
poolPreparedStatements: true
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
# 保持长连接
keepAlive: true
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis:
type-aliases-package: com.candy.pojo
mapper-locations:
- classpath:mapper
private Boolean enable;
private String applicationName;
private String applicationVersion;
private String applicationDescription;
private String tryHost;
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public String getApplicationVersion() {
return applicationVersion;
}
public void setApplicationVersion(String applicationVersion) {
this.applicationVersion = applicationVersion;
}
public String getApplicationDescription() {
return applicationDescription;
}
public void setApplicationDescription(String applicationDescription) {
this.applicationDescription = applicationDescription;
}
public String getTryHost() {
return tryHost;
}
public void setTryHost(String tryHost) {
this.tryHost = tryHost;
}
}
然后在写swaggerconfiguration:
package com.candy.config;
import com.candy.SwaggerProperties;
import io.swagger.models.auth.In;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.*;
@Configuration
@EnableOpenApi
public class SwaggerConfiguration {
private final SwaggerProperties swaggerProperties;
public SwaggerConfiguration(SwaggerProperties swaggerProperties) {
this.swaggerProperties = swaggerProperties;
}
@Bean
public Docket createReatApi(){
return new Docket(DocumentationType.OAS_30).pathMapping("/")
//定义是否开启swagger
.enable(swaggerProperties.getEnable())
//将api的元信息设置为包含json ResourceListing响应中
.apiInfo(apiInfo())
//设置接口调试地址
.host(swaggerProperties.getTryHost())
//选择哪些接口作为swagger的doc发布
.select()
//配置要扫描接口的方式 any:全部 basePackage:指定包
.apis(RequestHandlerSelectors.basePackage("com.candy"))
//过滤路径
.paths(PathSelectors.any())
.build()
//支持的通讯协议集合
.protocols(newHashSet("https","http"))
//授权信息设置,必要的header token等认证信息
.securitySchemes(securitySchemes())
//授权信息全局应用
.securityContexts(securityContexts());
}
//api页面上半部分展示信息
private ApiInfo apiInfo(){
return new ApiInfoBuilder().title(swaggerProperties.getApplicationName()+"ApiDoc")
.description(swaggerProperties.getApplicationDescription())
//作者信息
.contact(new Contact("sixcandy","null","1161187988@qq.com"))
.version("application version:"+swaggerProperties.getApplicationVersion())
.build();
}
private Set newHashSet(String type1,String type2){
Set set = new HashSet<>();
set.add(type1);
set.add(type2);
return set;
}
private List securitySchemes(){
ApiKey apiKey = new ApiKey("BASE_TOKEN","token", In.HEADER.toValue());
return Collections.singletonList(apiKey);
}
private List securityContexts(){
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN",new AuthorizationScope[]{new AuthorizationScope("global","")} )))
.build()
);
}
}
测试:
给api文档写注释:
添加一个user类:
package com.candy.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("用户实体类")
public class User {
@ApiModelProperty("用户名")
public String username;
@ApiModelProperty("密码")
public String password;
}
改造controller:
@RestController
public class HelloController {
@GetMapping (value = "/hello")
public String hello(){
return "hello";
}
@PostMapping("/user")
public User user(){
return new User();
}
}
测试:
完结撒花!!!芜湖!!!



