SpringBoot从入门到精通(全)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 前言==本博文结合软件idea进行主要讲解==**springboot的特性主要有**- 简化 Spring 应用程序的创建和开发过程- 抛弃了繁琐的 xml 配置过程,采用大量的默认配置简化以及注解反射- 直接使用 java main 方法启动内嵌的 Tomcat 服务器运行 Spring Boot 程序,不需要部署 war 包文件**四大核心**分别为自动配置、起步依赖、Actuator和命令行界面

前言

==本博文结合软件idea进行主要讲解==

文中主要的学习视频主要通过
最新SpringBoot2教程-从零深入SpringBoot【实战解读SpringBoot】

博文中的源码主要在
源码课程

更多Java知识点:java框架零基础从入门到精通的学习路线(超全)

springboot的特性主要有

  • 简化 Spring 应用程序的创建和开发过程
  • 抛弃了繁琐的 xml 配置过程,采用大量的默认配置简化以及注解反射
  • 直接使用 java main 方法启动内嵌的 Tomcat 服务器运行 Spring Boot 程序,不需要部署 war 包文件

四大核心分别为自动配置、起步依赖、Actuator和命令行界面

1. 入门案例

1.1 新建项目

创建一个基本的springboot项目
springboot的初始化结构默认是需要连接网络的
在这里插入图片描述

以下大部分是默认设置,主要填写项目名包名等
修改java的version为8
在这里插入图片描述
下一步为设置依赖信息
springboot是web工程,选择web工程,版本是最新版本,不要选择SNAPSHOT测试版本。RELEASE为最新稳定版本。
在这里插入图片描述
最后的工程目录为
.gitignore为设置可忽视的后缀名文件
mcnw名字系列为命令行界面
我们只需要关注pom.xml文件即可
在这里插入图片描述
springboot也是基于maven项目
有parent父工程以及子工程,其版本信息可不一致
查看pom.xml文件

  • springboot框架下web项目的起步依赖信息、测试起步依赖信息以及打包编译的插件

具体起步依赖信息和测试起步依赖信息的版本号多数跟父工程

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

查看其它目录结构文件
在这里插入图片描述

  • 在static中主要存放的是css、html等静态文件
  • templates为前端模板
  • application.properties为核心配置文件

springboot的启动入口类在main下,test文件同理

  • 核心注解,主要用于开启spring自动配置
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

1.2 代码模板

以下代码可能会出现maven项目的配置问题或者springboot的出错可查看我之前的文章
1.maven:编译出现Process terminated解决方法

2.springboot:出现Could not transfer artifact org.springframework.boot:spring-boot-等问题解决方法

springboot项目代码必须放到Application类所在的同级目录或下级目录

//SpringBoot项目启动入口类
@SpringBootApplication  //开启springboot配置
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

在下一级目录中新建一个类
添加注解
value设置的是路径。通过tomcat访问,后面加此路径即可

@Controller
public class IndexController {

    @RequestMapping(value = "/springboot/say")
    public @ResponseBody String say() {
        return "Hello,SpringBoot!";
    }
}

运行主函数之后出现如图所示即可
在这里插入图片描述
在网页中输入http://localhost:8080/springboot/say
即可访问网址
在这里插入图片描述
可以以map的方式出现

@RequestMapping(value = "/mapvalue")
public @ResponseBody Map<String,Object> mapvalue() {
     Map<String,Object> retMap = new HashMap<String, Object>();
     retMap.put("message","SpringBoot Project");

  return retMap;
}

访问网址的格式如下
http://localhost:8081/springboot/mapvalue
在这里插入图片描述
可以以传参格式进入

@Controller
public class IndexController {


    @RequestMapping(value = "/say")
    public @ResponseBody Object say(String message) {

        return "Say:Hello " + message;
    }
}

具体传参的格式截图如下
http://localhost:9090/yaml/say?message=3
在这里插入图片描述

==总结以上模板主要有@Controller、@RequestMapping以及@ResponseBody注解等==

2. 配置详解

2.1 核心配置文件properties

如果不做设置的时候会自动配置,如果不想自动可以自已设置内嵌Tomcat端口号以及上下文根,上下文根必须加/

  • 一个工程文件只能有一个核心配置文件
#设置内嵌Tomcat端口号
server.port=8081

#设置上下文根
server.servlet.context-path=/springboot

在网页中输入http://localhost:8081/springboot/say

配置完成之后的显示为
在这里插入图片描述

2.2 核心配置文件yml、yaml

yml、yaml配置文件比较少用
注释该配置文件后面加--
删除properties配置文件建立一个yml后缀的文件

在这里插入图片描述
具体配置信息如下
yml配置文件主要采用前后的空格以及tab键位格式
==值前面需要有空格==

server:
  port: 8081
  servlet:
    context-path: /

同理yaml配置文件也一样

server:
  port: 9090
  servlet:
    context-path: /yaml

在网页中输入http://localhost:9090/yaml/say

==如果配置文件properties和yml都存在,则以properties配置文件为主==
涉及其他配置文件比如maven的私服
可查看我之前的文章Maven详细配置(全)
剖析配置主要是这一段导致而已

<mirrors>

<mirror>

<id>alimaven</id>

<name>aliyun maven</name>

<!-- https://maven.aliyun.com/repository/public/ -->


<url>http://maven.aliyun.com/nexus/content/groups/public/</url>

<mirrorOf>central</mirrorOf>

</mirror>

</mirrors>

<!-- 配置: java8, 先从阿里云下载, 没有再去私服下载 -->

2.3 多环境核心配置文件properties

工作中的开发环境:开发、测试、准生产和生产四种环境
ip地址用户环境等可能都不一样
所以需要配置四个环境
在这里插入图片描述
比如开发环境的配置文件

#开发环境配置文件
server.port=8080
server.servlet.context-path=/dev

但环境太多,需要配置一个主配置环境当前使用的是哪一个
则在application.properties中书写
active的激活配置文件主要是根据application-xxx后面的xxx必须是英文不能是中文

#springboot主核心配置文件
#激活使用的配置文件
spring.profiles.active=dev

2.4 多环境核心配置文件yml

yml同理properties配置文件
在这里插入图片描述
配置一个yml配置文件

server:
  port: 8080
  servlet:
    context-path: /product

配置一个主yml配置文件

spring:
  profiles:
    active: product

2.5 自定义配置

2.5.1 @value

主要是为了取值
这个是设置了配置文件,在类中使用 @value来取值

在properties核心配置文件中
添加自定义的配置

#设置内嵌tomcat端口号
server.port=8080
#设置上下文根
server.servlet.context-path=/


school.name=manongyanjiuseng
websit=http://www.manongyanjiuseng.com

通过配置一个一个@Value
在代码中通过用注解的方式去取用@Value
通过@Value(${ })传值进入
赋值给一个参数比如private String schoolName;

@Value("${school.name}")
private String schoolName;

@Value("${websit}")
private String websit;

@RequestMapping(value = "/say")
public @ResponseBody String say() {
    return "Hello:" + schoolName + ":" + websit;
}

2.5.2 @ConfigurationProperties

与上面的区别就是没有直接用@value
而是通过一个注解类
最后引用的是对象而不是所属值

通过对象注解,引用核心配置文件

@ConfigurationProperties主要是为了映射对象
@Component将此类将给spring容器进行管理

自定义配置为

