SpringBoot学习笔记

1. SpringBoot框架概述

SpringBoot是对于SSM开发的一个简化,应用SpringBoot可以使我们从繁琐的写依赖、写配置的枷锁中解放出来。

它的优点有:

  1. 能够快速创建基于Spring的应用程序
  2. 能够直接使用java main方法启动内嵌的tomcat服务器运行SpringBoot程序,省去部署步骤
  3. 提供约定好的starter pom来简化Maven设置
  4. 自动化配置,根据项目的Maven依赖配置,自动配置Spring,SpringMVC等
  5. 提供了程序的健康检查等功能
  6. 基本可以不使用XML配置文件,采用注解配置

2. SpringBoot入门案例

2.1 如何创建一个SpringBoot项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
建立目录结构,创建一个处理器类:

package com.example.springboot.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class IndexController {

    @RequestMapping("/SpringBoot/say")
    @ResponseBody
    public String say() {
        return "Hello SpringBoot";
    }
}

启动入口类,访问该地址即可。

2.2 核心配置文件application.properties

在此配置文件中,可用Key=Value的方式配置端口号、上下文路径等

#配置端口号
server.port=8080

#配置上下文路径
server.servlet.context-path=/springboot

则此时的访问变成了:http://localhost:8080/springboot/SpringBoot/say

配置文件以.yml或.yaml结尾也是可以的。如果与.properties的配置文件同时存在,以.properties为优先。

如果有多个以.properties结尾的配置文件,如application-xxx.properties,则在主核心配置文件application.properties中用spring.profiles.active=xxx的方式指定生效的配置文件。.yml同理

2.3 核心配置文件自定义配置

乱码问题:最好不要出现中文,如果有,则在idea-settings-editor-file encodings中勾选transparent native-to-ascii conversion即可

2.3.1 单独获取自定义配置

在核心配置文件中自定义的值,在需要该值的类中通过@Value注解就可以拿到:

#自定义配置
school.name=wuhandaxue
package com.example.springboot.web;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class IndexController {
    @Value("${school.name}")
    private String schoolName;

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

2.3.2 将自定义配置映射为对象获取

要求:需要有统一的前缀

通过@Component将类交给Spring容器管理后,通过@ConfigurationProperties(prefix=“前缀”)注解获取配置文件中的自定义配置,然后通过@Resource/@Autowired自动注入:

#自定义配置
school.name=wuhandaxue
school.city=wuhan

类:

package com.example.springboot.domain;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "school")
public class School {
    private String name;
    private String city;

    public String getName() {
        return name;
    }

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

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

控制器:

package com.example.springboot.controller;

import com.example.springboot.domain.School;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
public class IndexController {
    @Resource
    private School school;

    @RequestMapping("/say")
    @ResponseBody
    public String say() {
        return "Hello" + school.getName() + "in" + school.getCity();
    }
}

两种获取方式可以同时使用。

@ConfigurationProperties可能会触发红色警告框,加入如下依赖即可解决:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>

2.4 SpringBoot集成jsp

SpringBoot默认推荐使用的是thymeleaf,那如果要集成jsp的话,需要手动创建webapp文件夹,然后在模块设置中:
在这里插入图片描述
webapp文件夹多了一个蓝点即为成功,再加入jsp的解析依赖(仅支持展现功能)

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

继续在pom.xml的build标签中手动指定jsp编译的路径(springboot已规定为META-INF/resources):

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

对于jsp,我们还需要配置视图解析器来解析

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

之后jsp文件就像以前一样放在webapp中,正常步骤开发
控制器类:

package com.example.springboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class IndexController {

    @RequestMapping("/say")
    public ModelAndView say() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "HelloJsp");
        mv.setViewName("show");
        return mv;
    }
}

jsp:

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/6/7
  Time: 21:48
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

3. SpringBoot的Web开发

3.1 集成Mybatis

通过mybatis提供的逆向工程xml文件和插件,来通过添加的数据库数据反向生成dao和domain(在添加依赖之前)

添加mybatis集成springboot依赖和mysql驱动

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.0.0</version>
		</dependency>

加入数据到数据库

