Spring Boot整合MyBatis学习总结

公司的很多项目都陆陆续续引入了Spring Boot,通过对Spring Boot的接触了解发现其真的是大大地简化了开发、简化了依赖配置,很多功能注解一下就可以实现,真的是太方便了。下面记录了一个Spring Boot的入门程序实现。

1,pom.xml文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zws</groupId>
  <artifactId>spring-boot</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-boot</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.10.RELEASE</version>
  </parent>

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

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

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

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

	<dependency>
	    <groupId>com.alibaba</groupId>
	    <artifactId>druid-spring-boot-starter</artifactId>
	    <version>1.1.0</version>
	</dependency>

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

	<dependency>
	    <groupId>commons-logging</groupId>
	    <artifactId>commons-logging</artifactId>
	    <version>1.2</version>
	</dependency>

	<dependency>
	    <groupId>org.slf4j</groupId>
	    <artifactId>slf4j-api</artifactId>
	</dependency>

	<dependency>
	    <groupId>log4j</groupId>
	    <artifactId>log4j</artifactId>
	    <version>1.2.17</version>
	</dependency>

	<dependency>
	    <groupId>com.alibaba</groupId>
	    <artifactId>fastjson</artifactId>
	    <version>1.2.46</version>
	</dependency>

	<dependency>
	    <groupId>junit</groupId>
	    <artifactId>junit</artifactId>
	    <scope>test</scope>
	</dependency>
  </dependencies>
  
  <build>
      <plugins>
      	  <plugin>
		      <groupId>org.apache.maven.plugins</groupId>
			  <artifactId>maven-compiler-plugin</artifactId>
			  <configuration>
			      <source>1.8</source>
			      <target>1.8</target>
			  </configuration>
		  </plugin>
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
      </plugins>
  </build>
</project>

可以看到这个文件比内容并不多,但是却引入了很多需要的依赖。这里引入的Spring Boot版本为1.5.6.RELEASE,其中spring-boot-maven-plugin插件是Spring Boot提供的打包用的插件。mybatis-spring-boot-starter为MyBatis集成Spring Boot的依赖。druid-spring-boot-starter为阿里开源数据源Druid集成Spring Boot的依赖,它会下载对应的druid jar包,注意这里并没有直接引入Druid依赖,如果直接引入Druid依赖jar包,则druid的监控页面无法显示sql。

2,Spring Boot配置文件resources/application.properties:

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

#tomcat访问日志
server.tomcat.basedir=logs
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=access
server.tomcat.accesslog.pattern=%t %a "%r" %s %b (%D ms)

datasource.druid.url=jdbc:mysql://localhost/db_boot?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
datasource.druid.username=root
datasource.druid.password=root
datasource.druid.driver-class-name=com.mysql.jdbc.Driver
datasource.druid.initialSize=5
datasource.druid.minIdle=5
datasource.druid.maxActive=20
datasource.druid.maxWait=60000
datasource.druid.minEvictableIdleTimeMillis=300000
datasource.druid.validationQuery=select 'x'
datasource.druid.testOnBorrow=false
datasource.druid.testOnReturn=false
datasource.druid.testWhileIdle=true
datasource.druid.poolPreparedStatements=false
datasource.druid.maxPoolPreparedStatementPerConnectionSize=100
datasource.druid.filters=stat,wall,log4j

mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

application.properties文件为Spring Boot的总的配置文件,Spring Boot默认会加载resources目录下的application.properties文件。

3,MyBatis的配置文件resources/mybatis/mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<setting name="cacheEnabled" value="true" />
		<setting name="lazyLoadingEnabled" value="true" />
		<setting name="multipleResultSetsEnabled" value="true" />
		<setting name="useColumnLabel" value="true" />
		<setting name="useGeneratedKeys" value="false" />
		<setting name="autoMappingBehavior" value="PARTIAL" />
		<setting name="autoMappingUnknownColumnBehavior" value="WARNING" />
		<setting name="defaultExecutorType" value="SIMPLE" />
		<setting name="defaultStatementTimeout" value="25" />
		<setting name="defaultFetchSize" value="100" />
		<setting name="safeRowBoundsEnabled" value="false" />
		<setting name="mapUnderscoreToCamelCase" value="false" />
		<setting name="localCacheScope" value="SESSION" />
		<setting name="jdbcTypeForNull" value="OTHER" />
		<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
	</settings>
	<typeAliases>
		<package name="com.zws.be.user.bean" />
	</typeAliases>
</configuration>

此配置文件的路径已经配置在了resources/application.properties文件内。