server.port=8080
server.servlet.context-path=/

school.name=manongyanjiuseng
websit=http://码农研究僧个人博客

abc.name=abc
abc.websit=http://码农研究僧个人博客

在代码中这样书写@ConfigurationProperties此为核心配置类
@ConfigurationProperties必须有前缀prefix
如果有同名属性可以用这个

@Component//将此类将给spring容器进行管理
@ConfigurationProperties(prefix = "school")
public class School {

    private String name;

    private String websit;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getWebsit() {
        return websit;
    }

    public void setWebsit(String websit) {
        this.websit = websit;
    }
}

在主函数中通过注解的方式进行@Autowired

@Controller
public class IndexController {

    @Autowired
    private School school;

    @Autowired
    private Abc abc;

    @RequestMapping(value = "/say")
    public @ResponseBody String say() {


        return "school.name="+school.getName()+"-----school.websit="+school.getWebsit() + "====abc.name"+abc.getName()+"===abc.websit="+abc.getWebsit();
    }
}

==特别注意==
使用@ConfigurationProperties 注解出现警告问题
可以在pom.xml配置文件中加入以下配置

<!--解决使用@ConfigurationProperties 注解出现警告问题-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

截图如下
在这里插入图片描述

3. springboot之web工程

3.1 集成jsp

存放jsp文件目录结构为
在这里插入图片描述
在main下新建一个webapp并将该目录设置为web资源文件

具体配置可查看我之前的文章
Tomcat:HTTP状态 404 - 未找到解决方法
在这里插入图片描述

  • Springboot项目默认推荐使用的前端引擎是thymeleaf,要使用springboot集成jsp,需要添加依赖信息,以及手动指定jsp最后编译的路径而且springboot集成jsp,编译jsp的路径是springboot规定好的位置META-INF/resources

jsp的依赖信息放在xml配置中

<!--引入SpringBoot内嵌Tomcat对jsp的解析依赖,不添加解析不了jsp-->
<!--仅仅只是展示jsp页面,只添加一个依赖-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

指定jsp路径需要放在pom.xml配置文件中的build中

<resources>
    <resource>
        <!--源文夹-->
        <directory>src/main/webapp</directory>
        <!--指定编译到META-INF/resources-->
        <targetPath>META-INF/resources</targetPath>
        <!--指定源文件夹中的哪个资源要编译进行-->
        <includes>
            <include>*.*</include>
        </includes>
    </resource>
</resources>

还需要配置视图解析器
配置在application.properties中

#配置视图解析器
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

java文件格式调用为
集成jsp页面不用@ResponseBody这个注解
集成jsp有两种比较,注意对比以及区别
后面会经常使用到
传入的第一个参数是给前端使用的

@Controller
public class IndexController {

    @RequestMapping(value = "/say")
    public ModelAndView say() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("message","Hello,SpringBoot");
        mv.setViewName("say");
        return mv;
    }

    //也可以
    @RequestMapping(value = "/index")
    public String index(Model model) {
        model.addAttribute("message","HelloWorld");
        return "say";
    }
}

注意上面这两者的区别

  • 一个是传入model的这个对象,之后通过addAttribute这个方法将其添入,第一个参数是jsp传参的参数
  • 另一个是直接定义ModelAndView这个方法,使用这个类的addObject将其jsp中参数传入

代码中具体的参数可看我这篇文章
SpringMVC之ModelAndView类详细分析(全)

jsp具体内容为

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>

最后具体的截图如下
在这里插入图片描述
总的来说这个有两种模板
==模板如下==

@RequestMapping(value = "/index")
public String index(Model model) {
    model.addAttribute("data","SpringBoot Thymeleaf");
    return "index";
}

@RequestMapping(value = "/index1")
public ModelAndView index1() {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("index");
    mv.addObject("data","SpringBoot");
    return mv;
}

//放入对象
@RequestMapping(value = "/user/detail")
public ModelAndView userDetail() {
    ModelAndView mv = new ModelAndView();
    User user = new User();
    user.setId(1001);
    user.setAge(23);
    user.setUsername("lisi");

    mv.setViewName("userDetail");
    mv.addObject("user",user);

    return mv;
}

3.2 集成Mybatis

需要添加mybatis的依赖以及mysql驱动

<!--MySQL驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <!--<version>5.1.9</version>-->
</dependency>

<!--MyBatis整合SpringBoot框架的起步依赖-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

通过使用mybatis逆向工程集成
可看我之前的文章
mybatis逆向工程详细配置讲解(全)

通过逆向工程生成的映射,具体如何使用
可继续往下看

接口类

public interface StudentService {

    /**
     * 根据学生ID查询详情
     * @param id
     * @return
     */
    Student queryStudentById(Integer id);
}

接口实现类
通过@Service注解进行说明,通过 @Autowired进行对象注入,之后可以使用他的函数

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public Student queryStudentById(Integer id) {
        return studentMapper.selectByPrimaryKey(id);
    }
}

具体如何使用他的函数主要是通过mapper的映射类进行标注
通过@Mapper 扫描DAO接口到spring容器
在这里插入图片描述

在用户层界面上实现他的逻辑代码
主要代码如下
通过@Controller进行注解说明,通过 @Autowired进行对象注入

@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;

    @RequestMapping(value = "/student")
    public @ResponseBody Object student(Integer id) {

        Student student = studentService.queryStudentById(id);

        return student;
    }
}

最后还要配置数据库的用户信息,才可进行使用

#设置连接数据库的配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.154.128:3306/springboot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123

==补充说明==
由于mapper文件中的映射文件在src上,而且是xml文件结尾
编译的时候执行的结果不会出来
所以要添加扫描
再pom.xml文件中添加如下

<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
    </resource>
</resources>

第二种方案是:
将其mapper的映射文件移到resources上
之后再连接数据库配置末尾添加如下

#指定MyByBatis映射文件的路径
mybatis.mapper-locations=classpath:mapper/*.xml

基于以上两种方式
在最后都要在springboot中添加如下注解,之后pom.xml文件可以将其删除

@SpringBootApplication  //开启spring配置
@MapperScan("com.bjpowernode.springboot.mapper") //开启扫描Mapper接口的包以及子目录
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

3.3 事务

事务是一个完整的功能,也叫做一个完整的事务
事务只跟数据库的DML语句有关系:增删改

具体例子如下
通过逆向工程生成mapper和类等
之后添加相对应的控制层界面@Controller
在界面中定义接口类,以及要实现的接口实现类函数
接口实现类传入的参数是mapper映射的类

@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;

    @RequestMapping(value = "/update")
    public @ResponseBody Object update(Integer id,String name) {
        Student student = new Student();
        student.setId(id);
        student.setName(name);
        int updateCount = studentService.updateStudentById(student);

        return "修改学生编号为"+id+"的姓名修改结果:"+updateCount;
    }
}

接口类为

public interface StudentService {

    /**
     * 根据学生ID修改学生信息
     * @param student
     * @return
     */
    int updateStudentById(Student student);
}

接口实现类为
为了更好的实现事务的回滚,此处添加了一个bug
正常情况下应该不允许修改

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    
    @Override
    public int updateStudentById(Student student) {

        //修改成功
        int i = studentMapper.updateByPrimaryKeySelective(student);

        //失败
        int a = 10/0;

        return i;
    }
}

因为在xml中有配置文件,且在src目录下的
所以需要配置@MapperScan(basePackages = "com.bjpowernode.springboot.mapper")