逆向工程配置文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!--指定连接数据库的JDBC 驱动包所在位置,指定到你本机的完整路径-->
    <classPathEntry location="D:\work\maven_work\repository\mysql\mysql-connector-java\8.0.25\mysql-connector-java-8.0.25.jar"/>
    <!--配置table表信息内容体,targetRuntime 指定采用MyBatis3的版本-->
    <context id="tables" targetRuntime="MyBatis3">
        <!--抑制生成注释,由于生成的注释都是英文的,属性设置为true可以不让它生成-->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--配置数据库连接信息-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT"
                        userId="root"
                        password="root">
            <property name="nullCatalogMeansCurrent" value="true"/>

        </jdbcConnection>

        <!--生成model 类,targetPackage 指定 model 类的包名,targetProject 指定
        生成的 model放在eclipse的哪个工程下面-->
        <javaModelGenerator targetPackage="com.example.springboot.model"
                            targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
            <property name="trimStrings" value="false"/>
        </javaModelGenerator>
        <!--生成 MyBatis的Mapper.xml文件,targetPackage 指定 mapper.xml文件的包名,targetProject 指定生成的 mapper.xml放在 eclipse的哪个工程下面
        -->
        <sqlMapGenerator targetPackage="com.example.springboot.mapper"
                         targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!--生成 MyBatis的 Mapper接口类文件,targetPackage 指定 Mapper 接口类的包名,targetProject 指定生成的 Mapper 接口放在eclipse 的哪个工程下面
        -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.example.springboot.mapper"
                             targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!--数据库表名及对应的Java模型类名-->
        <table tableName="t_Student" domainObjectName="Student"
               enableCountByExample="false"
               enableUpdateByExample="false"
               enableDeleteByExample="false"
               enableSelectByExample="false"
               selectByExampleQueryId="false" />
        <!--
                <table tableName="user" domainObjectName="User"
                       enableCountByExample="false"
                       enableUpdateByExample="false"
                       enableDeleteByExample="false"
                       enableSelectByExample="false"
                       selectByExampleQueryId="false" />-->
    </context>
</generatorConfiguration>

逆向工程插件:

			<!--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>

然后点击右侧Maven工具栏的生成按钮即可
在这里插入图片描述
编写Controller和Service,记得在mapper接口中加入@Mapper注解或选择在入口方法上加入@MapperScan,其属性指定mapper接口所在包

在核心配置文件中配置数据库连接四要素即可开启服务

3.2 事务支持

在service方法上加@Transactional注解即可

3.3 SpringBoot与SpringMVC

继承springmvc的常用注解:

  1. @RestController
    = @Controller + @ResponseBody
  2. @GetMapping
    = @RequestMapping(method = RequestMethod.GET)
  3. @PostMapping
    = @Controller(method = RequestMethod.POST)
  4. @PutMapping
    = @Controller(method = RequestMethod.PUT)
  5. @DeleteMapping
    = @Controller(method = RequestMethod.DELETE)

3.4 实现RESTful

RESTful:一个关于路径设计的风格,路径中加入参数,如
@RequestMapping(value = “/student/detail/{id}/{age}”)

3.5 集成Redis

添加springboot集成redis的起步依赖

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

编写控制器类

package com.example.springboot.web;

import com.example.springboot.service.StudentService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
public class StudentController {
    @Resource
    private StudentService studentService;

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

        studentService.put(key, value);

        return "数据插入成功!";
    }

    @RequestMapping("/get")
    @ResponseBody
    public Object get(String key) {
        String value = studentService.get(key);

        return "键-" + key + ",值-" + value;
    }
}

编写业务方法

package com.example.springboot.service.impl;

import com.example.springboot.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class StudentServiceImpl implements StudentService {
    /*
    使用spring集成redis起步依赖提供的redis模板对象来操作redis数据类型,它是一个键值对类型,
    泛型的key和value需要都写Object
     */
    @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) {
        return (String) redisTemplate.opsForValue().get(key);
    }
}

在核心配置文件中配置redis数据库的连接信息

#设置redis配置信息
spring.redis.host=192.168.230.128
spring.redis.port=6379

3.6 集成Dubbo

3.6.1 公共包

实体类

package model;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String name;

    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;
    }
}

业务接口

package service;

import model.User;

public interface UserService {
    User queryUserById(Integer id);
}

3.6.2 生产者

依赖

与Maven Dubbo项目不同,需额外注意

		<dependency>
			<groupId>org.example</groupId>
			<artifactId>007-springboot-dubbo-interface</artifactId>
			<version>1.0-SNAPSHOT</version>
		</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>