4,resources/mybatis/UserMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zws.be.user.mapper.UserMapper" >
    <resultMap id="UserMap" type="User">
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="name" property="name" jdbcType="VARCHAR" />
        <result column="pass" property="pass" jdbcType="VARCHAR" />
        <result column="create_date" property="createDate" />
    </resultMap>
    <select id="getAll" resultMap="UserMap">
       select id, name, pass, create_date from user
    </select>
    
    <select id="getUserById" resultMap="UserMap" parameterType="long">
    	select id, name, pass, create_date from user where id = #{value}
    </select>
</mapper>

5,Sping Boot启动类Application.java:

package com.zws.be;

import javax.sql.DataSource;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;

import com.alibaba.druid.pool.DruidDataSource;

@SpringBootApplication
@MapperScan(basePackages = {"com.zws.be.*.mapper"})
@ServletComponentScan
@EnableScheduling
public class Application {

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

	@Bean("dataSource")
	@ConfigurationProperties("datasource.druid")
	public DataSource getDruidDataSource() {
		return DataSourceBuilder.create().type(DruidDataSource.class).build();
	}
}

这个是程序启动的入口,里面有mian函数,运行此类即可启动Spring Boot,Spring Boot默认嵌入了tomcat。注解@MapperScan(basePackages = {"com.zws.be.*.mapper"})指定了映射mapper文件的接口所在的包。@EnableScheduling注解用于开启Spring的定时组件,下面会有例子。@ServletComponentScan注解搭配@WebServlet和@WebFilter注解使得定义servlet和filter时非常方便。

6,下面是定义一个简单的restful接口所需的各类:

com.zws.be.user.bean.User:

package com.zws.be.user.bean;

import java.util.Date;

import org.apache.ibatis.type.Alias;
@Alias("User")
public class User {

	private Long id;
	private String name;
	private String pass;
	private Date createDate;

	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPass() {
		return pass;
	}
	public void setPass(String pass) {
		this.pass = pass;
	}
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", pass=" + pass + ", createDate=" + createDate + "]";
	}

}

com.zws.be.user.mapper.UserMapper:

package com.zws.be.user.mapper;

import java.util.List;

import com.zws.be.user.bean.User;

public interface UserMapper {

	List<User> getAll();

	User getUserById(Long id);
}

com.zws.be.user.service.UserService:

package com.zws.be.user.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zws.be.user.bean.User;
import com.zws.be.user.mapper.UserMapper;

@Service
public class UserService {

	@Autowired
	private UserMapper userMapper;

	public List<User> getUsers() {
		return userMapper.getAll();
	}

	public User getUser(Long id) {
		return userMapper.getUserById(id);
	}
}

com.zws.be.user.controller.UserController:

package com.zws.be.user.controller;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.zws.be.user.bean.User;
import com.zws.be.user.service.UserService;

@RestController
@RequestMapping("/user")
public class UserController {
	public Logger logger = Logger.getLogger(UserController.class);

	@Autowired
	private UserService userService;

	@RequestMapping(value="/{id}", method=RequestMethod.GET, produces = "application/json")
	public String hello(@PathVariable Long id) {
		User user = userService.getUser(id);
		return JSON.toJSONString(user, SerializerFeature.WriteDateUseDateFormat);
	}
}

7,配置Druid的sql监控servlet:

package com.zws.be.filter;

import javax.servlet.annotation.WebServlet;

import com.alibaba.druid.support.http.StatViewServlet;

/**
 * DRUID的sql监控
 * @author wensh.zhu
 * @2018-03-11
 */
@WebServlet(name="monitorSrvlet", urlPatterns= {"/druid/*"})
public class MonitorServlet extends StatViewServlet {

	private static final long serialVersionUID = -2211104135110049275L;

}

启动后访问http://localhost:8080/app/druid即可进入Druid的sql监控的监控页面。

8,过滤器例子:

package com.zws.be.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

import org.apache.log4j.Logger;

@WebFilter(filterName="filterDemo", urlPatterns = {"/*"})
public class FilterDemo implements Filter{
	private Logger logger = Logger.getLogger(FilterDemo.class);

	@Override
	public void destroy() {}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain)
			throws IOException, ServletException {
		logger.info("FilterDemo is working...");
		chain.doFilter(arg0, arg1);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

9,定时器例子:

package com.zws.be.timer;

import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TimerDemo {
	private Logger logger = Logger.getLogger(getClass());

	@Scheduled(cron = "0/30 * * * * *")  
	public void timer() {
		logger.info("定时器例子");
	}
}

10,log4j配置文件resources/log4j.properties:

log4j.rootLogger=INFO, stdout, infoLog, errorLog

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.conversionPattern = %d{yyyy-MM-dd HH\:mm\:ss}|%p|%C|%M|%L|%m%n

log4j.appender.infoLog=com.zws.be.log.MyRollingFileAppender
log4j.appender.infoLog.File=logs/info/info.log
log4j.appender.infoLog.Threshold = info
log4j.appender.infoLog.layout=org.apache.log4j.PatternLayout
log4j.appender.infoLog.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss}|%p|%C|%M|%L|%m%n