@SpringBootApplication
@MapperScan(basePackages = "com.bjpowernode.springboot.mapper")
@EnableTransactionManagement    //开启事务(可选项)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

最后在资源环境下还要添加sql的数据库信息
在这里插入图片描述
基于以上代码,最后还是修改成功
是因为还没有添加事务的回滚
具体添加回滚可以在接口实现类的函数中添加 @Transactional
并且在加载类中添加@EnableTransactionManagement //开启事务(可选项)

3.4 SpringmMVC常用注解

@Controller 处理 http 请求

如果控制层类上有实现的方法函数
@RestController //相当于控制层类上加@Controller + 方法上 @ResponseBody意味着当前控制层类中所有方法返还的都是JSON对象

在这里插入图片描述
@RequestMapping支持 Get 请求,也支持 Post 请求,本身第二个参数就是选择这个
@GetMapping 该注解通过在查询数据的时候使用 -> 查询
@PostMapping 该注解通常在新增数据的时候使用 -> 新增
@DeleteMapping 该注解通常在删除数据的时候使用 -> 删除
@PutMapping 该注解通常在修改数据的时候使用 -> 更新

具体代码展示逻辑

//@Controller
@RestController  //相当于控制层类上加@Controller + 方法上加@ResponseBody
// 意味着当前控制层类中所有方法返还的都是JSON对象
public class StudentController {


    @RequestMapping(value = "/student")
//    @ResponseBody
    public Object student() {
        Student student = new Student();
        student.setId(1001);
        student.setName("zhangsan");
        return student;
    }

    //该方法请求方式支持:GET和POST请求
    @RequestMapping(value = "/queryStudentById",method = {RequestMethod.GET,RequestMethod.POST})
    public Object queryStudentById(Integer id) {
        Student student = new Student();
        student.setId(id);
        return student;
    }


//    @RequestMapping(value = "/queryStudentById2",method = RequestMethod.GET)
    @GetMapping(value = "/queryStudentById2") //相当于上一句话,只接收GET请求,如果请求方式不对会报405错误
    //该注解通过在查询数据的时候使用 -> 查询
    public Object queryStudentById2() {
        return "Ony GET Method";
    }

//    @RequestMapping(value = "/insert",method = RequestMethod.POST)
    @PostMapping(value = "/insert") //相当于一句话
    //该注解通常在新增数据的时候使用 -> 新增
    public Object insert() {
        return "Insert success";
    }

//    @RequestMapping(value = "/delete",method = RequestMethod.DELETE)
    @DeleteMapping(value = "/delete")//相当于上一句话
    //该注解通常在删除数据的时候使用 -> 删除
    public Object delete() {
        return "delete Student";
    }


//    @RequestMapping(value = "/update",method = RequestMethod.PUT)
    @PutMapping(value = "/update") //相当于上一句话
    //该注解通常在修改数据的时候使用 -> 更新
    public Object update() {
        return "update student info1";
    }
}

3.5 RESTful

  • 一种协议
  • 主要是形式比较方便

比如我们要访问一个 http 接口:http://localhost:8080/boot/order?id=1021&status=1
采用 RESTFul 风格则 http 地址为:http://localhost:8080/boot/order/1021/1

通常在RESTful风格中方法的请求方式会按增删改查的请求方式来区分或者修改请求路径
RESUful请求风格要求路径中使用的单词都是名称,最好不要出现动词

主要的注解有:
@PathVariable 获取 url 中的数据

具体的实现代码如下

@RestController
public class StudentController {


    @RequestMapping(value = "/student")
    public Object student(Integer id,Integer age) {
        Student student = new Student();
        student.setId(id);
        student.setAge(age);
        return student;
    }

//    @RequestMapping(value = "/student/detail/{id}/{age}")
    @GetMapping(value = "/student/detail/{id}/{age}")
    public Object student1(@PathVariable("id") Integer id,
                           @PathVariable("age") Integer age) {
        Map<String,Object> retMap = new HashMap<>();

        retMap.put("id",id);
        retMap.put("age",age);
        return retMap;
    }

//    @RequestMapping(value = "/student/detail/{id}/{status}")
    @DeleteMapping(value = "/student/detail/{id}/{status}")
    public Object student2(@PathVariable("id") Integer id,
                           @PathVariable("status") Integer status) {
        Map<String,Object> retMap = new HashMap<>();

        retMap.put("id",id);
        retMap.put("status",status);
        return retMap;
    }

    //以上代码student1和student2会出现请求路径冲突问题
    //通常在RESTful风格中方法的请求方式会按增删改查的请求方式来区分
    //修改请求路径
    //RESUful请求风格要求路径中使用的单词都是名称,最好不要出现动词

    @DeleteMapping(value = "/student/{id}/detail/{city}")
    public Object student3(@PathVariable("id") Integer id,
                           @PathVariable("city") Integer city) {
        Map<String,Object> retMap = new HashMap<>();

        retMap.put("id",id);
        retMap.put("city",city);
        return retMap;
    }

    @PostMapping(value = "/student/{id}")
    public String addStudent(@PathVariable("id") Integer id) {
        return "add student ID:" + id;
    }

    @PutMapping(value = "/student/{id}")
    public String updateStudent(@PathVariable("id") Integer id) {
        return "update Student ID:" +id;
    }
}

3.6 集成redis

具体这部分的内容知识点可查看我之前的文章
Redis框架从入门到学精(全)
需要配置依赖文件

<!--SpringBoot集成Redis的起步依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

还要设置redis服务器的具体信息

#设置redis配置信息
spring.redis.host=192.168.154.128
spring.redis.port=6379
spring.redis.password=123456

接口代码

public interface StudentService {

    /**
     * 将值存放到redis中
     * @param key
     * @param value
     */
    void put(String key, String value);

    /**
     * 从redis中获取指定key的值
     * @param key
     * @return
     */
    String get(String key);
}

接口实现代码

@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Override
    public void put(String key, String value) {

        redisTemplate.opsForValue().set(key,value);

    }

    @Override
    public String get(String key) {

        String count = (String) redisTemplate.opsForValue().get(key);

        return count;
    }
}

具体代码的实现类为

@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;

    @RequestMapping(value = "/put")
    public @ResponseBody Object put(String key,String value) {

        studentService.put(key,value);

        return "值已成功放入redis";
    }

    @RequestMapping(value = "/get")
    public @ResponseBody String get() {
        String count = studentService.get("count");
        return "数据count为:" + count;
    }
}

以上用到一个模板主要是通过依赖文件引入
具体可查看这篇文章
RedisTemplate操作Redis,这一篇文章就够了(一)

3.7 集成dubbo

这部分内容的知识可看我之前的文章
Dubbo从入门到精通(全)

实现dubbo要有3个工程

  • 接口:存放实体bean和业务接口
  • 服务提供者:业务接口的实现类并且将服务暴露且注册到注册中心,调用数据持久层。主要的步骤是添加依赖(dubbo、注册中心、接口工程),配置服务提供者核心配置文件
  • 服务消费者:处理浏览器客户端发送的请求,从注册中心调用服务提供者所提供的服务。主要的步骤是添加依赖(dubbo、注册中心、接口工程),配置服务消费者核心配置文件

依赖文件都是相同的
主要如下