接口实现类

dubbo和springboot集成后,没有了可以自定义的dubbo核心配置文件,也就无法自定义实体bean,所以需要在接口实现类中使用注解@Component的方式将其交给容器管理,不能使用@Service的原因是与后面要使用的一个同名注解冲突,所以使用@Component代替

package com.example.dubbo.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import model.User;
import org.springframework.stereotype.Component;
import service.UserService;

@Component
/*
使用alibaba.dubbo提供的注解@Service来进行自身的暴露,
属性interface, version, timeout不能少,
就如同dubbo项目中的配置文件一样
<dubbo:service interface="service.UserService" ref="userServiceImpl" version="1.0.0" timeout="15000"/>
 */
@Service(interfaceClass = UserService.class, version = "1.0.0", timeout = 15000)
public class UserServiceImpl implements UserService {
    @Override
    public User queryUserById(Integer id) {
        User user = new User();
        user.setName("池田依来沙");
        user.setId(id);

        return user;
    }
}

核心配置文件

在核心配置文件中,生产者需要走三步:声明自身、声明注册中心、表明自身身份。

而声明注册中心和暴露自身的语句都没有idea的自动补全,需要熟记

#设置端口号和上下文根
#此步设置是必须的,因为后面要同时启动两个tomcat,如果不改端口号,势必会冲突
server.port=8081
server.servlet.context-path=/

#设置dubbo
#声明自己
spring.application.name=008-springboot-dubbo-provider
#声明注册中心
spring.dubbo.registry=zookeeper://localhost:2181
#表明自身身份
spring.dubbo.server=true

3.6.3 消费者

依赖

		<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>org.example</groupId>
			<artifactId>007-springboot-dubbo-interface</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

控制器方法

package com.example.dubbo.web;

import com.alibaba.dubbo.config.annotation.Reference;
import model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import service.UserService;

@Controller
public class UserController {

    /*
    没有配置文件声明实体bean,控制器方法也就不能使用@Autowired/@Resource来进行自动赋值了,
    需要使用alibaba.dubbo提供的注解@Reference来指明引用,
    属性interface, version, check不能少,
    就如同dubbo项目中的配置文件一样
    <dubbo:reference id="userService" interface="service.UserService" version="1.0.0" check="false"/>
     */
    @Reference(interfaceClass = UserService.class, version = "1.0.0", check = false)
    private UserService userService;

    @RequestMapping("/userDetail")
    @ResponseBody
    public Object userDetail(Integer id) {
        User user = userService.queryUserById(id);
        return "res" + user;
    }
}

核心配置文件

#配置dubbo
#声明自己
spring.application.name=009-springboot-dubbo-consumer
#声明注册中心
spring.dubbo.registry=zookeeper://localhost:2181

3.6.4 启动入口方法

因为在dubbo集成springboot项目中使用了多种dubbo提供的注解,而入口方法默认提供的注解@SpringBootApplication只能对springboot注解生效,所以我们需要在入口方法上加入专门使dubbo注解生效的@EnableDubboConfiguration,来开启dubbo配置。

生产者和消费者都需要。

package com.example.dubbo;

import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubboConfiguration //用于开启dubbo的注解和配置
public class Application {

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

}

3.7 springboot-dubbo-redis-mybatis大集合

配合逆向工程文件和逆向插件,来生成实体类和dao层

3.7.1 公共包

实体类由逆向工程自动生成

实体类

package com.example.springboot.model;

import java.io.Serializable;

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;
    }
}

业务接口

package com.example.springboot.service;

import com.example.springboot.model.Student;

public interface StudentService {
    Student queryStudentById(Integer id);

    int getStudentCount();
}

3.6.2 生产者

依赖

与Maven Dubbo项目不同,需额外注意

