SpringBoot
★ 特点
Spring Boot 简化新Spring应用的初始搭建以及开发过程,该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置
springboot = spring(项目管理框架)+springmvc(控制器框架)
- 创建独立的Spring应用程序
- 内嵌tomacat
- 简化maven的配置
- 自动配置
- 摒弃了xml形式的配置
★ 约束
★ 入口类解析
★ 注入语法
★ 配置文件的拆分
★ 项目构建
1、引入相关依赖
<!-- 继承springboot父级项目依赖(版本仲裁中心) -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.8.RELEASE</version>
</parent>
<!--web启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、创建springboot配置文件 application.yml
server:
port: 9999 #端口号
servlet:
context-path: /springboot #项目名
注意:
1.默认没有项目名
2.键和值之间相隔 tab
3.springboot 内嵌tomcat默认端口号 8080
3.创建入口类
@SpringBootApplication //注解: 这个类为springboot的入口类, 这个注解只能出现一次
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
4、创建controller
@RequestMapping("test")
@ResponseBody
public class AdminController {
@RequestMapping("test")
@ResponseBody
public String test(){
return "Hello Word";
}
}
5、点击 Application类左侧的启动按钮,启动项目测试
地址栏访问成功 显示数据:
★ springboot集成mybatis
1、引入相关依赖
<!--
mybatis对springboot的支持
不需要额外引入 mybatis的依赖
-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<!-- mysql相关依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
2、application.yml 配置文件
server:
port: 8989
servlet:
context-path: /springboot
spring:
datasource:
username: root #数据库用户名
password: root #数据库密码
type: com.alibaba.druid.pool.DruidDataSource #type
url: jdbc:mysql://localhost:3306/test #url
driver-class-name: com.mysql.jdbc.Driver #驱动
mybatis:
#扫描映射文件
mapper-locations: classpath:com/bz/mapper/**/*Mapper.xml
#实体类定义别名
type-aliases-package: com.bz.entity
此处有坑:
- 扫描映射文件时目录结构,不要在resources目录中用.来创建,要用/来创建,比如com/xiaoming/mapper,不是com.xiaoming.mapper
- 映射文件必须有包结构才支持通配
xml文件是放在src/main/resources下的,因为src/main/java目录默认只能编译java文件,不能编译mapper.xml
如果想把mapper.xml文件放在src/main/java下,那就在pom.xml配置一下
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
3、扫描dao
@SpringBootApplication
//dao 扫描
@MapperScan("com.bz.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
★ 测试
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2、测试代码
//springboot环境运行
@RunWith(SpringRunner.class)
//加载 入口类
@SpringBootTest(classes = Application.class)
public class SpringbootApplicationTests {
@Test
public void contextLoads() {
}
}
★ springboot集成jsp
- springboot框架默认推荐视图模板为 thymeleaf视图模板, 不支持jsp
1、引入依赖
<!-- 内部tomcat支持jsp的解析 -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
2、配置视图解析器
spring:
mvc:
view:
prefix: /
suffix: .jsp
3、上述的配置已经支持jsp试图, 但是通过入口类启动在idea中无法找到jsp
官方提供2种解决方案
① 使用插件的方式启动项目 (需引入插件)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
② 指定工作目录
4、jsp热部署
server:
servlet:
jsp:
init-parameters:
development: true #没有提示
★ 热部署(支持jsp及后台)
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
2、配置
① ctrl+alt+s
② ctrl+alt+shift+/
★ springboot实现切面编程
切面编程中的概念:
aop:在程序运行过程中,动态的生成代理对象,代理对象完成通用的额外的功能,被代理的对象(目标对象)完成核心功能
- Target(目标对象):被代理对象
- Advice(通知):处理目标方法以外的功能
- Pointcut(切入点):指定哪些包中的哪些类中的哪些方法
- Aspect(切面) :通知+切入点;指定哪些包中的哪些类中的哪些方法 添加额外功能
注意:只有组装成了切面,才会生成代理对象
切入点两种方法:
execution 精确到方法(细粒度) | execution(* com.bz.service. * . * (…)) |
---|---|
within 精确到类 | within(com.bz.service.*ServiceImpl) |
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、相关注解
3、实现代码(两种方式)
① 第一种
@Component//将交给springboot管理
@Aspect//声明当前类为一个切面
@Slf4j//通过@Slf4j获得log 必须引入lombok
public class MyAspect {
//前置通知+切入点组成切面
@Before("execution(* com.bz.service.*.* (..))")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();//方法名
Object[] args = joinPoint.getArgs(); //参数[]
Object target = joinPoint.getTarget(); //目标对象
log.info("---前置通知---");
log.info(name);
log.info(args.toString());
log.info(target.toString());
}
//后置通知
@After("execution(* com.bz.service.*.* (..))")
public void afert(JoinPoint joinPoint){
log.info("---后置通知---");
}
//环绕通知
@Around("execution(* com.bz.service.*ServiceImpl.* (..))")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
Object proceed = null;
try {
log.info("--前置通知--");
proceed = proceedingJoinPoint.proceed();
log.info("--后置通知--");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return proceed;
}
}
② 第二种 将切入点配合方法,然后调用方法就可以拿到切入点
@Component//将交给springboot管理
@Aspect//声明当前类为一个切面
@Slf4j
public class MyAspect2 {
//切入点配合方法
@Pointcut(value = "execution(* com.bz.service.*.* (..))")
public void pointcut(){}
//环绕通知+切入点 组成切面
@Around(value = "pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
Object proceed = null;
try {
log.info("--前置通知--");
proceed = proceedingJoinPoint.proceed();
log.info("--后置通知--");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return proceed;
}
}
★ logback日志
- logback 是由log4j创始人的又一个开源日志,相比于log4j更轻量级, 易用, 效率更高,规则和log4j一致
默认springboot引入了logback的依赖, 以及默认配置文件,可在application.yml中简单配置日志,如复杂日志设置可引入配置文件
logging:
level: #日志常用级别 debug < info < warn < error 日志级别越低打印日志量越详细
root: info #根日志 控制整个项目的日志
com.bz.dao: debug #子日志 具体某个包的日志
file: D:/java资料/test.log #指定输出的 文件夹 + 文件名
# path: D:/java资料/test1.log #只能指定文件夹,默认名 spring.log
pattern: #自定义布局
#控制台布局
console: '[%p] %d{yyyy-MM-dd HH:mm:ss} %m %n'
#在文件中的布局
file: '[%p] %d{yyyy-MM-dd HH:mm:ss} %m %n'
#注意:
# file 和 path 不能联合使用
# console + file 自定的布局一定加 ''
项目中使用日志——通过@Slf4j获得log ,必须引入lombok
注意:只能打印高于或等于根目录级别的,低于根目录级别将不再打印
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@Slf4j
public class test {
@Autowired
private EmpService empService;
@Test
public void test(){
List<Emp> emps = empService.queryAll();
log.debug("debug"); //低于跟日志级别将不再打印
log.info("info");
log.warn("warn");
log.error("error");
log.info("emp的信息{}",emps); //可将emps信息放到到花括号当中输出
}
}
★ 文件上传
form表单:
<form action="${pageContext.request.contextPath}/upl/upload" enctype="multipart/form-data" method="post">
<input type="file" name="files">
<br>
<input type="submit">
</form>
后台接收上传:
@Controller
@RequestMapping("/upl")
public class Upload {
@RequestMapping("upload")
public String upload(MultipartFile files, HttpSession session) throws IOException {
/*
* 上传步骤:
* 1.获取文件名-将文件名拼接时间戳(为了防止同一个文件上传多次发生覆盖)
* 2.获取文件上传路径(通过相对路径获取绝对路径)- 判断这个文件夹是否存在(存在 使用 | 不存在 创建)
* 3.上传
* */
String originalFilename = files.getOriginalFilename();//上传文件的真实名字
String name = new Date().getTime() + "-" + originalFilename;//文件名拼接时间戳
String realPath = session.getServletContext().getRealPath("/upload");//获取绝对路径
//判断文件夹是否存在
File file = new File(realPath);
if (!file.exists()) {
//不存在创建文件夹
file.mkdirs();
}
//上传 参数1:文件的路径 参数2:文件名
files.transferTo(new File(realPath, name));
return "index";
}
}
上传文件大小:
spring:
servlet:
multipart:
max-file-size: 10MB #单个文件大小 默认1MB
max-request-size: 90MB #同时上传多个文件大小 默认10MB
★ 文件下载
代码:
@Controller
@RequestMapping("dow")
public class Dowload {
@RequestMapping("download")
public void dowload(String name , HttpSession session, HttpServletResponse response) throws IOException {
//1.获取下载的路径
String realPath = session.getServletContext().getRealPath("upload");
//设置下载方式及文件名字的编码 参数一: 下载的位置 参数二: 下载形式(附件attachment 在线打开 inline)
response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode(name,"utf-8"));
//设置响应类型及编码格式
//动态获取文件类型: ① 获取下载文件的后缀 ② 根据后缀获取文件类型
String extension = FilenameUtils.getExtension(name); //返回值为后缀(没有. txt jpg xlsx)
String mimeType = session.getServletContext().getMimeType("." + extension);
response.setContentType(mimeType);
//2.通过输出流写出 参数1:拷贝的文件①路径 ②名字 参数2:如何拷贝
@Cleanup ServletOutputStream outputStream = response.getOutputStream();
FileUtils.copyFile(new File(realPath,name),outputStream);
}
}
★ 拦截器
1.创建拦截器
@Component
public class MyInterceptor implements HandlerInterceptor {
/* preHandle: 访问controller中的方法之前执行 应用场景:强制登录
* Object o : 访问的controller中的方法对象
* return : true: 放行 false: 结束当前请求
* */
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
Object user = httpServletRequest.getSession().getAttribute("user");//用户强制登录
if (user == null) {
//跳转登录界面
String contextPath = httpServletRequest.getContextPath();
httpServletResponse.sendRedirect(contextPath+"/login.jsp");
return false;
}
return true;
}
/* postHandle: 执行controller中的方法之后, 返回ModelAndView之前执行 应用场景:添加公用的数据
* Object o : 访问的controller中的方法对象
* ModelAndView modelAndView: controller中返回的Model,View封装的对象
* */
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
String viewName = modelAndView.getViewName();//拦截器中获取controller返回的视图名字
Map<String, Object> model = modelAndView.getModel();//拦截器中获取controller返回的数据
modelAndView.addObject("name","王五");//手动添加公用的数据
modelAndView.setViewName("index");//指定跳转的视图
}
/* afterCompletion: 页面响应完成之后执行, 无论是否有异常都会执行 应用场景:日志记录等
* Exception e: 异常对象
* */
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println(e.getMessage());
}
}
2.配置拦截器
@Component
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
/*
* 添加拦截器
* 参数拦截器注册对象 参数: 拦截器 拦截哪些请求 不包含哪些请求
* */
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/**").excludePathPatterns("/index2");
}
}
★ jackson全局日期格式
spring:
mvc:
date-format: yyyy-MM-dd hh:MM:ss #接收日期格式
jackson:
date-format: yyyy-MM-dd hh:mm:ss #响应日期格式
time-zone: GMT+8
★ 总结依赖,注解,配置