<!--Dubbo集成SpringBoot框架起步依赖-->
<dependency>
    <groupId>com.alibaba.spring.boot</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

<!--注册中心-->
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.10</version>
</dependency>

<!--接口工程-->
<dependency>
    <groupId>com.bjpowernode.springboot</groupId>
    <artifactId>020-springboot-dubbo-interface</artifactId>
    <version>1.0.0</version>

服务消费者:
实现业务逻辑的一个层面
此处比往常多了一个表示dubbo接口暴露的注解@Reference(interfaceClass = StudentService.class,version = "1.0.0",check = false)

@Controller
public class StudentController {
    //dubbo:reference interface="" version="" check=false
    @Reference(interfaceClass = StudentService.class,version = "1.0.0",check = false)
    private StudentService studentService;

    @RequestMapping(value = "/student/count")
    public @ResponseBody Object studentCount() {

        Integer allStudentCount = studentService.queryAllStudentCount();

        return "学生总人数为:"+allStudentCount;
    }
}

服务提供者:

接口交给spring容器@Component
暴露接口需要使用这个 @Service(interfaceClass = StudentService.class,version = "1.0.0",timeout = 15000)

@Component
@Service(interfaceClass = StudentService.class,version = "1.0.0",timeout = 15000)
//dubbo:service interface="" version="" timeout=""
public class StudentServiceImpl implements StudentService {

    @Override
    public Integer queryAllStudentCount() {

        //调用数据持久层

        return 1250;
    }
}

接口工程:

public interface StudentService {

    /**
     * 获取学生总人数
     * @return
     */
    Integer queryAllStudentCount();
}

在消费者和服务提供者的配置类中
还要添加一个开启dubbo的配置,不一样注解不一样的开启配置

@SpringBootApplication      //开启spring配置
@EnableDubboConfiguration   //开启dubbo配置
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

3.8 集成ssm

主要集成了dubbo、mybatis、spring、springmvc和jsp
一共有三个工程量

  • 接口工程:存放实体bean和业务接口
  • 服务提供者:集成mybatis、redis

添加依赖文件:mybatis依赖,mysql驱动依赖,dubbo依赖,zookeeper依赖,redis依赖,接口工程
配置核心配置文件:配置连接数据库,配置连接redis,配置dubbo

  • 服务消费者:集成jsp,dubbo

添加依赖文件:dubbo依赖,zookeeper依赖,解析jsp页面的依赖,接口工程
配置核心配置文件:配置视图解析器,配置dubbo

主要的代码逻辑步骤如下
先导入逆向工程代码以及配置逆向工程的依赖文件
注意这个地方的model和mapper文件归属不一样的工程
在这里插入图片描述
以及依赖文件

<!--mybatis 代码自动生成插件-->
<plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>1.3.6</version>
    <configuration>
        <!--配置文件的位置-->
        <configurationFile>GeneratorMapper.xml</configurationFile>
        <verbose>true</verbose>
        <overwrite>true</overwrite>
    </configuration>
</plugin>

之后生成对应的文件结构

==消费者的工程类==
配置依赖文件

<!--SpringBoot框架web项目起步依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--Dubbo集成SpringBoot框架起步依赖-->
<dependency>
    <groupId>com.alibaba.spring.boot</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

<!--zookeeper注册中心-->
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.10</version>
</dependency>

<!--接口工程-->
<dependency>
    <groupId>com.bjpowernode.springboot</groupId>
    <artifactId>023-springboot-dubbo-ssm-interface</artifactId>
    <version>1.0.0</version>
</dependency>

<!--SpringBoot集成JSP,仅仅只是展示JSP页面需要添加解析jsp页面的依赖-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

书写代码逻辑类
控制层面的代码
@Reference暴露端口
通过model去接收该类

@Controller
public class StudentController {

    @Reference(interfaceName = "com.bjpowernode.springboot.service.StudentService",version = "1.0.0",check = false)
    private StudentService studentService;

    @RequestMapping(value = "/student/detail/{id}")
    public String studentDetail(Model model,
                                @PathVariable("id") Integer id) {

        Student student = studentService.queryStudentById(id);

        model.addAttribute("student",student);

        return "studentDetail";
    }

    @GetMapping(value = "/student/all/count")
    public @ResponseBody Object allStudentCount() {

        Integer allStudentCount = studentService.queryAllStudentCount();

        return "学生总人数为:"+allStudentCount;
    }


}

配置文件
不用声明dubbo的消费者配置
因为还有jsp页面,所以还要配置jsp的视图解析器

#设置内嵌Tomcat端口号
server.port=8080
server.servlet.context-path=/

#设置dubbo配置
spring.application.name=025-springboot-dubbo-ssm-consumer
spring.dubbo.registry=zookeeper://192.168.154.128:2181

#配置视图解析器
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

jsp还需要配置资源位置

<resource>
    <directory>src/main/webapp</directory>
    <targetPath>META-INF/resources</targetPath>
    <includes>
        <include>*.*</include>
    </includes>
</resource>

jsp的主要页面也就是传参进入而已

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>学生详情</title>
</head>
<body>
<h3>学生编号:${student.id}</h3>
<h3>学生姓名:${student.name}</h3>
<h3>学生年龄:${student.age}</h3>
</body>
</html>

==提供者的代码==
配置依赖文件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--Dubbo集成SpringBoot起步依赖-->
<dependency>
    <groupId>com.alibaba.spring.boot</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

<!--注册中心-->
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.10</version>
</dependency>

<!--MyBatis集成Springboot起步依赖-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

<!--MySQL驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<!--SpringBoot集成Redis起步依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--接口工程-->
<dependency>
    <groupId>com.bjpowernode.springboot</groupId>
    <artifactId>023-springboot-dubbo-ssm-interface</artifactId>
    <version>1.0.0</version>
</dependency>

还需要添加一个扫面xml文件的
因为逆向工程生成的mapper在src目录下

<resource>
    <directory>src/main/java</directory>
    <includes>
        <include>**/*.xml</include>
    </includes>
</resource>

代码逻辑的实现类
通过spring的容器对象进行注解@Component
暴露端口@Service

@Component
@Service(interfaceName = "com.bjpowernode.springboot.service.StudentService",version = "1.0.0",timeout = 15000)
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Override
    public Student queryStudentById(Integer id) {
        return studentMapper.selectByPrimaryKey(id);
    }

    @Override
    public Integer queryAllStudentCount() {

        //提升系统性能,用户体验提升
        //首先去redis缓存中查询,如果有:直接使用,如果没有:去数据库查询并存放到redis缓存中
        Integer allStudentCount = (Integer) redisTemplate.opsForValue().get("allStudentCount");

        //判断是否有值
        if (null == allStudentCount) {

            //去数据库查询
            allStudentCount = studentMapper.selectAllStudentCount();

            //并存放到redis缓存中
            redisTemplate.opsForValue().set("allStudentCount",allStudentCount,30, TimeUnit.SECONDS);
        }

        return allStudentCount;
    }
}

配置文件

#配置内嵌Tomcat端口号
server.port=8081
#设置上下文根
server.servlet.context-path=/

#设置连接数据库信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.154.128:3306/springboot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123

#设置dubbo配置
spring.application.name=024-springboot-dubbo-ssm-provider
#声明当前工程为服务提供者
spring.dubbo.server=true
#设置注册中心
spring.dubbo.registry=zookeeper://192.168.154.128:2181

#设置redis配置
spring.redis.host=192.168.154.128
spring.redis.port=6379
spring.redis.password=123456

在启动配置类中要添加以下注解
还要有包的扫描类,主要是配置mapper的

@SpringBootApplication
@MapperScan(basePackages = "com.bjpowernode.springboot.mapper")
@EnableDubboConfiguration   //开启dubbo配置
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

==接口类==
这个接口类有逆向工程生成的java类
还要书写上面的接口类

public interface StudentService {

    /**
     * 根据学生ID查询详情
     * @param id
     * @return
     */
    Student queryStudentById(Integer id);

    /**
     * 获取学生总人数
     * @return
     */
    Integer queryAllStudentCount();

}