既然是大集合,就需要有springboot起动依赖, dubbo, redis, mybatis, mysql驱动, zookeeper和公共包接口依赖,因为了dao层的xml映射文件,所以还需要扫描插件告诉idea将其一同编译到classes中去。

	<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>

		<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>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.0.0</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

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

		<dependency>
			<groupId>org.example</groupId>
			<artifactId>010-springboot-dubbo-redis-ssm-interface</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
	</dependencies>

	<build>
		<resources>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.xml</include>
					<include>**/*.properties</include>
				</includes>
				<filtering>false</filtering>
			</resource>
		</resources>
		<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>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

接口实现类

@Resource和@Autowired都可以

package com.example.springboot.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.example.springboot.mapper.StudentMapper;
import com.example.springboot.model.Student;
import com.example.springboot.service.StudentService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

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

    @Resource
    private RedisTemplate<Object, Object> redisTemplate;

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

    @Override
    public int getStudentCount() {
        //首先去redis缓存中查询,redis中没有再去数据库查,然后放到redis中
        Integer totalCount = (Integer) redisTemplate.opsForValue().get("count");
        if (totalCount == null) {
            totalCount = studentMapper.getStudentTotalCount();

            //可选择设置数据存活时间
            redisTemplate.opsForValue().set("totalCount", totalCount, 15, TimeUnit.SECONDS);
        }

        return totalCount;
    }
}

核心配置文件

redis在linux中启动,所以ip为linux的

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

#设置dubbo
spring.application.name=011-springboot-dubbo-redis-ssm-provider
spring.dubbo.server=true
spring.dubbo.registry=zookeeper://localhost:2181

#设置mybatis
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=GMT
spring.datasource.username=root
spring.datasource.password=root

#设置redis
spring.redis.host=192.168.230.128
spring.redis.port=6379

3.6.3 消费者

消费者则需要springboot起动依赖, dubbo, zookeeper, jsp展现和公共包接口依赖。同时需要告诉idea将jsp文件一同编译到classes中去,所以需要编译的插件

依赖

	<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>

		<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>org.example</groupId>
			<artifactId>010-springboot-dubbo-redis-ssm-interface</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>


	</dependencies>

	<build>
		<resources>
			<resource>
				<!--源文件夹-->
				<directory>src/main/webapp</directory>
				<!--指定编译到META-INF/resources-->
				<targetPath>META-INF/resources</targetPath>
				<!--指定哪个资源需要编译-->
				<includes>
					<include>*.*</include>
				</includes>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

控制器方法

package com.example.springboot.web;

import com.alibaba.dubbo.config.annotation.Reference;
import com.example.springboot.model.Student;
import com.example.springboot.service.StudentService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

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

    @RequestMapping("/student")
    public String studentDetail(Model model, Integer id) {
        Student student = studentService.queryStudentById(id);

        model.addAttribute("student", student);

        return "studentDetail";
    }

    @RequestMapping("/studentCount")
    @ResponseBody
    public Object studentCount(Model model) {
        int count = studentService.getStudentCount();

        return "总人数:" + count;
    }
}

核心配置文件

#设置dubbo
spring.application.name=012-springboot-dubbo-redis-ssm-consumer
spring.dubbo.registry=zookeeper://localhost:2181

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

3.6.4 启动入口方法

生产者

@MapperScan用来统一扫描mapper包,就不用在mapper接口一个个加了。

package com.example.springboot;

import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

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

}

消费者

package com.example.springboot;

import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubboConfiguration
public class Application {

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

}

4. SpringBoot非Web应用程序

本章了解即可。

4.1 第一种方法

在springboot程序启动后,会返回一个spring容器ConfigurableApplicationContext,类似于以前的spring容器ClasspathXmlApplicationContext。

可在入口方法中声明它,来获得容器中的bean

ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);

StudentService service = (StudentService)applicationContext.getBean("studentServiceImpl");

4.2 第二种方法

通过实现CommandLineRunner接口的方式来执行

@SpringBootApplication
@EnableDubboConfiguration
public class Application implements CommandLineRunner {

	@Resource
	private StudentService studentService;

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

	@Override
	public void run(String... args) throws Exception {
		studentService.method();
	}
}

5. SpringBoot使用拦截器

手写拦截器实现HandlerInterceptor接口,由于在springboot中无法配置拦截器,代替它的是创建拦截器配置类并在其类名上加入@Configuration注解使其相当于一个xml配置文件,再实现WebMvcConfigurer接口,重写它的addInterceptors方法。

addInterceptors方法自带一个形参InterceptorRegistry,使用形参的addInterceptor()方法来注册拦截器和拦截路径

实体类

package com.example.springboot.model;

public class User {
    private Integer id;
    private String name;

    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;
    }
}

拦截器类

package com.example.springboot.interceptor;

import com.example.springboot.model.User;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        User user = (User) request.getSession().getAttribute("user");
        if (user == null) {
            response.sendRedirect(request.getContextPath() + "/user/login");
            return false;
        }

        return true;
    }
}

拦截器配置类

package com.example.springboot.config;

import com.example.springboot.interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/*
由于在springboot中无法配置拦截器,
代替它的是创建拦截器配置类并在其类名上加入@Configuration注解使其相当于一个xml配置文件,
再实现WebMvcConfigurer接口,重写它的addInterceptors方法。

addInterceptors方法自带一个形参InterceptorRegistry,
使用形参的addInterceptor()方法来注册拦截器和拦截路径
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    //类似于配置文件中的<mvc:interceptors>
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //要拦截的路径
        String[] addPathPatterns = {"/user/**"};

        //要放行的路径,多个路径以,隔开
        String[] excludePathPatterns = {"/user/login"};

        //类似于<bean class="handler.Interceptor"/>
        registry.addInterceptor(new MyInterceptor()).addPathPatterns(addPathPatterns).excludePathPatterns(excludePathPatterns);
    }
}

控制器

package com.example.springboot.web;

import com.example.springboot.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

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

    @RequestMapping("/login")
    @ResponseBody
    public Object login(HttpServletRequest request) {
        User user = new User();
        user.setId(1001);
        user.setName("池田依来沙");

        request.getSession().setAttribute("user", user);

        return "login success!";
    }

    @RequestMapping("/center")
    @ResponseBody
    public Object center() {
        return "access to center!";
    }
}

6. SpringBoot使用Servlet

本章了解即可。

第一种方式:

自定义一个servlet继承HttpServlet,重写doGet(), doPost()方法,在类上加入@WebServlet注解,属性定义请求uri,在入口方法上加入@ServletComponentScan注解,属性basePackages设为servlet包的路径即可。

第二种方式:

用创建配置类(注册组件)的方式代替注解,在类上加入@Configuration注解,创建返回值为ServletRegistryBean的方法,在方法上加入@Bean,它相当于bean标签,在方法体中new出这个对象,将自己创建的servlet,请求路径传参即可。

7. SpringBoot使用Filter/Listener

本章了解即可。

7.1 Filter

第一种方式:
创建过滤器类,实现javax.servlet.filter接口,类名上加入@WebFilter注解,用属性声明要过滤的url-pattern,最后在入口方法上加入@ServletComponentScan注解,属性basePackages设为filter包的路径即可。

第二种方式:
创建过滤器类,实现javax.servlet.filter接口,用创建配置类(注册组件)的方式代替注解,在类上加入@Configuration注解,创建返回值为FilterRegistryBean的方法,在方法上加入@Bean,它相当于bean标签,在方法体中new出这个对象,将自己创建的filter传参,再用该对象调用addUrlPatterns,将要过滤的路径(不支持**)以字符串形式传参即可。

7.2 Listener

创建监听器类,实现javax.servlet.ServletContextListener接口,实现它的初始化或销毁方法,之后在类上加入@Component注解

@Component
public class DicListener implements ServletContextListener {
    @Reference(interfaceClass = DicService.class, version = "1.0.0")
    private DicService dicService;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("开始加入数据字典");
        ServletContext servletContext = sce.getServletContext();

        Map<String, List<DicValue>> map = dicService.getAll();
        Set<String> set = map.keySet();

        for (String s : set) {
            List<DicValue> list = map.get(s);
            servletContext.setAttribute("s" + list, list);
        }
        System.out.println("完成加入数据字典");

    }
}

8. SpringBoot项目配置字符编码

字符编码过滤器类characterEncoding容器已经帮我们写好了,我们直接拿来。

创建该过滤器类,然后使用它的setForceEncoding()方法,传参true,再用它的setEncoding()方法传参要使用的编码集。

然后用创建配置类(注册组件)的方式代替注解,在类上加入@Configuration注解,创建返回值为FilterRegistryBean的方法,在方法上加入@Bean,它相当于bean标签,在方法体中new出这个对象,用该对象的setFilter()方法将写好的字符过滤器类传参,再用该对象调用addUrlPatterns,将要过滤的路径(不支持**)以字符串形式传参。

最后,在spring核心配置文件中关闭springboot自带的http字符编码支持,我们的才能生效。

spring.http.encoding.enabled=false
server.servlet.encoding.enabled=false

备选:resp.setContentType("text/html;character=utf-8");

第二种方式:

仅在spring核心配置文件中配置:

spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.http.encoding.charset=utf-8

9. SpringBoot打包与部署

记得手动指定资源文件夹

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

还有,如果没有这个,打好的包中是没有资源文件夹的。

		<resources>
			<resource>
				<!--源文件夹-->
				<directory>src/main/resources</directory>
				<!--指定哪个资源需要编译-->
				<includes>
					<include>**/*.*</include>
				</includes>
			</resource>
		</resources>

