2、添加依赖,pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
3、配置文件
server:
port: 80
servlet:
#项目发布路径 一般都是默认值/
context-path: /
spring:
datasource:
url: jdbc:mysql:///dbpms?serverTimezone=GMT%2B8&characterEncoding=utf8
username: root
password: 123456
thymeleaf:
cache: false
prefix: classpath:/templates/modules/
suffix: .html
#配置视图解析器
mvc: #引入mvn配置
view:
prefix: /WEB-INF/ # /默认代表根目录 src/main/webapp
suffix: .jsp
main:
banner-mode: off
aop:
proxy-target-class: false
#AOP异步加载配置
task:
execution:
pool:
core-size: 8
max-size: 256
keep-alive: 60000
queue-capacity: 256
thread-name-prefix: db-service-task-
mybatis:
#只要定义了别名包 之后的映射类型可以自动的完成拼接.
type-aliases-package: com.jt.demo.pojo
mapper-locations: classpath:/mapper/*/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.cy: debug
shiro:
loginUrl: /login.html
JAVAEE应用体系中繁重的配置、低下的开发效率、高难度的三方集成,复杂的部署流程等等一直被开发人员所诟病。即使是使用Spring这样的轻量级的资源整合框架,在实现其相对比较多的资源整合时,依旧需要大量的手动依赖管理,复杂的XML配置(还经常没有提示)。还有就是现在的软件生态应用也已经形成一定的规模,系统架构正在从单体架构,分布式架构,跨越到微服务架构。随着整个架构体系的变化,企业对技术的要求也在变化,现在的企业更注重技术的开箱即用,更注重技术在生态圈中的深度融合,更注重轻量级的运维。由此由此spring boot诞生。
SpringBoot 是一个基于spring框架的脚手架,在这个脚手架中已经做好了spring工程中需要的一些基础工作,例如一些基础依赖,配置,监控等功能.其主要作用就是为了简化spring对资源的整合过程.实现快速的业务开发.
Spring Boot核心特性.:
1)起步依赖(项目创建时已经整合好了一些基础依赖)
2)自动配置(将项目中的很多共性配置已经做好)
3)健康检查(为项目中bean对象的运行提供相关监控操作)
4)内嵌服务(在项目中可以直接嵌入一个tomcat服务,直接通过这个服务运行项目)
启动过程概要分析
SpringBoot工程启动时其简易初始化过程,如图所示:
在启动过程中底层做了哪些事情,大致描述如下:
1)基于配置加载类(通过ClassLoader将指定位置的类读到内存->底层通过线程调用IO从磁盘读取到内存)。
2)对类进行分析(创建字节码对象-Class类型,通过反射获取器配置信息)。
3)对于指定配置(例如由spring特定注解描述)的对象存储其配置信息(借助BeanDefinition对象存储)。
4)基于BeanDefinition对象中class的配置构建类的实例(Bean对象),并进行bean对象的管理(可能会存储到bean池)。
延迟加载
现在思考一个问题,对于ObjectPool这个类,假如项目启动以后,暂时不会用到这个池对象,是否有必要对其进行创建(默认是会创建的)?我们知道没必要,因为占用内存。那如何在启动时不创建此类对象呢?
借助Spring框架提供的延迟加载特性进行实现。例如,我们可以在需要延迟加载的类上使用@Lazy注解进行描述
对象作用域
@Scope默认就是单例(singleton)作用域,这个作用域会配合延迟加载(@Lazy)特性使用,表示此类的实例在需要时可以创建一份并且将其存储到spring的容器中(Bean池),需要的时候从池中取,以实现对象的可重用。假如一些对象应用次数非常少,可以考虑不放入池中,进而使用@Scope(“prototype”)作用域对类进行描述,让此类的对象何时需要何时创建,用完以后,当此对象不可达了,则可以直接被GC系统销
毁。
对象生命周期
1)@PostConstruct 注解描述的方法为生命周期初始化方法,在对象构建以后执行.
2)@PreDestroy 注解描述的方法为生命周期销毁方法,此方法所在的对象,假如存储到了spring容器,那这个对象在从spring容器移除之前会先执行这个生命周期销毁方法(prototype作用域对象不执行此方法).
依赖注入
@Autowired由spring框架定义,用于描述类中属性或相关方法(例如构造方法)。Spring框架在项目运行时假如发现由他管理的Bean对象中有使用@Autowired注解描述的属性或方法,可以按照指定规则为属性赋值(DI)。其基本规则是:首先要检测容器中是否有与属性或方法参数类型相匹配的对象,假如有并且只有一个则直接注入。其次,假如检测到有多个,还会按照@Autowired描述的属性或方法参数名查找是否有名字匹配的对象,有则直接注入,没有则抛出异常。最后,假如我们有明确要求,必须要注入类型为指定类型,名字为指定名字的对象还可以使用@Qualifier注解对其属性或参数进行描述(此注解必须配合@Autowired注解使用)
FAQ
spring入门该做什么?
a)创建maven项目
b)添加spring依赖?(spring-context,spring-web,…)
c)添加spring配置文件或者配置类?
d)对spring管理的资源进行配置,
e)编写单元测试对项目进行初步测试,…
整合jdbc
我们访问数据库时,需要通过TCP协议与数据库建立连接,连接使用完以后要释放连接,TCP协议是一个面向连接的协议,而建立连接需要三次握手,释放连接需要四次挥手,这个过程是比较耗时的,假如频繁访问数据库,每次都是直接与数据建立连接,会带来的很大的性能问题,对于这样的问题如何解决呢?连接池诞生了.
池化思想分析
池化思想是我们项目开发过程中的一种非常重要的思想,如整数池,字符串池,对象池、连接池、线程池等都是SpringBoot工程下HikariCP整合测试池化思想的一种应用,都是通过复用对象,以减少因创建和释放对象所带来的资源消耗,进而来提升系统性能。
SpringBoot工程下HikariCP整合测试
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
配置
spring.datasource.url=jdbc:mysql:///dbgoods?
serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root spring.datasource.password=root
//其他配置
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true spring.datasource.hikari.idle-
timeout=30000 spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
整合MyBatis
Mybatis是一个优秀的持久层框架,底层基于JDBC实现与数据库的交互。并在JDBC操作的基础上做了封装和优化,它借助灵活的SQL定制,参数及结果集的映射方式,更好的适应了当前互联网技术的发展。Mybatis框架的简单应用架构如图所示:
在SpringBoot脚手架工程中,Spring框架会基于MyBatis框架底层配置,创建SqlSessionFactory对象,然后再通过此工厂对象创建SqlSession,最后基于Springku框架为测试类注入SqlSession对象,接下来,我们可以通过SqlSession对象实现与数据库的会话了。(SqlSessionFactory由底层创建,spring整合mybatis需要将SqlSessionFactory配置在.xml文件)
最大的优势? (能够低成本的快速实现数据库中的数据操作)
开源 (免费-成本低)
简单 (操作步骤,参数映射,结果映射)
灵活 (动态SQL-可以更好适配不同需求-for,if,…)
稳定 (不会三天两头出错)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.12.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
spring.main.banner-mode=off
#spring datasource
spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml
#spring log
logging.level.com.cy=info
#logging.file.path=D:/TCGBIII/devlogs/
@Mapper
public interface GoodsDao {
int deleteObjects(@Param("ids") Integer... ids);
List<Goods> findGoods();
}
创建logger对象及配置
private static final Logger log= LoggerFactory.getLogger(DefaultGoodsDao.class);
logging.file.path=d:/TCGBIII/devlogs/
FAQ
1)Mybatis快速入门应用你做了什么?
a)创建maven项目
b)添加项目依赖?(mysql驱动,连接池依赖,日志,mybatis,…)
c)创建mybatis配置文件?(.xml)
d)配置连接池,事务管理,映射文件路径,…
e)编写pojo,dao等对象?
f)编写映射文件(XxxMapper.xml)?
e)编写测试类,进行单元测试
1.当项目做的越来越来大时,项目中业务就会变得越来越复杂,假如我们只使用一个对象去处理所有的业务,这个对象的复杂度就会更高并且难以维护,生活中和实际项目中对类似问题的解决方案往往"分而治之"的思想.来降低业务复杂度,提高其可维护性.那现在的问题的是如何分,
按照什么规则去分,这就需要有一定的设计,于是MVC设计思想诞生.
2.MVC 是什么?
1)分层设计思想
2)一种套路或设计模式
3)是Model,View,Controller单词的缩写
3.1)Model (业务逻辑对象)
3.2)Controller(控制逻辑对象)
3.3)View(显示逻辑对象)
3.Spring 框架中Web模块中的MVC设计
Spring中的Web模块基于MVC设计思想做了落地实现,其核心组件有:
1)DispatcherServlet (Spring MVC中核心控制器-Controller)
2)RequestMapping (封装的请求映射->url到具体handler及方法之间的映射)
3)Handler(请求处理器->负责处理Controller获取请求->可以将其理解为model)
4)ModelAndView (封装了业务数据和视图信息的对象)
5)ViewResolver (负责模板视图解析的对象->View)
4.SpringBoot工程中Web MVC 快速入门实现
1)创建项目module
2)添加项目依赖(spring web,thymeleaf)
3) 项目结构分析(static,templates)
4) 项目启动分析(启动运行启动类,检测服务是否启动ok)
5) 修改项目端口,重新启动分析
6)分别在static和templates目录中创建html页面然后进行访问测试
6.1)在static目录下直接创建index.html,启动服务后直接浏览器访问测试,测试ok.
6.2)在templates目录下创建default.html,启动服务后直接浏览器访问测试,404异常
6.3)在项目中定义TemplateController以及相关方法,在方法内部返回字符串default(
可以将这个字符串理解为view的名字),然后启动服务,基于方法上定义的请求url映射(@RequestMapping(“/doTemplateUI”))访问方法,检测测试输出。
<dependencies>
<!--web应用中的模板引擎,负责提供视图解析器,解析html模板
thymeleaf通过自定义标签属性的方式为html元素添加了更加强悍的一些功能-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--提供了spring框架web模板的依赖支持,并且默认内嵌了tomcat-->
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
spring.main.banner-mode=off
server.port=80
#spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.prefix=classpath:/templates/module/
#spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
FAQ
1)说说spring web模块请求的处理过程?
1.1)基于域名获取ip地址(例如:127.0.0.1)
1.2)基于ip地址找到网络中计算机(ip地址是网络中计算机的唯一标识)
1.3)基于端口找到tomcat服务(port是计算机中应用的唯一标识)
1.4)tomcat服务会基于thread并借助io读取网络http协议中请求数据
1.5)tomcat内部会创建请求(request)和响应(response)对象,用于封装请求和响应信息
1.6)tomcat会调用Filter对象对request数据进行过滤
1.7)Filter对request过滤以后,会将请求交给DispatcherServlet进行处理?
1.8)DispatcherServlet读取请求中的url,并基于url从requestMapping中找到对应的handler以及方法
1.9)DispatcherServlet基于反射技术调用handler方法
1.10)DispatcherServlet会将handler方法返回的view等相关信息进行封装,然后交给视图解析器进行解析
1.11)ViewResolver视图解析器对为view name添加前缀,后缀,并将model中数据填充到view中
1.12)DispatcherServlet 将视图解析器解析的结果封装到response对象,并将其响应到客户端。
2)templates目录存储什么文件(html模板文件)
3)templates目录的html页面可以在浏览器直接访问吗?不可以
4)static目录下一般可以放什么资源?(html/css/js/images)
5)templates目录和static目录下存放的html文件有什么不同吗?
5.1)static目录下的html可以直接在浏览器访问但不能被spring中视图解析器进行解析
5.2)templates目录的html页面不可以在浏览器直接访问但可以被spring的视图解析器进行解析,
从而为html赋予更多的能力(例如thymeleaf表达式,分支语句,循环语句,…)
6)thymeleaf是什么?(是一个以html作为模板的模板引擎,此引擎为html元素添加
额外属性并进行解析,然后对其进行赋能。springboot工程中对thymeleaf做了默认的支持与配置)
5.SpringBoot工程中Web MVC应用配置进阶
1)SpringBoot工程中thymeleaf模板引擎的前后缀配置
2)SpringBoot工程中页面自动刷新配置(修改页面内容后,不重启服务既可看到更新内容)
FAQ?
1)springboot工程中thymeleaf默认的前缀和后缀配置分别是什么?
1.1)前缀:spring.thymeleaf.prefix=classpath:/templates/
1.2)后缀:.html
2)springboot工程中thymeleaf的前缀可以自己指定吗?(可以,例如
spring.thymeleaf.prefix=classpath:/templates/)
3)SpringBoot工程中的static和templates目录中的html,默认对其内容修改以后,不重启服务,然后刷新访问地址,可以看到修改的内容吗?(不可以,假如希望看到,我们需要修改idea和springboot的配置文件)
3.1)假如是static目录,则需要让项目支持自动编译(build)和运行时编译(
compiler.automake.allow.when.app.running)。
3.2)假如是templates目录,则需在以上两个步骤的基础上,添加一个缓存配置(
spring.thymeleaf.cache=false)。
4)你能说说让我们页面更新以后可以不重启服务就看到修改结果的步骤吗?
4.1)检查file/settings/build/compiler/build project automatically
4.2)检查运行时编译(compiler.automake.allow.when.app.running)
4.3)检查springboot配置文件(spring.thymeleaf.cache=false)
4.4)重启tomcat服务,进行访问测试,修改内容,再刷新测试。
4.5)假如重启tomcat服务器以后,对html文件内容做了更新,还看不到更新,
则对项目重新rebuild,然后再重启tomcat进行测试
4.6)以上步骤还不可以解决你的刷新问题则重启idea(大招)
6.SpringBoot工程中响应数据的处理?
1)响应的数据都有什么?(静态资源数据-html/css/js/images/;动态数据-业务数据)
2)响应数据的封装?(ModelAndView)
2.1)通过model封装业务数据
2.2)通过view对象封装html页面
3)将响应的业务数据转换为JSON格式字符串写到客户端?
3.1)什么是json?(一种数据格式:{“key1”:“Value1”,“Key2”:“Value2”})
3.2)为什么要转换为json字符串?(跨平台-跨端,解析方便)
3.3)将方法返回值map,pojo对象转换为json写到客户端
FAQ?
1)ModelAndView是什么? (Spring MVC模块中默认提供一个封装响应数据的对象)
2)ModelAndView一般应用在什么场景呢?(响应数据既包含view又包含model)
3)你是如何理解JSON的?(就是一种支持跨端需求的轻量级数据格式而已)
4)SpringBoot工程中默认是如何将pojo,map等类似对象转换为json格式字符串的?(借助jackson)
5)@ReponseBody注解的作用是什么?(描述Handler中的方法,用于告诉底层应该如何对方法的
返回值进行处理,例如此注解描述的方法,其返回值肯定不是view,同时告诉底层方法返回值的转换
结果最终要写到响应体,然后传输到客户端)
6)@RestController注解的作用的是什么?(描述Handler类型,用于定义此类是一个Controller
请求处理对象,同时类中所有方法都默认添加@ResponseBody注解)
FAQ?
1)Spring MVC 控制层方法中的参数值都来自于哪个对象?request
2)Spring MVC 控制层方法参数中常用注解你知道有几个呢?
2.1)@RequestParam (定义参数规则,例如参数是否可选,指定获取哪个参数的值)
2.2)@DateTimeFormat (定义可以获取的日期的日期格式)
2.3)@RequestBody(表示参数可以接收客户端post请求提交的json原生数据)
2.4)@PathVariable(表示参数的值来自url中{}表达式中的数据)
3)Spring MVC控制方法上定义请求方式,请求url的注解你了解的有哪些?
3.1)@RequestMapping(value=“/doGet”,method=RequestMethod.GET)
3.2)@GetMapping(“/path”) 一般应用于查询数据的请求方式定义
3.3)@PostMapping(“/path”) 一般应用于添加数据的请求方式定义
3.4)@DeleteMapping(“/path”) 一般应用于删除数据的请求方式定义
3.5)@PutMapping(“/path”) 一般应用于更新数据的请求方式定义
1、Spring IOC相关注解
@Configuration 标识当前类是配置类
@ComponentScan 包扫描注解 扫描注解
@Bean 标识该方法的返回值交给Spring容器管理
@Scope 控制多例和单例
@Lazy 懒加载
@PostConstruct 初始化方法
@PreDestroy 销毁方法
@Component 将当前类未来的对象交给容器管理
@Autowired 按照类型进行注入
@Qualifier 按照名称进行注入
@Repository 标识持久层注解
@Service 标识Service层
@Controller 标识Controller层
@Mapper 持久层mapper接口实现类由mybatis创建,并交给容器管理
@MapperScan(“com.xxx.mapper”) mapper接口可不用添加@Mapper注解
@Value 为属性赋值 @Value(“${key}”)
@PropertySource 加载指定路径的配置文件properties
@RestControllerAdvice Controller层的全局异常处理
@ExceptionHandler 按照某种异常类型进行拦截
2、Spring AOP相关注解
@Aspect 标识当前类是一个切面类
@Pointcut 用于定义切入点表达式 表达式写法4种
@EnableAspectJAutoProxy 让AOP的注解有效果
@Before AOP-前置通知
@AfterReturning AOP-后置通知
@AfterThrowing AOP-异常通知
@After AOP-最终通知
@Around AOP-环绕通知
@Order(1) //可以利用order关键字 实现AOP的排序 数字越小越先执行.
@EnableAsync 在启动类的上面添加,配合@Async进行异步操作
@Async 业务方法需要执行异步操作,可在方法上面添加该注解
@Transactional Spring中用来控制事务
3、SpringMVC相关注解
@RestController 表示Controller类,同时要求返回值为JSON
@ResponseBody 将返回的数据转化为JSON串, 如果是字符串本身 原数据返回
@RequestMapping(“/hello”) 实现浏览器的请求路径与方法的映射
@GetMapping(“”) 只能接收GET请求类型
@DeleteMapping(“”) 只能接收DELETE请求类型
@PostMapping(“”) 只能接收POST请求类型
@PutMapping(“”) 只能接收PUT请求类型
@RequestParam 常用来处理简单类型的绑定,其原理是通过Request.getParameter() 获取参数值的。
@RequestBody 参数接收时,将JSON串转化为java对象 json中的key与对象的属性一致.
@PathVariable restFul结构,接收参数的注解.
@DateTimeFormat(pattern = “yyyy-MM-dd”)接受时间类参数
@CrossOrigin 允许跨域访问
4、lombok相关注解
@Data lombok动态生成get/set/toString/equals/hashcode等方法
@Accessors 控制是否开启链式加载结构
@NoArgsConstructor 生成无参构造方法
@AllArgsConstructor 生成全参构造方法
5、mybatis 持久层相关注解
@Mapper mybatis提供的注解将当前的接口交给Spring容器管理. Map<类名小写,JDK动态代理对象>
@MapperScan Mybatis中扫描指定包路径的接口 为其创建代理对象.
@Insert Mybatis 新增操作注解
@Update Mybatis 修改操作注解
@Delete Mybatis 删除操作注解
@Select Mybatis 查询操作注解
@SpringBootTest 该注解的作用在进行代码测试时启动spring容器,之后动态的获取对象 注意包路径 主启动类的同包及子包中.
@Param Mybatis中将参数封装为Map集合. @Param(“maxAge”) int maxAge
@Alias Mybatis中定义对象的别名 @Alias(“User”)
6、mybatis plus 相关注解
@TableName(“item_cat”) MybatisPlus注解POJO与数据表绑定 注意表名
@TableId(type = IdType.AUTO) MybatisPlus注解 标识主键/主键自增
@TableField(exist = false) MybatisPlus注解 标识属性是否存在,及名称是否一致**
在实际的java项目中我们创建的所有pojo类几乎都要为属性添加set/get/toString等相关方法,所有的日志记录相关类可能都要创建日志等对象,这些样板代码既没有技术含量,又影响着代码的美观,同时重复的编码过程会在无形中加大我们的工作量。 此时Lombok应运而生。
lombok简介
概述:Lombok是一个第三的Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来告诉编译过程中的编译工具,在源代码编译成字节码的过程中,在字节码中添加一些量样板代码。
常用注解分析
@Setter 用于为描述的类生成setter方法,不包含final修饰属性。
@Getter 用于为描述的类生成getter方法。
@ToString 用于为描述的类添加toString方法。
@EqualsAndHashCode 用于为描述的类,生成hashCode和equals方法。
@NoArgsConstructor 用于为描述的类生成无参的构造方法。
@AllArgsConstructor 用于为描述的类生成包含类中所有字段的构造方法。
@Data用于为描述的类生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Slf4J 用于为描述的类添加一个日志属性对象。
lombok安装
idea中的安装配置
第一步:打开idea的设置窗口,找到plugins菜单,搜索lombok进行安装,如图所示:
第二步:启动注解处理,如图所示:
第三步:重启idea(可选,有的idea版本需要)。
lombok在maven项目中应用
第一步:添加lombok依赖。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>annotationProcessor</scope>
</dependency>
第二步:在类上应用lombok注解。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods {
private Long id;
private String name;
private String remark;
private Date createdTime;
}
第三步:编写单元测试类检测Lombok注解应用
@Slf4j
@SpringBootTest
public class GoodsTests{
@Test
void testGoods(){
Goods g=new Goods();
g.setId(100L);
g.setName("Lombok");
log.info("id的值为{}",g.getId());
log.info("name的值为{}",g.getName());
}
}
热部署简介:Spring Boot 开发者为Spring Boot项目中提供了一个热部署(spring-boot-devtools)模块,支持项目的热部署(修改了某些资源以后无需重启服务),以提高开发效率.其底层其实是借助了两个类加载器做了具体实现,一个类加载器加载不变class,一个类加载器加载可能变化类,以提供类的热部署性能.
热部署环境初始化
IDEA工具中启动注册窗口(按ctrl+shift+alt+/),如图所示:
选择编译构建配置,如图所示:
热部署在项目中应用
在需要热部署的项目或module中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
依赖下载以后,可重启reload项目,然后当我们修改了src/main/java目录下的java文件或修改了src/main/resources目录下的配置文件时,默认都会重启你的web服务器,但是修改了测试类或html文件不会自动重启和部署。
健康监控简述:Spring Boot 中actuator模块提供了健康检查,审计、指标收集,HTTP跟踪等功能,可以帮助我们更好的管理和跟踪springboot项目。
健康监控配置实现
在需要使用健康监控的项目或module中,添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
添加完依赖以后,reload项目或module。
健康监控启动分析
启动项目,在浏览器中输入如下地址:(SpringBoot默认打开的监控选项有限)
http://localhost/actuator
其访问结果,如图所示:
还可以在actuator列出的选中中进行点击,例如访问health
http://localhost/actuator/health
其呈现结果,如图所示(其中up状态表示正常):
假如希望查看更多actuator选项,可以在spring boot中配置文件
application.properties中添加如下语句:
management.endpoints.web.exposure.include=*
然后,重启服务器,基于访问http://localhost/actuator地址…
在项目的开发中,不管是对底层的数据逻辑操作过程,还是业务逻辑的处理过程,还是控制逻辑的处理过程,都不可避免会遇到各种可预知的、不可预知的异常。处理好异常对系统有很好的保护作用,同时会大大提高用户的体验。
异常处理分析
概述:
Java项目中处理异常方式无非两种,要么执行trycatch操作,要么执行throw操作(抛给其它对象处理),无论采用哪种方式,其目的是让我们的系统对异常要有反馈。但现在的问题是我们如何让这种反馈代码的编写即简单又直观、友好。
处理规范
我们在处理异常的过程中通常要遵循一定的设计规范,例如:
捕获异常时与抛出的异常必须完全匹配,或者捕获异常是抛出异常的父类类型。
避免直接抛出RuntimeException,更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常(例如ServiceException)。
捕获异常后必须进行处理(例如记录日志)。如果不想处理它,需要将异常抛给它的调用者。
最外层的逻辑必须处理异常,将其转化成用户可以理解的内容。
避免出现重复的代码(Don’t Repeat Yourself),即DAY原则。
SpringBoot 工程下的异常处理
准备工作
第一步:创建项目或module,并添加web依赖,代码如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
第二步:修改项目访问端口为80,例如
server.port=80
第三步:定义Controller类,代码如下:
package com.cy.pj.arithmetic.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ArithmeticController {
@RequestMapping("doCompute/{n1}/{n2}")
@ResponseBody
public String doCompute(@PathVariable Integer n1,
@PathVariable Integer n2){
Integer result=n1/n2;
return "Result is "+result;
}
}
第四步启动项目进行访问测试
在浏览器地址栏输入http://localhost/doCompute/10/2,检测输出结果。
Result is 5
默认异常处理
在浏览器地址栏输入http://localhost/doCompute/10/0,检测输出结果。
对于这样的默认异常处理(spring boot提供),用户体验不太友好,为了呈现更加友好的异常信息,我们通常要对异常进行自定义处理。
自己try异常处理
在控制层方法中,我们可以进行try catch处理,例如:
@RequestMapping("doCompute/{n1}/{n2}")
@ResponseBody
public String doCompute(@PathVariable Integer n1,
@PathVariable Integer n2){
try{
Integer result=n1/n2;
return "Result is "+result;
}catch(ArithmeticException e){
return "exception is "+e.getMessage();
}
}
一个Controller类中通常会有多个方法,这样多个方法中都写try语句进行异常处理会带来大量重复代码的编写,不易维护。
Controller内部定义异常处理方法
在Controller类中添加异常处理方法,代码如下:
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public String doHandleArithmeticException(ArithmeticException e){
e.printStackTrace();
return "计算过程中出现了异常,异常信息为"+e.getMessage();
}
@ExceptionHandler注解描述的方法为异常处理方法(注解中的异常类型为可处理的异常类型),假如Controller类中的逻辑方法中出现异常后没有处理异常,则会查找Controller类中有没有定义异常处理方法,假如定义了,且可以处理抛出的异常类型,则由异常处理方法处理异常。
控制层中的全局异常处理类及方法定义
当项目由多个控制层类中有多个共性异常的处理方法定义时,我们可以将这些方法提取到公共的父类对象中,但是这种方式是一种强耦合的实现,不利于代码的维护。我们还可以借助spring框架中web模块定义的全局异常处理规范进行实现,例如定义全局异常处理类,代码如下:
package com.cy.pj.common.web;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public String doHandleArithmeticException(ArithmeticException e){
e.printStackTrace();
return "计算过程中出现了异常,异常信息为"+e.getMessage();
}
}
其中,@RestControllerAdvice 注解描述的类为全局异常处理类,当控制层方法中的异常没有自己捕获,也没有定义其内部的异常处理方法,底层默认会查找全局异常处理类,调用对应的异常处理方法进行异常处理。如图所示:
在基于C/S架构的编程模型中,客户端往往需要对服务端返回的数据,基于状态的不同进行不同的处理。例如,正确的状态数据一种呈现方式,错误的状态数据是另外一种呈现方式。于是服务端响应数据的标准化设计油然而生。
响应标准设计
在响应数据标准化设计时,首先要对响应数据进行分析,哪些数据要响应到客户端,对这些数据进行怎样的状态设计等。假如现在响应的业务数据包含三部分:状态,消息,具体数据。我们可以这样设计,例如:
package com.cy.pj.common.pojo;
/**
* 基于此对象封装服务端响应到客户端的数据
*/
public class ResponseResult {
/**响应状态码(有的人用code)*/
private Integer state=1;//1表示ok,0表示error,.....
/**状态码对应的信息*/
private String message="ok";
/**正确的响应数据*/
private Object data;
public ResponseResult(){}
public ResponseResult(String message){//new ResponseResult("delete ok"),
this.message=message;
}
public ResponseResult(Object data){//new ResponseResult(list);
this.data=data;
}
public ResponseResult(Throwable e){//new ResponseResult(e);
this.state=0;
this.message=e.getMessage();
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
响应数据的封装
在Controller类的逻辑方法中进行正常的响应数据封装,例如:
package com.cy.pj.module.controller;
import com.cy.pj.common.pojo.ResponseResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ArithmeticController {
@RequestMapping("/doCompute/{n1}/{n2}")
public ResponseResult doCompute(@PathVariable Integer n1, @PathVariable Integer n2){
Integer result=n1/n2;
ResponseResult r=new ResponseResult("计算结果:"+result);
r.setData(result);
return r;
}
}
在全局异常处理对象中进行异常响应数据的封装,例如:
package com.cy.pj.common.web;
import com.cy.pj.common.pojo.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log= LoggerFactory.getLogger(GlobalExceptionHandler.class);//2
@ExceptionHandler(ArithmeticException.class)
public ResponseResult doHandleArithmeticException(ArithmeticException e){
e.printStackTrace();
log.info("exception {}",e.getMessage());
return new ResponseResult(e);//封装异常结果
}
}