4. springboot之非web工程

没有webapp这个工程目录了
在选定的时候
不要勾选这个选项就是非web工程,勾选了就是web工程
在这里插入图片描述

创建依赖文件

<dependencies>
    <!--SpringBoot框架非web应用起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!--SpringBoot框架测试起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

对比一下web工程的依赖文件就会显示出有很大的不同

接口类

public interface StudentService {

    /**
     * SayHello
     * @return
     */
    String sayHello();
}

接口实现类

@Service
public class StudentServiceImpl implements StudentService {
    @Override
    public String sayHello() {
        return "Say Hello";
    }
}

最后在启动类中进行配置
==第一种方式==
这种方式通过SpringApplication的run方法返回一个ConfigurableApplicationContext对象,通过这个对象获取指定的对象即可

@SpringBootApplication
public class Application {


    public static void main(String[] args) {
        /**
         * Springboot程序启动后,返回值是ConfigurableApplicationContext,它也是一个Spring容器
         * 它其实相当于原来Spring容器中启动容器ClasspathXmlApplicationContext
         */

        SpringApplication.run(Application.class, args);

        //获取Springboot容器
        ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);

        //从spring容器中获取指定bean对象
        StudentService studentService = (StudentService) applicationContext.getBean("studentServiceImpl");

        //调用业务方法
        String sayHello = studentService.sayHello();

        System.out.println(sayHello);

    }

}

这里不能使用注入对象,因为main的内部方法不可以调用实体类,需要创建另外一个方法调用,所以就是第二种方式了

==第二种方式==
通过对象注入,之后继承CommandLineRunner这个接口并且重写run实现方法
之后再run方法进行调用注入的对象
需要继承这个类,因为这个类有一些注解可以指引这些对象去使用
在这里插入图片描述

@SpringBootApplication  //开启spring配置
public class Application implements CommandLineRunner {

    @Autowired
    private StudentService studentService;

    public static void main(String[] args) {
        //SpringBoot启动程序,会初始化Spring容器
        SpringApplication.run(Application.class, args);
    }


    //重写CommandLineRunner类中的run方法
    @Override
    public void run(String... args) throws Exception {

        //调用业务方法
        String sayHello = studentService.sayHello("World");

        System.out.println(sayHello);
    }
}

5. 拓展

以下可做了解,不过还是要熟悉即可

5.1 关闭修改logo

在这里插入图片描述

关闭springboot的logo
只要通过启动类中调用一个关闭logo的方法
并且加载参数即可成功
只要将其SpringApplication.run(Application.class,args);替换为
先获取入口类,之后通过设置其属性将其关闭setBannerMode(Banner.Mode.OFF);,之后run启动参数即可

@SpringBootApplication
public class Application {

    public static void main(String[] args) {

//        SpringApplication.run(Application.class,args);

        //获取入口SpringBoot类
        SpringApplication springApplication = new SpringApplication(Application.class);

        //设置它的属性
        springApplication.setBannerMode(Banner.Mode.OFF);

        springApplication.run(args);

    }

}

如何修改logo
可通过再资源类中加入一个文本banner.txt即可
具体生成logo的网址为
https://www.bootschool.net/ascii
或 者
http://patorjk.com/software/taag/
之后正常配置启动即可

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

5.2 拦截器

具体步骤:

  • 定义一个拦截器,实现HandlerInterceptor接口
  • 创建一个配置类(在springmvc配置文件中使用mvc:interceptors标签)

拦截器的内容主要是书写拦截的内容逻辑
代码如下

public class UserInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("进入拦截器------------------------------");
        //编写业务拦截的规则
        //从session中获取用户的信息
        User user = (User) request.getSession().getAttribute("user");

        //判断用户是否登录
        if (null == user) {
            //未登录
            response.sendRedirect(request.getContextPath() + "/user/error");
            return false;
        }


        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

具体用户类如下
简单定义

public class User {

    private Integer id;

    private String username;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

最主要的配置类,相当于xml的配置文件
继承WebMvcConfigurer改写addInterceptors这个方法,实现什么类拦截什么类不拦截
addInterceptor()括号中书写用于拦截哪个类

@Configuration  //定义此类为配置文件(即相当于之前的xml配置文件)
public class InterceptorConfig implements WebMvcConfigurer {

    //mvc:interceptors
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        //要拦截user下的所有访问请求,必须用户登录后才可访问,
        // 但是这样拦截的路径中有一些是不需要用户登录也可访问的
        String[] addPathPatterns = {
            "/user/**"
        };

        //要排除的路径,排除的路径说明不需要用户登录也可访问
        String[] excludePathPatterns = {
            "/user/out", "/user/error","/user/login"
        };

        //mvc:interceptor bean class=""
        registry.addInterceptor(new UserInterceptor()).addPathPatterns(addPathPatterns).excludePathPatterns(excludePathPatterns);
    }
}

在控制层面上
具体的代码逻辑是

@Controller
@RequestMapping(value = "/user")
public class UserController {


    //用户登录的请求,需要排除
    @RequestMapping(value = "/login")
    public @ResponseBody Object login(HttpServletRequest request) {
        //将用户的信息存放到session中
        User user = new User();
        user.setId(1001);
        user.setUsername("zhangsan");
        request.getSession().setAttribute("user",user);

        return "login SUCCESS";
    }

    //该请求需要用户登录之后才可访问
    @RequestMapping(value = "/center")
    public @ResponseBody Object center() {
        return "See Center Message";
    }

    //该请求不登录也可访问
    @RequestMapping(value = "/out")
    public @ResponseBody Object out() {
        return "Out see anytime";
    }

    //如果用户未登录访问了需要登录才可访问的请求,之后会跳转至该请求路径
    //该请求路径不需要用户登录也可访问
    @RequestMapping(value = "/error")
    public @ResponseBody Object error() {
        return "error";
    }
}

开启spring的配置还是不变

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

5.3 Servlet

具体这一部分知识可看我之前的文章
java web之Servlet技术详细分析(一)

springboot下使用servlet主要有两种方式

  • 通过注解方式,主要有两个注解,第一个为路径@WebServlet,第二个为扫描路径的注解@ServletComponentScan
  • 通过配置类注册组件

两种方式代码如下
通过继承HttpServlet这个类,之后重写doGetdoPost的方法即可
==第一种方式==

@WebServlet(urlPatterns = "/myservlet")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.getWriter().println("My SpringBoot Servlet-1");
       resp.getWriter().flush();
       resp.getWriter().close();

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

配置的类为

@SpringBootApplication  //开启spring配置
@ServletComponentScan(basePackages = "com.bjpowernode.springboot.servlet")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

==第二种方式==
第二种方式不用扫描类,因为配置类会被识别到
配置类如下