9.1 打war包

在pom.xml文件中通过<packaging>标签填入war,来指定打成war包,在<build>中用<finalName>指明项目名,再让入口方法继承SpringBootServletInitializer,重写它的configure()方法,返回值设为build.sources(Application.class);即可,之后将war包放入tomcat的webapp文件夹中就算部署成功,使用项目名+路径就可以访问了。

要注意的是,打war包的方式中,写在配置文件中的视图解析器是无效的,因为你换了个服务器运行。

9.2 打jar包

无需packaging指定,自动打成jar包,可在<build>中用<finalName>指明项目名。

打jar包的方式可以通过在cmd中用java命令的方式启动服务器来访问,因为springboot有内置的tomcat,此时,配置文件中的设置是会生效的。

10. 集成logback日志

该依赖springboot自带。

在resources目录中创建,起名要求为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</fileNamePattern>-->
            <fileNamePattern>D:/log/stdout.log.%d{yyyy-MM-dd}.log</fileNamePattern>
            <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>

然后在类名上加@Slf4j注解,加入lombok插件,再使用log.trace/debug/info/warn/error()方法来输出自定义日志。

11. 集成Thymeleaf模板

11.1 什么是Thymeleaf

一个Java语言开发的流行的模板引擎,对网络环境无严格要求,既可用于web环境,也可用于非web环境。它需要寄托在Html标签下才能实现。SpringBoot已经继承了Thymeleaf模板,所有的html都应写在templates中,这个文件夹中的文件无法被地址栏直接访问,必须经过中央调度器。

