优点
缺点
properties文件
#第一种配置文件
#mysql
jdbc.mysql.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/crm?serverTimezone=UTC
jdbc.mysql.username=root
jdbc.mysql.password=root
#druid
druid.initialSize=10
druid.minIdle=10
druid.maxActive=50
druid.maxWait=60000
yml文件
#第二种配置文件
#myKey: myValue
#yaml 层级式键值对配置
#层级:通过换行符+空格,同一层级必须对其,父层与子层之间通常使用2个空格
#level1:
# level21: aaa
# level2:
# level31: bb
# level32: cc
#数据类型
#简单值
#字符串:可以不使用引号包裹,但是有特殊符号时需要使用引号包裹(例如:空格)
name: 张三
age: 10
birthday: 1998/07/25
gender: true
obj: ~
#数组(也认为是LIst集合)
#行内
array1: [spring, springmvc, mybatis]
array2:
- html
- css
- javascript
#对象(也可认为是Map集合)
student:
name: 李四
age: 22
birth: 1999/10/17
gender: false
hobby: [football, games, swimming]
address:
city: 郑州市
area: 金水区
street: 民航路
#主配置
#激活环境配置profiles
#spring:
# profiles:
# active: dev
#server:
# port: 8080
本质是将配置类对象放到ioc容器中
单个读取
@Value("${name}")
private String username;
使用配置类读取
第一种方式
@Component + @ConfigurationProperties
第二种方式
@EnableConfigurationProperties + @ConfigurationProperties
读取第三方的properties文件
@Component
@ConfigurationProperties(prefix = "jdbc.mysql")
//加载第三方资源文件
@PropertySource(value = "classpath:db.properties")
读取原生的xml文件
demo
/**
* 读取配置文件数据
*/
@RestController
public class ReadConfigController {
/**
* 单个读取,不方便
* 使用@Value注解+SpringEL来实现配置读取
*/
@Value("${name}")
private String username;
@Value("${age}")
private Integer age;
@Value("${birthday}")
private Date birthday;
@Value("${gender}")
private Boolean gender;
@Value("${student.name}")
private String studentName;
@GetMapping("/read")
public String read(){
return "姓名:" + username + " 年龄:" + age + " 生日:" + birthday + " 性别:" + gender + " 学生姓名:" + studentName;
}
/**
* 使用配置类
* 将配置类放到IOC容器,在这里自动注入
*/
@Autowired
private StudentProperties studentProperties;
@GetMapping("/readProperties")
public StudentProperties readProperties(){
return studentProperties;
}
/**
* 读取第三方的properties文件
*/
@Autowired
private MysqlProperties mysqlProperties;
@GetMapping("/readProp")
public MysqlProperties readProp(){
return mysqlProperties;
}
/**
* 读取原生的xml配置文件
*/
@Autowired
private Emp emp;
@GetMapping("/readXml")
public Emp readXml(){
return emp;
}
}
在配置类上加注解
//加载原生的xml spring配置文件
@ImportResource(locations = "classpath:applicationContext.xml")
//开启配置文件读取,属性为要读取的配置类,可以批量读取配置类
@EnableConfigurationProperties({StudentProperties.class, AddressProperties.class})
@SpringBootApplication
public class Springboot02ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot02ConfigApplication.class, args);
}
}
读取yaml文件的配置类
/**
* 学生配置读取类,自动读取yml配置文件
*
* 成员变量名称必须与配置名称保持一致(驼峰与中划线)
* 1.@Component + @ConfigurationProperties
* 2.@EnableConfigurationProperties + @ConfigurationProperties
*
* 第二种方式的@EnableConfigurationProperties注解
* 需要放到配置类上
* 作用是:开启配置文件读取
*/
@Data
//@Component //配置bean
@ConfigurationProperties(prefix = "student") //读取配置文件,属性用来指定层级
public class StudentProperties {
private String name;
private Integer age;
private Date birth;
private Boolean gender;
private String[] hobby;
private AddressProperties address;
//get... set...
}
// @Component
@Data
@ConfigurationProperties(prefix = "student.address")
public class AddressProperties {
private String city;
private String area;
private String street;
}
读取properties文件的配置类
/**
* 读取#第三方的priperties文件
*/
@Data
@Component
@ConfigurationProperties(prefix = "jdbc.mysql")
//加载第三方资源文件
@PropertySource(value = "classpath:db.properties")
public class MysqlProperties {
private String driverClassName;
private String url;
private String username;
private String password;
}
读取原生的applicationContext.xml文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dept" class="com.dx.bean.Dept">
<property name="id" value="10"/>
<property name="dname" value="研发部"/>
bean>
<bean id="emp" class="com.dx.bean.Emp">
<property name="id" value="1001"/>
<property name="ename" value="汤姆"/>
<property name="dept" ref="dept"/>
bean>
beans>
@Data
public class Emp {
private Integer id;
private String ename;
private Dept dept;
}
@Data
//开启链式调用
@Accessors(chain = true)
public class Dept {
private Integer id;
private String dname;
}
三种工作环境配置文件:开发环境(dev)、生产环境(prod)、测试环境(test)
#环境配置
#需要激活:在application.yml中激活
#命名规则:application-xxx.xml
#开发环境配置
server:
#端口号
port: 8001
servlet:
#根路径
context-path: /web-dev
#生产环境配置
server:
port: 8003
servlet:
context-path: /web-prod
#测试环境
server:
port: 8002
servlet:
context-path: /web-test
在测试的时候,需要修改pom的编译路径,确保把所有的配置文件都编译以后再测试
<build>
<resources>
<resource>
<directory>D:\workspace\SpringBoot-Code\02-spring-boot-configdirectory>
<includes>
<include>**/*.ymlinclude>
<include>application.ymlinclude>
includes>
resource>
resources>
build>
外部配置文件
在D盘放一个application.yml文件 端口指定为8009
打包后使用命令行运行并且指定
java -jar aaa.jar --spring.config.location=D:/application.yml
命令修改配置文件
可以使用命令行参数指定(文档一行写不下的时候,不要回车)
java -jar aaa.jar --server.port=8888 --server.servlet.context-path=/bjpowernode
后加载的会覆盖先加载的
最后加载的优先级最高
spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
其中同一目标下的properties文件的优先级大于yml文件
配置文件可以放的位置和优先级
classpath:/ --优先级4
classpath:/config/ --优先级3
file:./ --优先级2
file:./config/ --优先级1
@RestController
//注解式日志:动态为该类声明一个静态Logger成员变量
//@Slf4j
public class LogController {
/**
* 使用日志:
* 在当前类中声明一个成员变量,类型为Logger类型
*/
private Logger log = LoggerFactory.getLogger(LogController.class);
@GetMapping("/getLog")
public String getLog(){
/**
* 在各个日志框架都有级别
* 错误error,警告warn,信息info,调试debug,底层trace
*
* springboot默认级别为info
* 可以在application.yml配置文件中配置
*
* 例如:当级别为info,日志输入仅会输入info以及以上级别日志
*/
//程序出现异常
log.error("error级别的日志");
//程序有可能出现问题,提醒或警告
log.warn("warn级别的日志");
//信息:记录用户操作
log.info("info级别的日志");
//调试信息:开发时使用
log.debug("debug级别的日志");
//程序底层信息
log.trace("trace级别的日志");
//热部署添加内容
log.info("无需重启自动生效...");
return "正在记录日志";
}
}
全局配置 局部配置
#配置日志
logging:
level:
#使用root配置全局的日志级别
root: info
#局部日志级别,两种写法
# com.dx.controller: trace
com:
dx:
controller: trace
#自定义日志格式
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss SSS} %-5level [%thread] %logger -- %msg%n"
#日志在文件中的输出
file:
#日志文件名,在根目录下可以找到文件
name: demo.log
#指定日志文件路径,但是不能与那么同时配置,两个只能用一个
# path: c:/log/
#如果想既自定义文件名 又指定文件位置,可以导入logback.xml文件,如果使用logback.xml记得把这里的配置去掉,不然会冲突
logback.xml:可以直接使用,直接放到项目中就可以
<configuration scan="false" scanPeriod="60 seconds" debug="false">
<property name="LOG_HOME" value="d:/logback/" />
<property name="appName" value="springboot">property>
<appender name="cc" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
layout>
appender>
<appender name="ff" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/${appName}.logfile>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.logfileNamePattern>
<MaxHistory>365MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%npattern>
layout>
appender>
<logger name="com.bjpowernode.controller" level="debug" />
<logger name="org.springframework" level="debug" additivity="false">logger>
<root level="info">
<appender-ref ref="cc" />
<appender-ref ref="ff" />
root>
configuration>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
//开启对象中set方法的链式调用
@Accessors(chain = true)
//链式调用
Student s3 = new Student()
.setId(30)
.setName("王五")
.setAddress("深圳")
.setScore(82.6);
System.out.println(s3);
//注解式日志:动态为该类声明一个静态Logger成员变量
@Slf4j
public class LogController {
//可以代替这条语句
// private Logger log = LoggerFactory.getLogger(LogController.class);
@GetMapping("/getLog")
public String getLog(){
log.error("error级别的日志");
log.warn("warn级别的日志");
log.info("info级别的日志");
log.debug("debug级别的日志");
log.trace("trace级别的日志");
log.info("无需重启自动生效...");
return "正在记录日志";
}
}
默认位置
# 默认静态资源路径:
# "classpath:/META-INF/resources/"
# "classpath:/resources/"
# "classpath:/static/"
# "classpath:/public/"
配置自定义位置
配置静态资源访问路径
spring:
web:
resources:
#设置当前项目静态资源目录
#注意:配置自定义静态资源目录时,需要添加原有配置项,否则会覆盖原有配置
#classpath表示在类路径下查找资源,file表示在操作系统的文件系统下查找资源 d:/
static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/my/,file:${custom.upload}
mvc:
#设置当前项目静态资源的访问前缀
static-path-pattern: /static/**
#配置自定义本地的资源路径
custom:
upload: E:\文件\图片\壁纸
导入bootstrap和jqury依赖
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>jqueryartifactId>
<version>3.6.0version>
dependency>
<dependency>
<groupId>org.webjarsgroupId>
<artifactId>bootstrapartifactId>
<version>3.4.1version>
dependency>
使用demo
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<link rel="stylesheet" href="/webjars/bootstrap/3.4.1/css/bootstrap.min.css">
head>
<body>
<div style="text-align: center">
<h1>首页h1>
<div>
<span id="hello">你好span>
div>
<div>
<button type="button" class="btn btn-primary">按钮button>
div>
<div>
<img src="/static/bbb.jpg" alt="" style="width: 300px; height: 200px">
div>
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js">script>
<script type="text/javascript">
$(function (){
var str = $('#hello').html();
alert(str);
$('#hello').append('springboot');
})
script>
div>
body>
html>
开发时关闭缓存、发布时打开缓存
spring:
#Thymeleaf的配置
thymeleaf:
#页面缓存,开发时关闭缓存、发布时打开缓存
cache: false
#前后缀,使用默认值就可以
# prefix: classpath:/templates/
# suffix: .html
取值
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
......
<p th:text="${msg}">p>
<p th:text="${message}">p>
<p th:utext="${message}">p>
<p>[[${msg}]]p>
<form action="/emp/edit" th:action="@{/emp/edit}" method="post">
<div class="form-group">
<label>员工编号label>
<input type="text" name="id" class="form-control" th:value="${emp.id}">
div>
<div class="form-group">
<label>员工姓名label>
<input type="text" name="ename" class="form-control" th:value="*{ename}">
div>
<div class="form-group">
<label>入职日期label>
<input type="date" name="hiredate" class="form-control" th:value="${#dates.format(emp.hiredate, 'yyyy-MM-dd')}">
div>
<div class="form-group">
<label>员工性别label>
<select name="gender" class="form-control">
<option value="">option>
<option value="1" th:selected="${emp.gender=='1'}">男性option>
<option value="2" th:selected="${emp.gender=='2'}">女性option>
select>
div>
<div class="form-group">
<button type="button" class="btn btn-primary">提交button>
div>
form>
循环
<tr th:each="emp : ${empList}">
<td>[[${emp.id}]]td>
<td th:text="${emp.ename}">td>
tr>
判断
<td>
<span th:if="${emp.gender=='1'}">男性span>
<span th:if="${emp.gender=='2'}">女性span>
td>
<td th:switch="${emp.gender}">
<span th:case="'1'">帅哥span>
<span th:case="'2'">靓女span>
td>
日期格式化
//日期格式化
//在成员变量上添加注解 @DateTimeFormat:接收参数时格式化 @JsonFormat:发送参数时格式化
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date hiredate;
<td th:text="${#dates.format(emp.hiredate, 'yyyy-MM-dd')}">td>
自动根路径 @{...}
#在application.yml文件中
#修改项目的根路径
server:
servlet:
context-path: /boot
<p><a href="/emp/list" th:href="@{/emp/list}">员工列表a>p>
路径传参
<td>
<a href="/emp/get/1" th:href="@{'/emp/get/' + ${emp.id}}" class="btn btn-warning btn-xs">编辑a>
<a href="#" th:href="@{/emp/remove(id=${emp.id},ename=${emp.ename},job=${emp.job})}" class="btn btn-danger btn-xs">删除a>
td>
<form th:action="@{/auth/login}" method="post" style="width: 350px;margin: 10px auto;">
<div style="color: red;">[[${message}]]div>
<div class="form-group">
<label>用户名label>
<input type="text" name="username" class="form-control">
div>
<div class="form-group">
<label>密码label>
<input type="password" name="password" class="form-control">
div>
<div class="form-group">
<button type="submit" class="btn btn-primary">登录button>
div>
form>
/**
* 自定义WebMvc配置类
* 实现一个接口WebMvcConfigurer的配置类,相当于原生springmvc.xml配置文件
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 动态页面访问映射
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/page/login").setViewName("login");
registry.addViewController("/").setViewName("login");
registry.addViewController("/page/index").setViewName("index");
}
/**
* 注册拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry
//配置拦截器对象
.addInterceptor(new LoginInterceptor())
//配置拦截器拦截路径
.addPathPatterns("/**")
//配置拦截器放行路径(白名单)
.excludePathPatterns("/static/**", "/webjars/**", "/auth/login", "/page/login", "/");
}
/**
* 对静态资源处理
*/
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry
// .addResourceHandler("/static2/**")
// .addResourceLocations("classpath:/my2/");
// }
/**
* 添加自定义的数据格式转换器
*/
@Override
public void addFormatters(FormatterRegistry registry) {
// registry.addFormatter();
registry.addConverter(new PointConverter());
}
/**
* 前后端分离的项目:设置全局跨域处理
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
}
}
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object loginUser = request.getSession().getAttribute("loginUser");
if(loginUser == null){
request.setAttribute("message", "没有登录");
request.getRequestDispatcher("/page/login").forward(request, response);
return false;
}
return true;
}
}
/**
* 自定义的类型转换器:
* 作用:将String转换为自定义Point
*/
public class PointConverter implements Converter<String, Point> {
@Override
public Point convert(String source) {
String[] ss = source.split(",");
Point point = new Point(ss[0], ss[1]);
return point;
}
}
<p><a th:href="@{/getPoint(point='15,58')}">类型转换器案例a>p>
servlet、filter、listener
默认不支持,需要在配置类中配置bean
配置三大组件
@Configuration
public class ServletConfig {
/**
* 注册servlet
*/
@Bean
public ServletRegistrationBean servletRegistrationBean(){
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
//设置Servlet对象
servletRegistrationBean.setServlet(new DemoServlet());
//设置路径映射
servletRegistrationBean.addUrlMappings("/demo");
//设置初始化参数
//单个
servletRegistrationBean.addInitParameter("msg", "hello");
//批量
// servletRegistrationBean.setInitParameters();
return servletRegistrationBean;
}
/**
* 注册Filter
*/
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new DemoFilter());
filterRegistrationBean.addUrlPatterns("/*");
// filterRegistrationBean.addInitParameter();
return filterRegistrationBean;
}
/**
* 注册Listener
*/
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean(){
ServletListenerRegistrationBean servletListenerRegistrationBean = new ServletListenerRegistrationBean();
servletListenerRegistrationBean.setListener(new DemoListener());
return servletListenerRegistrationBean;
}
}
DemoFilter.java
@WebFilter("/*")
public class DemoFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("DemoFilter执行了.........");
//过滤器放行
filterChain.doFilter(servletRequest, servletResponse);
}
}
DemoListener.java
@WebListener
public class DemoListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("DemoListener执行了.....");
}
}
DemoServlet.java
@WebServlet("/demo")
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DemoServlet.........." + msg);
resp.getWriter().write("ok");
}
private String msg;
@Override
public void init(ServletConfig config) throws ServletException {
msg = config.getInitParameter("msg");
}
}
public class CustomException extends RuntimeException{
}
/**
* 全局异常处理器
* @RestControllerAdvice:全局异常处理器的注解
*/
// @ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHander {
@ExceptionHandler(CustomException.class)
public Map<String, Object> customExceptionHandle(CustomException e){
Map<String, Object> map = new HashMap<>();
map.put("code", -2);
map.put("message", "自定义异常发生");
return map;
}
@ExceptionHandler(Exception.class)
public Map<String, Object> exceptionHandle(Exception e){
Map<String, Object> map = new HashMap<>();
map.put("code", -1);
map.put("message", "其他异常发生");
return map;
}
}
在SpringMVC使用@DateTimeFormat和@JsonFormat
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date hiredate;
application.yml
#全局输入日期格式化,局部@DateTimeFormat
spring:
mvc:
format:
date: yyyy-MM-dd HH:mm:ss
#全局输出日期格式化,局部@JsonFormat
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
#配置文件上传
spring:
servlet:
multipart:
#单个文件大小限制
max-file-size: 1MB
#单次请求总文件大小限制
max-request-size: 10MB
WebConfig.java配置文件
/**
* 前后端分离的项目:设置全局跨域处理
* 浏览器的同源策略:
* 在发送异步请求时,请求地址中 协议、服务器地址、服务器端口号必须保持一致
* 如果不一致就违反浏览器同源策略,浏览器禁止访问,会接收到一个CORS错误
*
* 注意:协议http与https不同源
* 地址localhost与127.0.0.1不同源
*
* 前后端分离的项目:设置全局跨域处理
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
//跨域访问的路径(资源)
.addMapping("/**")
//设置允许跨域的服务器地址
// .allowedOriginPatterns("http://localhost:63342")
.allowedOriginPatterns("*")
//设置允许跨域访问的请求方式
// .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS")
.allowedMethods("*")
//设置允许跨域访问时的头部信息
// .allowedHeaders()
//设置暴露给请求服务器头部信息
// .exposedHeaders()
//设置跨域访问时是否允许携带凭证(cookie中JSESSIONID)
.allowCredentials(true)
//跨域访问时会先发送一个询问请求(询问当前请求是否允许跨域)
//设置询问请求的发送周期
.maxAge(3600);
}
后端资源
@RestController
public class UserController {
@GetMapping("/user/list")
public List<User> list(){
User user1 = new User(1, "zhangsan", "123");
User user2 = new User(2, "lisi", "123");
User user3 = new User(3, "wangwu", "123");
User user4 = new User(4, "zhaoliu", "123");
return Arrays.asList(user1,user2,user3,user4);
}
}
前端请求(另一个项目)
$.ajax('http://localhost:8080/boot/user/list',{
type:'get',
success:function (res) {
var str='';
$.each(res,function () {
str+='<tr>';
str+='<td>'+this.id+'td>';
str+='<td>'+this.username+'td>';
str+='<td>'+this.password+'td>';
str+='tr>';
});
$('#tab').html(str);
}
});
外部Tomcat支持tomcat jsp,内部Tomcat不支持tomcat jsp
新建项目的时候与SpringBoot相似,唯一不同是打包方式改为war
自己配置TomCat
将静态资源文件放到 webapp/WEB-IF/
下面
自动生成ServletInitializer.java文件
/**
* 在外部tomcat启动服务器时加载springboot程序
* 如果把这个类去掉,不会启动springboot,也就无法使用@Controller等组件
*/
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringBoot05JspApplication.class);
}
}
可以使用 jsp 文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
首页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
成功
成功
${message}
Controller
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(HttpServletRequest request){
System.out.println("HelloController中的hello方法执行了....");
request.setAttribute("message", "hello jsp");
return "success";
}
}
application.yml
#配置jsp页面的前缀与后缀
spring:
mvc:
view:
prefix: /WEB-INF/pages/
suffix: .jsp
新建项目时除了选中工具和核心包外,还要选中IO中的Validation依赖
自动引入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
/**
* hibernate-validator框架,后台数据校验,通过注解的方式来实现
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Student {
/**
* @NotNull 数据不能为null
* @NotEmpty 数据不能为null,也不能为空字符串
* @NotBlank 数据不能为null,也不能为空字符串,也不能由空白字符组成
* @Size 校验字符串、数组、集合的长度
* @Range 校验数字的范围
* @Email 校验有效是否合法
* @Pattern 通过正则表达式校验
*
* 注解通用配置项:message,校验失败时提示信息
*/
@NotBlank(message = "姓名不能为空")
@Size(message = "姓名长度为4~10个字符", min = 4, max = 10)
private String name;
@NotNull(message = "年龄不能为空")
@Range(message = "年龄范围为0~100岁", min = 0, max = 100)
private Integer age;
@NotBlank(message = "邮箱不能为空")
//[email protected]
@Email(message = "邮箱格式不合法")
//正则校验
// @Pattern(message = "", regexp = "")
private String email;
}
开启数据校验
@RestController
public class ValidationController {
/**
* 开启校验 @Validated
*
* 在方法的参数上标注@Validated表示开启后台数据校验,每个开启的数据校验数据之后,需要跟随一个BindingResult类型的参数
* BindingResult对象用于接收校验失败的信息
*/
@PostMapping("/save")
public String save(@Validated Student student, BindingResult bindingResult){
//判断校验是否通过
if(bindingResult.hasErrors()){
List<ObjectError> allErrors = bindingResult.getAllErrors();
for (ObjectError error : allErrors) {
System.out.println(error.getDefaultMessage());
}
}else{
System.out.println(student);
}
return "ok";
}
}
application.yml
#用于校验配置文件
user:
username: zhangsan
age: 20
email: [email protected]
配置类
@SpringBootApplication
//使配置类的注解生效
@EnableConfigurationProperties(UserProperties.class)
public class Springboot06ValidationApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot06ValidationApplication.class, args);
}
}
@Data
@ConfigurationProperties(prefix = "user")
//添加批量读取配置文件的类上
@Validated
public class UserProperties {
@NotBlank(message = "用户名不能为空")
@Size(message = "用户名长度为6~16个字符", min = 6, max = 16)
private String username;
@NotNull(message = "年龄不能为空")
@Range(message = "年龄范围为0~100岁", min = 0, max = 100)
private Integer age;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不合法")
private String email;
}
可以参考JDK手册:java.util.regex / Pattern
后端使用正则表达式
public class ParttenTests {
@Test
public void run(){
/**
* 正则表达式,验证字符串是否符合指定的规则
*/
//1.String类
String str = "zhang#123";
System.out.println(str.matches("[abc]"));
System.out.println(str.matches("[^abc]"));
System.out.println(str.matches("[a-zA-Z]"));
System.out.println(str.matches("[0-9]"));
System.out.println(str.matches("[a-zA-Z0-9]"));
System.out.println(str.matches("\\S"));
System.out.println(str.matches("\\w{5,10}"));
System.out.println(str.matches(".{5,10}"));
System.out.println(str.matches(".*"));
System.out.println("14345678901".matches("^1[3|5|6|7|8|9]\\d{9}$"));
//2.Pattern类
boolean result = Pattern.matches("^[0-9]+$", "123");
System.out.println(result);
//3.Matcher类
Pattern pattern = Pattern.compile("^[0-9]+$");
Matcher matcher = pattern.matcher("123a");
System.out.println(matcher.matches());
}
}
前端使用正则表达式
<script type="text/javascript">
var regex = /^[0-9]+$/;
var result = regex.test('123');
alert(result);
script>
使用注解
//正则校验
// @Pattern(message = "", regexp = "")
private String email;
引入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
Controller
@RestController
public class AopController {
@GetMapping("/list")
public String list(){
System.out.println("AopController中的list方法....");
return "ok";
}
}
AopAspect.java
/**
* 切面类
*/
@Component
@Aspect
// @Order(1) //设置切面的启动顺序
public class AopAspect {
//公共切点表达式,方式一
public static final String POINT_CUT = "execution(* com.bjpowernode.controller.*.*(..))";
//公共切点表达式,方式二
@Pointcut("execution(* com.bjpowernode.controller.*.*(..))")
public void exp(){}
/**
* 前置通知
*/
@Before("execution(* com.bjpowernode.controller.*.*(..))")
public void before(){
System.out.println("切面的前置通知...");
}
/**
* 后置通知
*/
@After(POINT_CUT)
public void after(){
System.out.println("切面的后置通知...");
}
/**
* 返回通知
*/
@AfterReturning(value = "exp()", returning = "result")
public void returning(Object result){
System.out.println("切面的返回通知..." + result);
}
}
创建项目选择 jdbc api和Mysql Dirver 依赖
application.yml
#使用jdbc
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/student
username: root
password: 111111
#?切换数据源,需要配置才能生效
type: com.alibaba.druid.pool.DruidDataSource
#数据源配置
initialSize: 5
minIdle: 10
maxActive: 50
maxWait: 30000
entity层 略
dao
public class DeptDaoImpl implements DeptDao {
/**
* 注入JdbcTemplate对象
* JdbcTemplate是spring-jdbc中提供的工具类,用于操作数据库
*/
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int insert(Dept dept) {
String sql="insert into dept(dname,loc) values(?,?)";
return jdbcTemplate.update(sql,dept.getDname(),dept.getLoc());
}
}
测试
@SpringBootTest
class Springboot08JdbcApplicationTests {
@Autowired
private DataSource dataSource;
//查看数据源配置信息
@Test
void contextLoads() {
//自带数据源是: HikariDataSource
System.out.println("数据源:"+dataSource);
}
/**
* 使用jdbc完成查询
*/
@Test
void testJdbc() throws SQLException {
Connection connection = dataSource.getConnection();
String sql="select deptno,dname,loc from dept where deptno=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,60);
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
int deptno = resultSet.getInt("deptno");
String dname = resultSet.getString("dname");
String loc = resultSet.getString("loc");
System.out.println("编号="+deptno+" 名字="+dname+" 地址="+loc);
}
resultSet.close();
preparedStatement.close();
connection.close();
}
}
引入依赖,版本号不能省略
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
配置文件按application.yml
#配置数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/student
username: root
password: 111111
#切换数据源,需要配置才能生效
type: com.alibaba.druid.pool.DruidDataSource
#数据源配置
initialSize: 5
minIdle: 10
maxActive: 50
maxWait: 30000
#开启监控: 监控stat,SQL防火墙wall,日志slf4j,需要配置
filters: stat,wall,slf4j
自定义的配置类
/**
* 自定义德鲁伊数据源配置类
*/
@Configuration
public class DruidConfig {
@Bean
//使用注解使配置文件的数据源生效
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource dataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
//可以在这配置,也可以使用配置文件配置
// druidDataSource.setInitialSize(10);
return druidDataSource;
}
/**
* sql监控的servlet
*/
@Bean
public ServletRegistrationBean servletRegistrationBean(){
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
servletRegistrationBean.addInitParameter("loginUsername","admin");
servletRegistrationBean.addInitParameter("loginPassword", "123");
return servletRegistrationBean;
}
/**
* sql监控过滤器
*/
@Bean
public FilterRegistrationBean filterRegistrationBean(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
//排除路径
filterRegistrationBean.addInitParameter("exclusions", "/druid/*,*.js,*.css,*.jpg,*.png");
return filterRegistrationBean;
}
}
引入依赖
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
配置
#使用自带启动类的德鲁伊
spring:
datasource:
#切换数据源
type: com.alibaba.druid.pool.DruidDataSource
druid:
#必要信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/student
username: root
password: 111111
#连接池基本信息
initial-size: 6
min-idle: 7
max-active: 15
max-wait: 20000
#sql监控
filter: stat,wall,slf4j
#serlvet
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-password: 111
login-username: root
#filter
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: "/druid/*,*.js,*.css,*.jpg,*.png"
封装了jdbc的工具
DeptDaoImpl.java
@Repository
public class DeptDaoImpl implements DeptDao {
/**
* 注入JdbcTemplate对象
* JdbcTemplate是spring-jdbc中提供的工具类,用于操作数据库
*/
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public int insert(Dept dept) {
String sql="insert into dept(dname,loc) values(?,?)";
return jdbcTemplate.update(sql,dept.getDname(),dept.getLoc());
}
@Override
public List<Dept> select() {
/**
* queryForList() 批量查询返回数据封装在map集合中
* query(sql, rowMapper) 批量查询返回数据封装在指定的实体对象中
*
* RowMapper 行映射器,将字段与实体中的属性对照
* BeanPropertyRowMapper 是RowMapper接口的实现类对象,根据字段名称与实体类中属性名称实现自动映射
*/
String sql = "select deptno, dname, loc from dept order by deptno desc";
//手动映射
// jdbcTemplate.query(sql, new RowMapper(){
// @Override
// public Dept mapRow(ResultSet rs, int rowNum) throws SQLException {
// Dept dept = new Dept();
// dept.setDeptno(rs.getInt("deptno"));
// dept.setDname(rs.getString("dname"));
// dept.setLoc(rs.getString("loc"));
// return dept;
// }
// });
RowMapper<Dept> rowMapper = new BeanPropertyRowMapper<>(Dept.class);
List<Dept> list = jdbcTemplate.query(sql, rowMapper);
return list;
}
@Override
public Dept selectById(Integer deptno) {
String sql = "select deptno, dname, loc from dept where deptno=?";
/**
* queryForObject(String sql, RowMapper rowMapper) 返回结果为单行多列
* queryForObject(String sql, Class requiredType) 返回结果为单行单列
*/
// int i = jdbcTemplate.queryForObject(sql, Integer.class);
RowMapper<Dept> rowMapper = new BeanPropertyRowMapper<>(Dept.class);
Dept dept = jdbcTemplate.queryForObject(sql, rowMapper, deptno);
return dept;
}
}
测试类
@SpringBootTest
class Springboot08JdbcApplicationTests {
@Autowired
private DataSource dataSource;
@Test
void contextLoads() {
//自带数据源是: HikariDataSource
//查看数据源配置信息
System.out.println("数据源:"+dataSource);
if (dataSource instanceof DruidDataSource){
DruidDataSource druidDataSource=(DruidDataSource) dataSource;
System.out.println(druidDataSource.getInitialSize());
System.out.println(druidDataSource.getMinIdle());
System.out.println(druidDataSource.getMaxActive());
System.out.println(druidDataSource.getMaxWait());
}
}
@Autowired
DeptDao deptDao;
@Test
void testInsert(){
Dept dept = new Dept();
dept.setDname("采购部");
dept.setLoc("深圳");
int result = deptDao.insert(dept);
System.out.println(result);
}
@Test
void testSelect(){
List<Dept> list = deptDao.select();
for (Dept dept : list) {
System.out.println(dept);
}
}
@Test
void testSelectById(){
Dept dept = deptDao.selectById(48);
System.out.println(dept);
}
}
创建项目时,加上MyBatisFramwork依赖
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.2.2version>
dependency>
数据库连接池依赖和分页插件
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>1.4.2version>
dependency>
配置文件
#配置数据源
spring:
jackson:
date-format: yyyy-MM-dd
time-zone: GMT+8
mvc:
format:
date: yyyy-MM-dd
datasource:
#切换数据源
type: com.alibaba.druid.pool.DruidDataSource
druid:
#必要信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/bjpowernode
username: root
password: root
#连接池基本信息
initial-size: 6
min-idle: 7
max-active: 15
max-wait: 20000
#sql监控
filter: stat,wall,slf4j
#serlvet
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-password: 111
login-username: root
#filter
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: "/druid/*,*.js,*.css,*.jpg,*.png"
#mybatis配置
#1.SqlSessionFactory配置bean -- 在自动化配置中已实现
#2.mapper代理对象配置bean -- 通过注解的方式来实现
mybatis:
#加载核心配置文件
# config-location: classpath:mybatis.xml
#加载mapper文件
mapper-locations: classpath:mapper/*.xml
# mapper-locations: classpath:mapper/**/*.xml
#类型别名
type-aliases-package: com.bjpowernode.entity
#全局参数: 与加载核心配置文件项冲突
configuration:
#开启下划线转驼峰
map-underscore-to-camel-case: true
#日志输出
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#插件:分页(单独配置)
#分页组件pagehelper
pagehelper:
#自动识别数据库,应用数据库方言
#mysql: select * from table_name limit offset,pageSize
#oracle: select * from (select *,rownum myrow from (select * from table_name) where rownum <= 10) where myrow >= 5
# auto-dialect: true
#合理化分页
reasonable: true
@SpringBootApplication
/**
* 批量配置mapper代理
* 需要指定dao接口所在包
*/
@MapperScans({
@MapperScan(basePackages = "com.bjpowernode.dao"),
@MapperScan(basePackages = "com.bjpowernode.dao2")
})
@MapperScan(basePackages = "com.bjpowernode.dao")
public class Springboot09MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot09MybatisApplication.class, args);
}
}
entity
@Data
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private Date hiredate;
private Double sal;
private Double comm;
private Integer deptno;
}
dao
/**
* 使用注解来配置mapper代理对象
*
* @Mapper
* 作用:为当前接口生成mapper代理对象,并将代理对象放入ioc容器
* 类似于spring中单个接口代理对象的配置
*/
@Mapper
public interface EmpDao {
List<Emp> select();
Emp selectById(Integer id);
int insert(Emp entity);
int update(Emp entity);
int delete(Integer id);
}
mapper
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjpowernode.dao.EmpDao">
<select id="select" resultType="emp">
select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp order by empno asc
select>
<select id="selectById" parameterType="int" resultType="Emp">
select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp where empno=#{empno}
select>
<insert id="insert" parameterType="com.bjpowernode.entity.Emp">
insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)
values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})
insert>
<update id="update" parameterType="com.bjpowernode.entity.Emp">
update emp set ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno}
where empno=#{empno}
update>
<delete id="delete" parameterType="int">
delete from emp where empno=#{empno}
delete>
mapper>
service
public interface EmpService {
Map<String, Object> page(Integer pageNumber, Integer pageSize);
Emp get(Integer id);
boolean save(Emp entity);
boolean update(Emp entity);
boolean remove(Integer id);
}
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpDao empDao;
@Override
public Map<String, Object> page(Integer pageNumber, Integer pageSize) {
PageHelper.startPage(pageNumber, pageSize);
PageInfo<Emp> pageInfo = new PageInfo<>(empDao.select());
Map<String, Object> pageMap = new HashMap<>();
pageMap.put("list", pageInfo.getList());
pageMap.put("total", pageInfo.getTotal());
return pageMap;
}
@Override
public Emp get(Integer id) {
return empDao.selectById(id);
}
/**
* springboot中事务管理
* 使用注解的方式来实现
*/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean save(Emp entity) {
return empDao.insert(entity) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean update(Emp entity) {
return empDao.update(entity) > 0;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean remove(Integer id) {
return empDao.delete(id) > 0;
}
}
Controller
@RestController
@RequestMapping("/emp")
public class EmpController {
@Autowired
private EmpService empService;
@GetMapping("/page")
public Map<String, Object> page(Integer pageNumber, Integer pageSize){
Map<String, Object> pageMap = empService.page(pageNumber, pageSize);
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "ok");
result.put("data", pageMap);
return result;
}
@GetMapping("/get/{id}")
public Map<String, Object> get(@PathVariable("id") Integer id){
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "ok");
result.put("data", empService.get(id));
return result;
}
@PostMapping("/save")
public Map<String, Object> save(@RequestBody Emp emp){
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "ok");
result.put("data", empService.save(emp));
return result;
}
@PutMapping("/edit")
public Map<String, Object> edit(@RequestBody Emp emp){
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "ok");
result.put("data", empService.update(emp));
return result;
}
@DeleteMapping("/remove/{id}")
public Map<String, Object> remove(@PathVariable("id") Integer id){
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "ok");
result.put("data", empService.remove(id));
return result;
}
}
引入依赖
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-boot-starterartifactId>
<version>3.0.0version>
dependency>
配置文件
#swagger自定义配置
#测试访问文档页面:http://localhost:8080/swagger-ui/index.html
swagger3:
base-package: com.dx.controller
name: xxx
url: https://gitee.com/
email: [email protected]
version: 1.0
group-name: dx
title: "标题 "
description: "描述信息"
terms-of-service-url: https://gitee.com/
license: cxs
license-url: https://gitee.com/
#时间格式
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mvc:
format:
date: yyyy-MM-dd HH:mm:ss
#解决swagger3.0和springboot整合的时问题
pathmatch:
matching-strategy: ant_path_matcher
读取配置的类
@Data
@ConfigurationProperties(prefix = "swagger3")
public class SwaggerProperties {
// 扫描的包
// 给这个包下面的接口创建文档
private String basePackage;
// 作者姓名
private String name;
// 作者主页链接
private String url;
// 作者邮箱
private String email;
// 版本号
private String version;
// 分组名称
private String groupName;
// 文档标题
private String title;
//文档描述
private String description;
// 组织地址
private String termsOfServiceUrl;
// 许可证
private String license;
// 许可链接
private String licenseUrl;
}
注入配置类,配置swagger
@Configuration
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerConfig {
@Autowired
private SwaggerProperties swaggerProperties;
/**
* 配置swagger中的标题,描述,联系人,联系方法...
*/
public ApiInfo getApiInfo(){
//创建联系人对象
Contact contact = new Contact(swaggerProperties.getName(), swaggerProperties.getUrl(), swaggerProperties.getEmail());
return new ApiInfoBuilder()
.contact(contact)
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.version(swaggerProperties.getVersion())
.license(swaggerProperties.getLicense())
.licenseUrl(swaggerProperties.getLicenseUrl())
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
.build();
}
/**
* swagger的配置,基础信息,设置接口路径等等
* RequestHandlerSelectors.basePackage()通过指定基础包来生成文档
* RequestHandlerSelectors.withMethodAnnotation()通过指定的方法上注解来实现生成文档
*/
@Bean
public Docket docket(){
return new Docket(DocumentationType.OAS_30)
.apiInfo(getApiInfo())
.select()
//文档的生成的位置,两种方式
// .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
}
实体
@Data
@ApiModel("学生实体")
public class Student {
@ApiModelProperty("学生编号")
private Integer id;
@ApiModelProperty("学生姓名")
private String name;
@ApiModelProperty("学生住址")
private String address;
@ApiModelProperty("出生日期")
private Date birthday;
}
Controller
配置对类的描述注解
配置对方法的描述的注解
对参数的注解
@RestController
@RequestMapping("/student")
public class StudentController {
@ApiOperation("分页+条件查询 学生信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNumber", value = "当前页码", required = false, dataType = "Integer",defaultValue = "1", paramType = "query"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, dataType = "Integer",defaultValue = "10", paramType = "query")
})
@ApiResponses({
@ApiResponse(code = 0, message = "成功"),
@ApiResponse(code = -1, message = "失败")
})
@GetMapping("/page")
public Result page(@RequestParam(value = "pageNumber",defaultValue = "1") Integer pagerNumber,
@RequestParam(value = "pageSize",defaultValue = "5") Integer pageSize,
Student student) {
System.out.println(pagerNumber);
System.out.println(pageSize);
System.out.println(student);
return Result.success();
}
@GetMapping("/get/{id}")
@ApiOperation("根据ID获取学生信息")
@ApiImplicitParam(name="id",value = "学生编号",required = true, dataType="Integer", paramType = "path")
public Result get(@PathVariable("id") Integer id) {
System.out.println(id);
return Result.success();
}
@PutMapping("/edit")
@ApiOperation("编辑学生信息")
public Result edit(@RequestBody Student student){
System.out.println(student);
return Result.success();
}
@DeleteMapping("/remove/{id}")
@ApiOperation("根据编号删除学生信息")
@ApiImplicitParam(name = "id", value = "学生编号", required = true, dataType = "Integer", paramType = "path")
public Result remove(@PathVariable("id") Integer id){
System.out.println(id);
return Result.success();
}
}
查看swagger页面
#测试访问文档页面:http://localhost:8080/swagger-ui/index.html
异步调用需要配置注解@Async
启动类 开启异步调用
//开启异步调用
@EnableAsync
案例:统计耗时
@Service
public class AsyncService {
/**
* 异步调用注解
* 在处理请求的业务时,其中核心业务必须在同步处理中完成
* 辅助业务可以在异步处理中完成
*/
@Async
public void task1(){
try {
long start = System.currentTimeMillis();
//模拟程序执行耗时
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("task1耗时:" + (end - start) + "毫秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void task2(){
try {
long start = System.currentTimeMillis();
//模拟程序执行耗时
Thread.sleep(2000);
long end = System.currentTimeMillis();
System.out.println("task2耗时:" + (end - start) + "毫秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void task3(){
try {
long start = System.currentTimeMillis();
//模拟程序执行耗时
Thread.sleep(3000);
long end = System.currentTimeMillis();
System.out.println("task3耗时:" + (end - start) + "毫秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@RestController
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping("/doAsync")
public Map<String, Object> doAsync(){
long start = System.currentTimeMillis();
//调用service中的三个任务方法
//同步:第一个方法完成之后才能调用第二方法...耗时:三个方法时间相加
//异步:三个方法仅调用,不再登录方法执行完毕,即可向下执行
asyncService.task1();
asyncService.task2();
asyncService.task3();
Map<String, Object> map = new HashMap<>();
long end = System.currentTimeMillis();
map.put("code", 200);
map.put("message", "调用方法成功,总耗时为" + (end-start) + "毫秒");
return map;
}
}
在启动类上开启定时任务
//开启定时任务
@EnableScheduling
service 定时任务注解
定时表达式
@Service
public class JobService {
/**
* @Scheduled
* 定时任务注解
* cron配置项,为定时表达式
* 秒 分 时 日 月 周 年(可选)
* *星号:表示每,每秒、每分、每时...
* ?问好:只能在日和周两个位置出现,排除冲突
* -中划线:表示一个范围
* ,逗号:表示一个列表值,比如在星期中使用1,2,4
*/
// @Scheduled(cron = "* * * ? * 1-5")
@Scheduled(cron = "0/5 * * ? * 1-5")
public void myJob(){
System.out.println("定时任务...");
}
}
io中的 java mail … 依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
开启邮箱pop3的服务,写配置文件
spring:
mail:
#邮箱服务器地址 qq:smtp.qq.com 网易163:smtp.163.com
host: smtp.qq.com
#授权码,邮箱-》设置-》账户-》POP3/AMTP服务,开启服务后会获得授权码
password: xxxxxceoibdaaaaa
username: [email protected]
default-encoding: UTF-8
发送简单的内容
@Autowired
private JavaMailSender javaMailSender;
/**
* 发送基本的内容(纯文本)
*/
@Test
void testSend() {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
//发件人
simpleMailMessage.setFrom("[email protected]");
//收件人
simpleMailMessage.setTo("[email protected]");
//主题
simpleMailMessage.setSubject("这是一个测试邮件20220812");
//邮件内容
simpleMailMessage.setText("测试内容2022-08-12");
javaMailSender.send(simpleMailMessage);
}
发送邮件工具类
/**
* 测试发送复杂内容,例如图片和附件等
*/
@Test
void testSend2() throws MessagingException {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
// 创建一个邮件工具,可以发送附件
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,true,"utf-8");
mimeMessageHelper.setFrom("[email protected]");
mimeMessageHelper.setTo("[email protected]");
mimeMessage.setSubject("这是一个携带了图片和附件的邮件20220812");
//拼接内容参数
StringBuilder sb = new StringBuilder();
sb.append(" springboot 测试邮件发送复杂格式o
");
sb.append("哈哈哈
");
sb.append("居中
");
sb.append("
"); //如果要插入图片src='cid:picture'
//设置内容,可以被html解析
mimeMessageHelper.setText(sb.toString(), true);
// 从本地磁盘中读取到图片 站位到内容中去
mimeMessageHelper.addInline("picture",new File("C:\\Users\\NINGMEI\\Desktop\\aaa\\ddd.jpg"));
// 添加附件
mimeMessageHelper.addAttachment("SpringBoot.doc",new File("D:\\course\\05-SpringBoot\\springboot\\document\\SpringBoot.doc"));
javaMailSender.send(mimeMessage);
}