@Configuration  //该注解将此类定义为配置类(相当一个xml配置文件)
public class ServletConfig {

    //@Bean是一个方法级别上的注解,主要用在配置类里
    //相当于一个
    // <beans>
    //      <bean id="" class="">
    // </beans>
    @Bean
    public ServletRegistrationBean myServletRegistrationBean() {
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new MyServlet(),"/myservlet");

        return servletRegistrationBean;
    }
}

继承的HttpServlet这个类,具体配置类在上面,跳转路径也在上面

public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().println("My SpringBoot Servlet-2");
        resp.getWriter().flush();
        resp.getWriter().close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

最后的启动配置类没变化

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

5.4 过滤器

同样和servlet也是一个道理

  • 通过注解方式,主要有两个注解,第一个为路径@WebFilter,第二个为扫描路径的注解@ServletComponentScan
  • 通过配置类注册组件

==第一种方式==
通过继承Filter这个类,之后重写doFilter方法即可

@WebFilter(urlPatterns = "/myfilter")
public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("-------------------您已进入过滤器---------------------");

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

启动类

@SpringBootApplication
@ServletComponentScan(basePackages = "com.bjpowernode.springboot.filter")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

==第二种方式==
配置类为
以下的配置类过滤的时候只能是一个*
而上面的拦截器需要两个,因为作用域不同,两个代表还有其他的子目录或者子路径等

@Configuration  //定义此类为配置类
public class FilterConfig {

    @Bean
    public FilterRegistrationBean myFilterRegistrationBean() {

        //注册过滤器
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());

        //添加过滤路径
        filterRegistrationBean.addUrlPatterns("/user/*");

        return filterRegistrationBean;
    }
}

设置的过滤器类为

public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("-------------------您已进入过滤器-222-------------------");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

在界面控制层面的代码跳转如下

@Controller
public class UserController {


    @RequestMapping(value = "/user/detail")
    public @ResponseBody String userDetail() {
        return "/user/detail";
    }

    @RequestMapping(value = "/center")
    public @ResponseBody String center() {
        return "center";
    }

}

启动配置类不变

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

5.5 字符编码

因为中文会有乱码,不一样的语言显示也会有乱码所以要统一格式

同样也是两种方式

  • 使用 CharacterEncodingFilter
  • springboot字符编码设置

==第一种方式==
同样也是继承HttpServlet,改写两个方法
并且在这其中加入不一样的浏览器识别的话,统一编码格式setContentType("text/html;character=utf-8");

@WebServlet(urlPatterns = "/myservlet")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().println("世界您好,Hello World!");
        //统一设置浏览器编码格式
        resp.setContentType("text/html;character=utf-8");
        resp.getWriter().flush();
        resp.getWriter().close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

配置一个字符编码的配置类

@Configuration  //将此类定义为配置文件
public class SystemConfig {

    @Bean
    public FilterRegistrationBean characterEncodingFilterRegistrationBean() {

        //创建字符编码过滤器
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        //设置强制使用指定字符编码
        characterEncodingFilter.setForceEncoding(true);
        //设置指定字符编码
        characterEncodingFilter.setEncoding("UTF-8");


        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();

        //设置字符编码过滤器
        filterRegistrationBean.setFilter(characterEncodingFilter);
        //设置字符编码过滤器路径
        filterRegistrationBean.addUrlPatterns("/*");

        return filterRegistrationBean;
    }
}

启动的类要加入一个扫描的包名

@SpringBootApplication
@ServletComponentScan(basePackages = "com.bjpowernode.springboot.servlet")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

==第二种方式==
主要是在配置文件中设置过滤即可
主要的代码如下

@WebServlet(urlPatterns = "/myservlet")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("世界您好,Hello World!");
        resp.setContentType("text/html;character=utf-8");
        resp.getWriter().flush();
        resp.getWriter().close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

启动类

@SpringBootApplication
@ServletComponentScan(basePackages = "com.bjpowernode.springboot.servlet")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

区别在于这个
多一个配置
配置在application.properties

#设置请求响应字符编码
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.http.encoding.charset=utf-8

5.6 springboot打包部署

控制层面的类名
跳转的jsp页面不需要使用@ResponseBody,使用model进行传入参数

@Controller
public class UserController {


    @RequestMapping(value = "/user/detail")
    public @ResponseBody Object userDetail() {

        Map<String,Object> retMap = new HashMap<String, Object>();
        retMap.put("id",1001);
        retMap.put("username","lisi");

        return retMap;
    }
    
    @RequestMapping(value = "/user/page/detail")
    public String userPageDetail(Model model) {
        model.addAttribute("id",1001);
        model.addAttribute("username","wangwu");
        return "userDetail";
    }
}

因为有用到jsp的界面,所以需要使用jsp的依赖

<!--SpringBoot内嵌Tomcat解析jsp的依赖-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

而且还要配置web工程的目录

<resources>
    <resource>
        <directory>src/main/webapp</directory>
        <targetPath>META-INF/resources</targetPath>
        <includes>
            <include>*.*</include>
        </includes>
    </resource>

    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/*.*</include>
        </includes>
    </resource>
</resources>

配置了jsp的配置也要记得在软件中设置web工程
配置的jsp页面为

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h3>用户编码:${id}</h3>
<h3>用户姓名:${username}</h3>
</body>
</html>

springboot集成的jsp配置文件为application.properties

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

==设置成war包的打包部署==

<!--修改打包方式-->
<packaging>war</packaging>

src/main/resources 下的所有配置文件编译到 classes 下面去
不加这个的话,springboot下的application.properties不会被编译到
类似之前那个mapper,不加就不会被编译到内路径

<resource>
 <directory>src/main/resources</directory>
 <includes>
 <include>**/*.*</include>
 </includes>
</resource>
<!--指定打war包的字符-->
<finalName>springboot</finalName>

<!--编译的打包插件-->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

最主要的是在配置启动类中继承 SpringBootServletInitializer类并覆
盖 configure 方法

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {

        //参数为当前springboot启动类
        //构造新资源
        return builder.sources(Application.class);
    }
}

之后通过package中的clean以及package进行打包
将其复制到tomcat中的webapps目录中,并启动bin目录下的startup.bat启动,即可通过浏览器输入url进行访问

==设置成jar包的打包部署==
在打包到war包的时候,部署到tomcat中,之前在application.properties设置的上下文根和端口号就失效了,以本地的为路径
在打包jar包的时候,本身默认是打包jar包,端口号和上下文根本身就是springboot核心配置文件中设置的值

server.port=9090
server.servlet.context-path=/

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

默认打包的jar包是内嵌tomcat,默认打包插件的版本不能使用,需要更换为

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>1.4.2.RELEASE</version>
</plugin>

修改jar包的名字可在build下的 <finalName>springboot</finalName>
之后将jar包放到某一个目录中
使用cmd的命令行编译
执行java -jar springboot.jar 即可

==总结==
jar包和war包的部署方式不同,启动的方式也不同

6. 集成logback日志

  • 创建 SpringBoot 框架 web 项目
  • 添加 SSM 需要的依赖

MyBatis 集成 SpringBoot 框架的起步依赖
连接 MySQL 的驱动

  • 集成 SSM 在 application.properties 的配置
  • 通过 MyBatis 逆向工程生成 DAO

编写接口与实现类
在数据的访问层中进行映射