在web环境下,可以像jsp一样从后台接收数据并替换掉模板上的静态数据

在非web环境下,能直接显示模板上的静态数据

thymeleaf不需要像jsp一样要先编译后渲染,它的文件自始至终都是html文件,这样的模板引擎最终可以达成前后端分离的效果,提升用户体验。

11.2 SpringBoot集成Thymeleaf

创建带有Thymeleaf模板的springboot工程的过程有些许不同,在勾选Spring Web工程之后,还需要勾选:
在这里插入图片描述

在templates文件夹中新建的html中加入命名空间:xmlns:th="http://www.thymeleaf.org",在html标签中加入th:text="xxx"的属性,即可拿到后台的数据。如果有则替换掉静态数据,如果没有就展现静态数据:

特殊情况下,html文件位置变动了,可更改视图解析器的默认配置来匹配最新的html文件的位置。

thymeleaf的缓存默认是开启的,我们将其设置为关闭,再将服务器的“后台文件变化时”从do nothing改为自动更新资源,即可热更新前台显示

前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:text="${user.id}">xxx</div>
<div th:text="${user.name}">xxx</div>
</body>
</html>

配置文件

spring.thymeleaf.cache=false

11.3 Thymeleaf的表达式

11.3.1 标准变量表达式

${}标准变量表达式用于访问容器(tomcat)上下文环境中的变量,功能和EL表达式的${}相同。

必须放在html标签中,以th:text="${xxx}"包裹

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:text="${user.id}">xxx</div>
<div th:text="${user.name}">xxx</div>
</body>
</html>

11.3.2 选择变量表达式

不推荐。

使用th:object="${xxx}"属性来绑定对象,在其子标签中就可以使用*{id}的方式来代替${xxx.id}

11.3.3 混合使用

不推荐。

放在html标签中,直接以th:text="*{xxx}"包裹拿到数据,不需要th:object="${xxx}"

11.3.4 url路径表达式

11.3.4.1 不带参数:无优化

绝对路径:
传统写法:<a href="http://www.baidu.com"></a>
表达式写法:<a th:href="@{http://www.baidu.com}"></a>

相对路径:
传统写法:<a href="/res">传统方式相对路径跳转到res</a>
表达式写法:<a th:href="@{/res}">thymeleaf相对路径跳转到res</a>