log4j.appender.errorLog=com.zws.be.log.MyRollingFileAppender
log4j.appender.errorLog.File=logs/error/error.log
log4j.appender.errorLog.Threshold = error
log4j.appender.errorLog.layout=org.apache.log4j.PatternLayout
log4j.appender.errorLog.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss}|%p|%C|%M|%L|%m%n

自定义日志生成文件名称:

package com.zws.be.log;

import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;

import org.apache.log4j.Priority;
import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.spi.LoggingEvent;

public class MyRollingFileAppender extends RollingFileAppender{

	private long nextRollover = 0L;

	public void rollOver() {
		File target, file;

		if (qw != null) {
			long size = ((CountingQuietWriter) qw).getCount();
			nextRollover = size + maxFileSize;
		}

		boolean renameSuccessed = true;
		if (maxBackupIndex > 0) {
			file = new File(getRollingFileName(fileName, maxBackupIndex));
			if (file.exists()) {
				renameSuccessed = file.delete();
			}

			for (int i = maxBackupIndex - 1; i >= 1 && renameSuccessed; i --) {
				file = new File(getRollingFileName(fileName, i));
				if (file.exists()) {
					target = new File(getRollingFileName(fileName, i + 1));
					renameSuccessed = file.renameTo(target);
				}
			}

			if (renameSuccessed) {
				target = new File(getRollingFileName(fileName, 1));
				closeFile();
				renameSuccessed = file.renameTo(target);

				if (!renameSuccessed) {
					try {
						setFile(fileName, true, bufferedIO, bufferSize);
					} catch (IOException e) {
						if (e instanceof InterruptedIOException) {
							Thread.currentThread().interrupt();
						}
					}
				}
			}
		}
	}

	private String getRollingFileName(String fileName, int index) {
		String fName = "";
		String newIndex = index < 10 ? ("0" + index) : String.valueOf(index);
		if (index > 0) {
			fName = fileName.replace(".log", "") + "_" + newIndex + ".log";
		} else {
			fName = fileName;
		}
		return fName;
	}

	@Override
	protected void subAppend(LoggingEvent event) {
		super.subAppend(event);
		if (fileName != null && qw != null) {
			long size = ((CountingQuietWriter) qw).getCount();
			if (size >= maxFileSize && size >= nextRollover) {
				rollOver();
			}
		}
	}

	@Override
	public boolean isAsSevereAsThreshold(Priority priority) {
		String level = priority.toString();
		if ("ERROR".equals(level)) {
			return getThreshold().equals(priority);
		}

		return super.isAsSevereAsThreshold(priority);
	}
}

11,Spring MVC请求参数以及返回信息自动日志的辅助类:

package com.zws.be.log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.MessageFormat;

import org.apache.log4j.Logger;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
 * 用于请求参数、响应信息的自动日志。
 * @author wensh.zhu
 * @2018-03-11
 */
@ControllerAdvice(basePackages = {"com.zws.be"})
public class LogResponseBodyAdvice implements ResponseBodyAdvice<String>{

	private String pattern = "\n---BEGIN---\nReqURI:{0}\nParams:{1}\nMethod:{2}\nReturn:{3}\n---END---";

	private Logger logger = Logger.getLogger(LogResponseBodyAdvice.class);

	@Override
	public String beforeBodyWrite(String rtnMsg, MethodParameter param, MediaType arg2,
			Class<? extends HttpMessageConverter<?>> arg3, ServerHttpRequest req, ServerHttpResponse resp) {
		String clazName = param.getDeclaringClass().getName();
		String mtdName = param.getMethod().getName();
		String reqURI = req.getURI().toString();
		String reqParams = getReqParams(req);

		String log = getLog(reqURI, reqParams, clazName + "." + mtdName, rtnMsg);
		logger.info(log);
		return rtnMsg;
	}

	@Override
	public boolean supports(MethodParameter arg0, Class<? extends HttpMessageConverter<?>> arg1) {
		return true;
	}

	private String getLog(String reqURI, String reqParams, String proMethod, String rtnMsg) {
		return MessageFormat.format(pattern, reqURI, reqParams, proMethod, rtnMsg);
	}

	private String getReqParams(ServerHttpRequest req) {
		StringBuilder body = new StringBuilder();
		String line = null;
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(req.getBody(), "UTF-8"));
			while ((line = reader.readLine()) != null) {
				body.append(line);
			}
		} catch (IOException e) {
			logger.error("I/O error ", e);
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				logger.error("I/O error ", e);
			}
		}

		return body.toString();
	}
}

日志输出样例:

---BEGIN---
ReqURI:http://localhost:8080/app/user/1
Params:
Method:com.zws.be.user.controller.UserController.hello
Return:{"createDate":"2018-03-04 15:44:25","id":1,"name":"zhangsan","pass":"[email protected]"}
---END---

12,运行Application,访问http://localhost:8080/app/user/1,如下图:

查看druid的监控:

项目目录结构图:

原文地址:http://blog.51cto.com/wenshengzhu/2087406

时间: 2024-11-05 21:49:31

Spring Boot整合MyBatis学习总结的相关文章

企业分布式微服务云SpringCloud SpringBoot mybatis (十三)Spring Boot整合MyBatis

Spring中整合MyBatis就不多说了,最近大量使用Spring Boot,因此整理一下Spring Boot中整合MyBatis的步骤.搜了一下Spring Boot整合MyBatis的文章,方法都比较老,比较繁琐.查了一下文档,实际已经支持较为简单的整合与使用.下面就来详细介绍如何在Spring Boot中整合MyBatis,并通过注解方式实现映射. 整合MyBatis 新建Spring Boot项目,或以Chapter1为基础来操作 pom.xml中引入依赖 这里用到spring-bo

Spring Boot 整合mybatis时遇到的mapper接口不能注入的问题

现实情况是这样的,因为在练习spring boot整合mybatis,所以自己新建了个项目做测试,可是在idea里面mapper接口注入报错,后来百度查询了下,把idea的注入等级设置为了warning,至于怎末设置可以自行百度,这里不再赘述,但是接下来spring boot能够运行起来,但是通过浏览器访问的时候,就会报错,后来也是经过多方查询,发现了问题的原因,特此记录一下: spring  boot整合mybatis时,要将mapper装配到spring容器中,要在mapper接口中加上@M

第七天.spring boot 整合mybatis

一. spring boot 整合mybatis 1.整合思路: 1.1 添加依赖 mybatis 1.2 在配置文件中配置数据源信息 1.3 编写pojo mapper接口 mapeer映射文件 1.4手动配置mybatis的包扫描,在主启动类添加@MapperScan 1.5 启动springboot服务器 2.开始工程部署: 2.1:添加依赖 mybatis <!--整合springboot与mybatis的整合--> <dependencies> <dependenc

Spring Boot 整合 Mybatis 实现 Druid 多数据源详解

一.多数据源的应用场景 目前,业界流行的数据操作框架是 Mybatis,那 Druid 是什么呢? Druid 是 Java 的数据库连接池组件.Druid 能够提供强大的监控和扩展功能.比如可以监控 SQL ,在监控业务可以查询慢查询 SQL 列表等.Druid 核心主要包括三部分: 1. DruidDriver 代理 Driver,能够提供基于 Filter-Chain 模式的插件体系. 2. DruidDataSource 高效可管理的数据库连接池 3. SQLParser 当业务数据量达

spring boot整合mybatis

spring boot本来可以使用jpa进行数据库操作,但是考虑到jpa的资料比较少,学习成本比较大,不是所有的人都可以十分了解,因此考虑采用mybatis来进行数据库操作. 1.新建maven项目,在pom中添加相关依赖. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLoca

通过Spring Boot整合Mybatis分析自动配置详解

前言 SpringBoot凭借"约定大于配置"的理念,已经成为最流行的web开发框架,所以有必须对其进行深入的了解:本文通过整合Mybatis类来分析SpringBoot提供的自动配置(AutoConfigure)功能,在此之前首先看一个整合Mybatis的实例. SpringBoot整合Mybatis 提供SpringBoot整合Mybatis的实例,通过Mybatis实现简单的增删改查功能: 1.表数据 CREATE TABLE `role` (  `note` varchar(2

spring boot整合mybatis+mybatis-plus

Spring boot对于我来说是一个刚接触的新东西,学习过程中,发现这东西还是很容易上手的,Spring boot没配置时会默认使用Spring data jpa,这东西可以说一个极简洁的工具,可是我还是比较喜欢用mybatis,工具是没有最好的,只有这合适自己的. 说到mybatis,最近有一个很好用的工具--------mybatis-Plus(官网),现在更新的版本是2.1.2,这里使用的也是这个版本.我比较喜欢的功能是代码生成器,条件构造器,这样就可以更容易的去开发了. mybatis

spring boot 整合 mybatis

spring boot jpa的方式确实非常简单, 但是复杂系统避免不了自己写sql, 那么如果把sql写在方法的上面, 可能有些人会觉得怪异, 或者不舒服. 那么能不能将mybatis整合进spring boot , 将sql 分离出来呢. 一. pom.xml <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-s

spring boot 整合mybatis(好用!!!!)

springboot整合mybatis 1.pom依赖 <!-- 引入freeMarker的依赖包. --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> 2.配置application.properties spri