<!--获取学生总人数-->
<select id="selectStudentCount" resultType="java.lang.Integer">
    select count(*) from t_student
</select>

以上都是基于上面学习总结后的代码,现在是添加日志代码
配置文件名为 logback-spring.xml 的日志配置文件,放在 src/main/resources 下,也可以在application.yml 通过 logging.config 属性指定自
定义的名字

logging.config=classpath:logging-config.xml

logback-spring.xml 的文件配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为 TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果
设置为 WARN,则低于 WARN 的信息都不会输出 -->
<!-- scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为
true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认
单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为 1 分钟。 -->
<!-- debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback
运行状态。默认值为 false。通常不打印 -->
<configuration scan="true" scanPeriod="10 seconds">
    <!--输出到控制台-->
    <appender name="CONSOLE"
              class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志 appender 是为开发使用,只配置最底级别,控制台输出的日志级别是大
       于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <Pattern>%date [%-5p] [%thread] %logger{60}
                [%file : %line] %msg%n</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--<File>/home/log/stdout.log</File>-->
        <File>D:/log/stdout.log</File>
        <encoder>
            <pattern>%date [%-5p] %thread %logger{60}
                [%file : %line] %msg%n</pattern>
        </encoder>
        <rollingPolicy
                class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 添加.gz 历史日志会启用压缩 大大缩小日志文件所占空间 -->

            <!--<fileNamePattern>/home/log/stdout.log.%d{yyyy-MM-dd}.log</fileNam
            ePattern>-->

            <fileNamePattern>D:/log/stdout.log.%d{yyyy-MM-dd}.log</fileNamePatter
                    n>
            <maxHistory>30</maxHistory><!-- 保留 30 天日志 -->
        </rollingPolicy>
    </appender>
    <logger name="com.abc.springboot.mapper" level="DEBUG" />
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

如果要在终端中显示输出的语句
可以通过日志进行
需要添加如下依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

之后调用其函数

log.trace("查询当前学生总人数");
log.debug("查询当前学生总人数");
log.info("查询当前学生总人数");
log.warn("查询当前学生总人数");
log.error("查询当前学生总人数");

输出的语句只有低于这个的权限才会输出
如果root标签指定的日志级别那么以根日志级别为准,如果没有则已当前追加器日志级别为准
在这里插入图片描述

启动类的配置

@SpringBootApplication
@MapperScan(basePackages = "com.bjpowernode.springboot.mapper")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

==补充==
1.

位置 日志级别
appender trace
root trace

最后输出使用的是 trace

2.

位置 日志级别
appender trace
root debug

最后输出使用的是 debug

3.

位置 日志级别
appender trace
root

如果root没有值默认root级别是debug
最后输出使用的是 debug

4.

位置 日志级别
appender debug
root info

最后输出使用的是 info

7. SpringBoot集成Thymeleaf

详情可看这篇文章进行阅读
SpringBoot集成Thymeleaf从入门到精通(全)

8. 实战综合案例

主要是这四个工程
有父类工程,主要是用来管理依赖包,依赖包的版本号
接口,消费者,生产者工程主要是dubbo

8.1 父类工程

在创建父类工程的时候是使用maven,生成的父类依赖
要给每个包都复制一份
类似这种

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

父类工程管理的依赖包版本号

<properties>
    <java.version>1.8</java.version>
    <dubbo-spring-boot-starter-version>2.0.0</dubbo-spring-boot-starter-version>
    <zkclient.version>0.10</zkclient.version>
    <mybatis-spring-boot-starter-version>2.0.0</mybatis-spring-boot-starter-version>
</properties>

<!--管理SpringBoot父工程没有管理的依赖-->
<dependencyManagement>
    <dependencies>

        <!--Dubbo集成SpringBoot框架起步依赖-->
        <dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo-spring-boot-starter-version}</version>
        </dependency>

        <!--zookeeper注册中心-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>${zkclient.version}</version>
        </dependency>

        <!--MyBatis集成Springboot框架起步依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis-spring-boot-starter-version}</version>
        </dependency>

    </dependencies>
</dependencyManagement>

8.2 接口工程

接口类

public interface StudentService {

    /**
     * 根据学生ID查询详情
     * @param id
     * @return
     */
    Student queryStudentById(Integer id);
}

以及逆向工程生成的类放到这里

public class Student implements Serializable {
    private Integer id;

    private String name;

    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

8.3 提供者工程

在依赖文件中要放置 dubbo,zookeeper,mybatis,mysql,redis,接口工程

<dependencies>
    <!--SpringBoot框架web项目起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--Dubbo集成SpringBoot框架起步依赖-->
    <dependency>
        <groupId>com.alibaba.spring.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>

    <!--zookeeper注册中心-->
    <dependency>
        <groupId>com.101tec</groupId>
        <artifactId>zkclient</artifactId>
    </dependency>

    <!--MySQL驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <!--MyBatis集成Springboot框架起步依赖-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>

    <!--SpringBoot集成Redis起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <!--接口工程,自己创建的java工程的依赖版本号不需要由父工程再次管理-->
    <dependency>
        <groupId>com.bjpowernode.springboot</groupId>
        <artifactId>051-springboot-dubbo-ssm-interface</artifactId>
        <version>1.0.0</version>
    </dependency>

</dependencies>

以及存储位置的地方放置

<build>

    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
    </resources>

此处还涉及逆向工程要放置的mapper
所以先要弄逆向工程的GeneratorMapper.xml
所以在依赖文件中也要提前配置好

<plugins>

    <!--mybatis 代码自动生成插件-->
    <plugin>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.6</version>
        <configuration>
            <!--配置文件的位置-->
            <configurationFile>GeneratorMapper.xml</configurationFile>
            <verbose>true</verbose>
            <overwrite>true</overwrite>
        </configuration>
    </plugin>

实现接口实现类

@Component
@Service(interfaceClass = StudentService.class,version="1.0.0",timeout = 15000)
public class StudentServiceImpl implements StudentService {

    @Autowired
    private StudentMapper studentMapper;

    @Override
    public Student queryStudentById(Integer id) {
        return studentMapper.selectByPrimaryKey(id);
    }
}

如果需要添加什么数据库的修改还需要在该xml文件中加入数据库的编辑
在这里插入图片描述
还要添加其配置application.properties

#设置内嵌Tomcat端口号
server.port=8081
#设置上下文根
server.servlet.context-path=/

#设置连接数据库信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.154.128:3306/springboot?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123

#设置dubbo配置
spring.application.name=052-springboot-dubb-ssm-provider
#设置当前工程为服务提供者
spring.dubbo.server=true
#指定注册中心
spring.dubbo.registry=zookeeper://192.168.154.128:2181

#设置redis配置
spring.redis.host=192.168.154.128
spring.redis.port=6379
spring.redis.password=123456

配置启动类
因为有mapper所以要扫描这个包

@SpringBootApplication
@MapperScan(basePackages = "com.bjpowernode.springboot.mapper")
@EnableDubboConfiguration   //开启dubbo配置
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

8.4 消费者工程

需要在依赖文件中添加如下配置dubbo,zookeeper,thymeleaf,接口工程

<dependencies>
    <!--SpringBoot框架集成thymeleaf前端模版引擎起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!--SpringBoot框架web项目起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--Dubbo集成Springboot框架起步依赖-->
    <dependency>
        <groupId>com.alibaba.spring.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
    </dependency>