11.3.4.2 自带参数:无优化

传统写法:
<a href="/param?username=池田依来沙&height=170">带参数跳转</a>
表达式写法:
<a th:href="@{/param?username=池田依来沙&height=170}">thymeleaf方式带参数跳转</a>

11.3.4.3 从后台获取参数

无传统写法,只有依靠jsp或者thymeleaf写法

传统写法:依靠jsp
表达式写法:
<a th:href="@{'/param?username=' + ${user.name}}">thymeleaf方式从后台获取参数然后带参数跳转</a>
当有多个参数时,不用非常麻烦的拼接,使用表达式写法会非常方便
<a th:href="@{/param(id=${user.id},name=${user.name})}">thymeleaf方式从后台获取多个参数然后带参数跳转</a>

11.3.4.4 引用静态资源:无优化

对于静态资源的引用,使用thymeleaf包裹,如:
<script type="text/javascript" th:src="@{/js/jquery-x.x.x.min}"></script>
<img th:src="@{/img/001.jpg}">

11.4 Thymeleaf的常见属性

一般从后台取来的数据所在的标签的属性前加th:即可用到thymeleaf的功能,如
表单中的action=->th:action

11.4.1 循环遍历List集合

完整版:th:each="user,userStat:${userList}"
其实可以将userStat省略,即使省略也可以在标签内部使用它
th:each="user:${userList}"
其中,user代表从userList中拿出来的每一个元素即当前循环的对象,在子标签中对user进行展示即可。userStat代表当前循环对象的状态,可用userStat.的方式得到一些状态变量。userList代表被循环的集合。

<div th:each="user:${userList}">
    <span th:text="${user.id}"></span>
    <span th:text="${user.name}"></span>
</div>

11.4.2 循环遍历Map集合

<div th:each="user:${userMap}">
    <span th:text="${user.getKey()}"></span>
    <span th:text="${user.getValue().id}"></span>
    <span th:text="${user.getValue().name}"></span>
</div>

11.4.3 循环遍历Array集合

同List一样

11.4.4 复杂的循环遍历

list套map套list装user

<div th:each="a:${complicatedList}">
    <div th:each="b:${a}">
        <div th:each="c:${b.getValue()}">
            <span th:text="${c.id}"></span>
            <span th:text="${c.name}"></span>
        </div>
    </div>
</div>

11.4.5 条件判断

th:if
th:if=“${sex eq 1}”:等于1就显示

th:unless
th:unless=“${sex eq/ne 1}”:等于1就不显示/不等于1就不显示

th:switch/th:case
th:switch=“${productType}”
th:case=“0”
th:case=“*”

11.4.6 内敛表达式

在父级标签加th:inline=“xxx”,xxx可取text,javascript和none

11.4.6.1 内敛文本

内敛文本表达式不依赖于html,在子标签域中(域外也行)直接使用内敛表达式[[表达式]]即可获取动态数据,但必须要求在父级标签上加th:inline="text"属性,所以可以写在body里

<div th:inline="text">
    数据:[[${data}]]
</div>

11.4.6.2 内敛脚本

在script中想取值,需要在script标签上加内敛脚本,然后在[[]]中获得

<script type="text/javascript" th:inline="javascript">
    function showData() {
        alert([[${data}]]);
    }
</script>

11.4.6.3 值为none则什么都不做

11.5 Thymeleaf字面量

跟在th表达式中的
文本字面量:'xxx'/"xxx"
数字字面量:"2020"
布尔字面量:"${flag}"
空值字面量:``

11.6 Thymeleaf字符串拼接

使用|xxx|来包裹要拼接的字符串,如
<span th:text="|共${totalRows}条${totalPages}页,当前第${currentPage}页|">共123条13页,当前第2页</span>

显示效果就是
共123条13页,当前第2页

11.7 Thymeleaf运算符

th:text="${}"的引号中使用
三元运算:表达式?”正确结果”:”错误结果”
算术运算:+ , - , * , / , %
关系比较::> , < , >= , <= ( gt , lt , ge , le )
相等判断:== , != ( eq , ne )

11.8 Thymeleaf表达式基本对象

模板引擎提供了一组内置的对象,这些内置的对象可以直接在模板中使用,这些对象由
#号开始引用,我们比较常用的内置对象#request(相当于#httpServletRequest)、#session