    <!--zookeeper注册中心-->
    <dependency>
        <groupId>com.101tec</groupId>
        <artifactId>zkclient</artifactId>
    </dependency>

    <!--接口工程-->
    <dependency>
        <groupId>com.bjpowernode.springboot</groupId>
        <artifactId>051-springboot-dubbo-ssm-interface</artifactId>
        <version>1.0.0</version>
    </dependency>

</dependencies>

添加其配置application.properties

#设置内嵌tomcat端口号
server.port=8080
server.servlet.context-path=/

#设置dubbo配置
spring.application.name=053-springboot-dubbo-ssm-consumer
spring.dubbo.registry=zookeeper://192.168.154.128:2181

#关闭页面缓存
spring.thymeleaf.cache=false

#设置thymeleaf前/后缀
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

#设置字符编码
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8

根据学生查询的id以及代码等

@Controller
public class StudentController {

    @Reference(interfaceClass = StudentService.class,version = "1.0.0",check = false)
    private StudentService studentService;

    @RequestMapping(value = "/student/detail/{id}")
    public String studentDetail(Model model,
                                @PathVariable("id") Integer id) {

        //根据学生ID查询详情
        Student student = studentService.queryStudentById(id);

        model.addAttribute("student",student);

        return "studentDetail";
    }
}

前后端传输数据的页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>学生详情</title>
</head>
<body>
学生编号:<span th:text="${student.id}"></span><br/>
学生姓名:<span th:text="${student.name}"></span><br/>
学生年龄:<span th:text="${student.age}"></span><br/>
</body>
</html>

配置启动类

@SpringBootApplication
@EnableDubboConfiguration   //开启dubbo配置
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
相关文章
|
SQL Java 数据库连接
SpringBoot从入门到精通(二十七)JPA实现自定义查询,完全不需要写SQL!
前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增、删、改、查的功能。JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现完整的数据操作方法。 JPA除了这些功能和优势之外,还有非常强大的查询的功能。以前复查的查询都需要拼接很多查询条件,JPA 有非常方便和优雅的方式来解决
SpringBoot从入门到精通(二十七)JPA实现自定义查询,完全不需要写SQL!
|
前端开发 NoSQL Java
SpringBoot从入门到精通(二十)快速构建Restful Web API 服务
随着互联网化等逐渐深入,应用系统也变得越来越复杂,系统架构正在朝着微服务化,中台化的方向发展。这就需要各个系统、各个厂家之间的数据频繁交互。所以,使用 Restful 风格构建的应用接口适用于移动互联网厂商的业务场景,正在被越来越多的企业推荐使用。那么什么是 RESTful 呢?
SpringBoot从入门到精通(二十)快速构建Restful Web API 服务
|
SQL Java 关系型数据库
SpringBoot从入门到精通(三十)如何使用JdbcTemplate操作数据库?
前面介绍了Mybatis数据持久化框架,Mybatis虽然功能强大,但是,使用起来还是比较复杂的。所以接下来介绍一个简单的数据持久化框架——JdbcTemplate。
10138 2
SpringBoot从入门到精通(三十)如何使用JdbcTemplate操作数据库?
|
SQL 架构师 Java
SpringBoot从入门到精通(二十八) JPA 的实体映射关系,轻松一对一,一对多,多对多关系映射!
前面讲了Spring Boot 使用 JPA,实现JPA 的增、删、改、查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用。JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层和sql语句即可实现完整的数据操作方法。但是,之前都是介绍的单表的增删改查等操作,多表多实体的数据操作怎么实现呢?接下来聊一聊 JPA 的一对一,一对多,多对一,多对多等实体映射关系。
SpringBoot从入门到精通(二十八) JPA 的实体映射关系,轻松一对一,一对多,多对多关系映射!
|
JSON 算法 安全
SpringBoot从入门到精通(三十四)如何集成JWT实现Token验证
近年来,随着前后端分离、微服务等架构的兴起,传统的cookie+session身份验证模式已经逐渐被基于Token的身份验证模式取代。接下来介绍如何在Spring Boot项目中集成JWT实现Token验证。
SpringBoot从入门到精通(三十四)如何集成JWT实现Token验证
|
XML 缓存 前端开发
SpringBoot集成Thymeleaf从入门到精通(全)
目录SpringBoot集成Thymeleaf1. 关闭缓存2. 表达式3. 常用属性4. 遍历元素5. 条件判断6. 字面量7. 字符串拼接8. 数学运算 SpringBoot集成Thymeleaf Thymeleaf 是一个流行的模板引擎,该模板引擎采用 Java 语言开发 Thymeleaf 是另外的一种模板技术,它本身并不属于 Spring Boot,Spring Boot只是很好地集成这种模板技术,作为前端页面的数据展示 在创建模板的时候还需要多选择一个这个 之后默认会自动添加这些依赖 Sp
153 0
SpringBoot集成Thymeleaf从入门到精通(全)
|
存储 缓存 负载均衡
SpringBoot从入门到精通(二十九)使用Redis实现分布式Session共享
前面介绍了Spring Boot如何使用Redis缓存。接下来从项目实战出发,介绍使用Redis实现Session共享。 在分布式或微服务系统中,会出现这样一个问题:用户在服务器A上登录以后,假如后续的业务操作被负载均衡服务转发到服务器B上面,服务器B上没有这个用户的Session状态,就会强制让用户重新登录,导致业务无法顺利完成。因此,这就需要将Session进行共享,保证每个系统都能获取用户的Session状态。
SpringBoot从入门到精通(二十九)使用Redis实现分布式Session共享
|
前端开发 JavaScript Java
SpringBoot从入门到精通(三十三)Spring Boot项目打包,实现静态文件、配置文件与jar分离!
前面介绍了Spring Boot项目的打包、发布和部署。我们知道Spring Boot打包时,默认是会把resource目录下的静态资源文件和配置文件统一打包到jar文件中。这样部署到生产环境中一旦需要修改配置文件,则非常麻烦。
SpringBoot从入门到精通(三十三)Spring Boot项目打包,实现静态文件、配置文件与jar分离!
|
SQL Java 测试技术
SpringBoot从入门到精通(二十八)JPA 的实体映射关系,一对一,一对多,多对多关系映射!
前面讲了Spring Boot 使用 JPA,实现JPA 的增、删、改、查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用。JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层和sql语句即可实现完整的数据操作方法。但是,之前都是介绍的单表的增删改查等操作,多表多实体的数据操作怎么实现呢?接下来聊一聊 JPA 的一对一,一对多,多对一,多对多等实体映射关系。
SpringBoot从入门到精通(二十八)JPA 的实体映射关系,一对一,一对多,多对多关系映射!
|
SQL 架构师 NoSQL
SpringBoot从入门到精通(二十六)超级简单的数据持久化框架!Spring Data JPA 的使用!
Spring Data JPA 是Spring Data框架下的一个基于JPA标准操作数据的模块,简化了操作持久层的代码,只需要编写接口就可以。如果你是第一次使用 Spring Data JPA ,你一定会惊呼这东西简直就是神器,几乎不需要写什么关于数据库访问的代码一个基本的 CURD 的功能就出来了。使用非常简单方便,下面我们就来讲述 JPA 使用的基本操作。
SpringBoot从入门到精通(二十六)超级简单的数据持久化框架!Spring Data JPA 的使用!