手动指定上下文根

<script type="text/javascript" th:inline="javascript">
 var basePath = [[${#httpServletRequest.getScheme() + "://" +
#httpServletRequest.getServerName() + ":" +
#httpServletRequest.getServerPort() +
#httpServletRequest.getContextPath()}]];
 //http://localhost:8080/springboot/user/login
 //获取协议名称
 var scheme = [[${#request.getScheme()}]];
 //获取服务 IP 地址
 var serverName = [[${#request.getServerName()}]];
 //获取服务端口号
 var serverPort = [[${#request.getServerPort()}]];
 //获取上下文根
 var contextPath = [[${#request.getContextPath()}]];
 var allPath = scheme+"://"+serverName+":"+serverPort+contextPath;
 alert(allPath);
</script>

从session中获取数据的三种方式

<span th:text="${#session.getAttribute('username')}"></span><br/>
<span th:text="${#httpSession.getAttribute('username')}"></span><br/>
<span th:text="${session.username}"></span>

获得地址栏url:
#request.requestURL

获得传递的参数:
#request.queryString

11.9 Thymeleaf表达式功能对象(了解)

模板引擎提供的一组功能性内置对象,可以在模板中直接使用这些对象提供的功能方法
工作中常使用的数据类型,如集合,时间,数值,可以使用 Thymeleaf 的提供的功能性对象来处理它们

内置功能对象前都需要加#号,内置对象一般都以 s 结尾
官方手册:http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

#dates: java.util.Date 对象的实用方法:
<span th:text="${#dates.format(curDate, 'yyyy-MM-dd HH:mm:ss')}"></span>
#calendars: 和 dates 类似, 但是 java.util.Calendar 对象;
#numbers: 格式化数字对象的实用方法;
#strings: 字符串对象的实用方法: contains, startsWith, prepending/appending 等;
#objects: 对 objects 操作的实用方法;
#bools: 对布尔值求值的实用方法;
#arrays: 数组的实用方法;
#lists: list 的实用方法,比如<span th:text="${#lists.size(datas)}"></span>
#sets: set 的实用方法;
#maps: map 的实用方法;
#aggregates: 对数组或集合创建聚合的实用方法;

12 部署linux

12.1 启动zookeeper

记得更改配置文件

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=D:\work\zookeeper\apache-zookeeper-3.5.9-bin\apache-zookeeper-3.5.9-bin\data
# the port at which the clients will connect
clientPort=2181
admin.serverPort=8888
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

安装解压缩zookeeper:tar -zxvf xxx -C xxx
zookeeper启动:在bin目录下执行 ./zkServer.sh start
zookeeper关闭:在bin目录下执行 ./zkServer.sh stop

12.2 启动Mysql

mysql启动:在bin目录下执行 ./mysqld_safe &
mysql关闭:在bin目录下执行 ./mysqladmin -uroot -p shutdown再输入密码回车即可

12.3 启动生产者

在jar所在目录中执行java -jar xxx.jar &

12.4 启动消费者

在jar所在目录中执行java -jar xxx.jar &

13 我遇到的问题

问题描述:无法通过index.html跳转到login.html
解决方案:发现到index.html中跳转的路径是直接修改地址栏的地址来实现访问的,而springboot所有的html文件都在templates下,这个文件夹下的文件无法通过地址栏直接访问,所以将index.html中的访问方式改为通过后台访问,这样就可以通过中央调度器,然后通过后台转发到login.html即可解决。或者通过在配置文件中配置spring.web.resources.static-locations=classpath:/templates/,classpath:/static/的方式解除静态资源的访问也可以。

问题描述:无法访问静态资源,错误404,target中已编译
解决方案:static中的静态文件springboot可以直接读取,所以将静态资源前的/static或者…/static去掉,重启服务器即可。

记得序列化

要想在某个html中使用thymeleaf,该html必须是由后台返回的视图跳转的

每一个由后台视图返回的html都加上

	<base th:href="${#httpServletRequest.getScheme() + '://' +
	#httpServletRequest.getServerName() + ':' +
	#httpServletRequest.getServerPort() +
	#httpServletRequest.getContextPath()}">

之后再编辑

templates下的子包中的html发起的请求,需在接收请求的控制器类的请求路径字符串前加上完整包名

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值