Springboot 快速了解
springboot(一)
1、什么是springboot及其优点?
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
spring boot来简化spring应用开发,约定大于配置,去繁从简,just run就能创建一个独立的,产品级别的应用。
Spring Boot 优点非常多,如:
- 独立运行
- 简化配置
- 自动配置
- 无代码生成和xml配置
- 应用监控
2、spring、springmvc、springboot的区别?
**spring: **
一个IOC和AOP框架,项目中对象的管理权交给了容器。有七大模块。
springmvc:
是spring中的一个web模块。采用的mvc模式,通过DispatcherServer前端控制器、ModelAndView 模型和视图、ViewResolver视图解析器实现了web开发。
springboot:
Spring 和 SpringMVC 的问题在于需要配置大量的参数。Spring Boot 通过一个自动配置和启动的项来目解决这个问题。为了更快的构建产品就绪应用程序,Spring Boot 提供了一些非功能性特征。
3、springboot创建web工程
springboot不建议使用jsp作为开发模板,默认使用thymeleaf模板引擎作为动态网页技术。
工程目录:
resources目录:
static: 存放静态内容
templates:模板引擎的动态网页内容
application.properties: 全局配置文件
springboot中页面的加载顺序:
首页加载顺序:static > public > templates
错误页面加载:在static或 public或 templates中创建error目录,定义4xx.html、5xx.html即可
springboot中的启动器:
https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/reference/html/using-spring-boot.html#using-boot
Name | Description |
---|---|
spring-boot-starter | Core starter, including auto-configuration support, logging and YAML 核心启动器,包括自动配置支持、日志记录和YAML |
spring-boot-starter-activemq | Starter for JMS messaging using Apache ActiveMQ |
spring-boot-starter-amqp | Starter for using Spring AMQP and Rabbit MQ |
spring-boot-starter-aop | Starter for aspect-oriented programming with Spring AOP and AspectJ |
spring-boot-starter-artemis | Starter for JMS messaging using Apache Artemis |
spring-boot-starter-batch | Starter for using Spring Batch |
spring-boot-starter-cache | Starter for using Spring Framework’s caching support |
spring-boot-starter-data-cassandra | Starter for using Cassandra distributed database and Spring Data Cassandra |
spring-boot-starter-data-cassandra-reactive | Starter for using Cassandra distributed database and Spring Data Cassandra Reactive |
spring-boot-starter-data-couchbase | Starter for using Couchbase document-oriented database and Spring Data Couchbase |
spring-boot-starter-data-couchbase-reactive | Starter for using Couchbase document-oriented database and Spring Data Couchbase Reactive |
spring-boot-starter-data-elasticsearch | Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch |
spring-boot-starter-data-jdbc | Starter for using Spring Data JDBC |
spring-boot-starter-data-jpa | Starter for using Spring Data JPA with Hibernate |
spring-boot-starter-data-ldap | Starter for using Spring Data LDAP |
spring-boot-starter-data-mongodb | Starter for using MongoDB document-oriented database and Spring Data MongoDB |
spring-boot-starter-data-mongodb-reactive | Starter for using MongoDB document-oriented database and Spring Data MongoDB Reactive |
spring-boot-starter-data-neo4j | Starter for using Neo4j graph database and Spring Data Neo4j |
spring-boot-starter-data-r2dbc | Starter for using Spring Data R2DBC |
spring-boot-starter-data-redis | Starter for using Redis key-value data store with Spring Data Redis and the Lettuce client |
spring-boot-starter-data-redis-reactive | Starter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client |
spring-boot-starter-data-rest | Starter for exposing Spring Data repositories over REST using Spring Data REST |
spring-boot-starter-data-solr | Starter for using the Apache Solr search platform with Spring Data Solr |
spring-boot-starter-freemarker | Starter for building MVC web applications using FreeMarker views |
spring-boot-starter-groovy-templates | Starter for building MVC web applications using Groovy Templates views |
spring-boot-starter-hateoas | Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS |
spring-boot-starter-integration | Starter for using Spring Integration |
spring-boot-starter-jdbc | Starter for using JDBC with the HikariCP connection pool |
spring-boot-starter-jersey | Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web |
spring-boot-starter-jooq | Starter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc |
spring-boot-starter-json | Starter for reading and writing json |
spring-boot-starter-jta-atomikos | Starter for JTA transactions using Atomikos |
spring-boot-starter-jta-bitronix | Starter for JTA transactions using Bitronix. Deprecated since 2.3.0 |
spring-boot-starter-mail | Starter for using Java Mail and Spring Framework’s email sending support |
spring-boot-starter-mustache | Starter for building web applications using Mustache views |
spring-boot-starter-oauth2-client | Starter for using Spring Security’s OAuth2/OpenID Connect client features |
spring-boot-starter-oauth2-resource-server | Starter for using Spring Security’s OAuth2 resource server features |
spring-boot-starter-quartz | Starter for using the Quartz scheduler |
spring-boot-starter-rsocket | Starter for building RSocket clients and servers |
spring-boot-starter-security | Starter for using Spring Security |
spring-boot-starter-test | Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito |
spring-boot-starter-thymeleaf | Starter for building MVC web applications using Thymeleaf views |
spring-boot-starter-validation | Starter for using Java Bean Validation with Hibernate Validator |
spring-boot-starter-web | Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container |
spring-boot-starter-web-services | Starter for using Spring Web Services |
spring-boot-starter-webflux | Starter for building WebFlux applications using Spring Framework’s Reactive Web support |
spring-boot-starter-websocket | Starter for building WebSocket applications using Spring Framework’s WebSocket support |
spring-boot-starter-actuator | Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application |
spring-boot-starter-tomcat | Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web |
<!--springboot 核心启动器(自动配置、日志、YAML)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--springmvc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监视和管理应用程序-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--thymeleaf模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--springboot热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
第三方依赖添加到springboot中 :
https://mvnrepository.com/
<!--mybatis-springboot 启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!--druid 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
4、springboot中的jsp工程
- 创建工程,同时在main目录中创建以下目录:
# 工程目录
springboot-03
|--src
|--main
|--java
|--com.newer.springboot
|--config
|--controller
|--mapper
|--model
|--service
|--Springboot03Application
|--resources
|--static
|--templates
|--application.properties
|--webapp
|--WEB-INF
|--views
|--index.jsp
|--test
|--target
|--pom.xml
- 同时把webapp设置为工程中的Web Resource Directories
-
改pom.xml
<!--springboot默认不支持jsp,官网建议使用模板引擎--> <!--jsp依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- tomcat支持 --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <!-- 添加spring tomcat 否则jsp页面显示为下载--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
-
修改全局配置application.proteties
# 设置端口号 server.port=80 # 设置工程路径 http://localhost:8088/springboot # server.servlet.context-path=/springboot # 设置spring mvc spring.mvc.view.prefix=/WEB-INF/views/ spring.mvc.view.suffix=.jsp
-
编写Controller层:
@Controller public class UserController { @RequestMapping({"/index","/"}) public String index(){ return "index"; } }
-
使用idea中的maven插件启动项目
命令:mvn spring-boot:run
springboot(二)
需要了解
- springboot几种启动方式
- springboot中jsp工程的启动方式
- springboot+mybatis集成[重点]
- springboot静态资源管理
常见问题:
-
打不到jsp页面?
-
IDEA2018.3配置的maven版本3.3+以上,3.6.0以下
-
网络问题无法加载依赖
-
启动jsp工程:mvn spring-boot:run
-
-
返回的是页面的名称,不是真实的页面内容?
只能使用@Controller注解,不要使用@RestController或@ResponseBody
@Controller public class UserController { //设置欢迎页 http://localhost/springboot/index.jsp @RequestMapping({"/index","/"}) public String index(){ return "index"; } }
1、springboot三种启动方式
1) 直接运行main方法
2) 使用mvn插件或命令:mvn spring-boot:run
3) 打包后运行: java -jar 方式
打包命令:mvn package
运行命令:java -jar springboot-01-0.0.1-SNAPSHOT.jar
2、springboot中jsp工程的启动方式
-
使用mvn插件(使用的是内置tomcat): mvn spring-boot:run
-
配置外置的tomcat启动(了解)
a. 修改主启动类
@SpringBootApplication public class Springboot04Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(Springboot04Application.class); } public static void main(String[] args) { SpringApplication.run(Springboot04Application.class, args); } }
b. 配置外部tomcat运行war包:
解决tomcat控制台乱码问题:
在tomcat服务中修改vm options: -Dfile.encoding=UTF-8
3、springboot集成mybatis[重点]
-
创建数据表
create table t_user ( id int(10) auto_increment comment '编号' primary key, username varchar(50) default '' not null comment '用户名', password varchar(50) default '' not null comment '密码', createTime datetime not null on update CURRENT_TIMESTAMP comment '创建时间' ) comment 't_user' charset = utf8mb4;
-
改pom.xml
<!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--mybatis 集成 spring boot--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </dependency> <!--druid连接接--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.22</version> </dependency>
-
改配置文件application.properties
# 设置数据库 spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 # 设置mybatis(用于xml编码时) mybatis.type-aliases-package=com.newer.springboot.model mybatis.mapper-locations=classpath:/mapper/*.xml
-
写实体类
@Data public class User { private Integer id; private String username; private String password; private Date createTime; }
-
写mapper接口
@Mapper public interface UserMapper { @Select("select * from t_user where id = #{id}") User findById(@Param("id") Integer id); }
-
写service接口
public interface UserService { User findById(Integer id); }
-
写servicer接口的实现类
@Service public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Override public User findById(Integer id) { return userMapper.findById(id); } }
-
写controller层
@Controller public class UserController { @Autowired UserService userService; //设置欢迎页 http://localhost/springboot/index.jsp @RequestMapping({"/index","/"}) public String index(){ return "index"; } @RequestMapping("/getUser") @ResponseBody public User getUserById(){ User user = userService.findById(1); return user; } }
-
测试
4、springboot集成mybatis-plus
官网: https://mp.baomidou.com/
mybtais-plus 为简化开发而生,只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
-
创建数据表
-
改pom
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <!--对mybatis进行了增强--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.22</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
-
改全局配置文件application.properties
# 设置端口号 server.port=80 # 设置数据库 spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 # 设置mybatis mybatis.type-aliases-package=com.newer.springboot.model mybatis.mapper-locations=classpath:/mapper/*.xml
-
写实体类
@Data @TableName("t_user") public class User { @TableId private Integer id; private String username; private String password; @TableField("createTime") private Date createTime; }
-
mapper接口
@Mapper public interface UserMapper extends BaseMapper<User> { }
-
写servicer接
public interface UserService extends IService<User> { }
-
写servicer接口实现类
@Service("userService") public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService { }
-
写controller层
@RestController public class UserController { @Autowired UserService userService; @RequestMapping("/getUser") public User getUserById(){ User user = userService.getById(1); return user; } @RequestMapping("/getUserList") public List<User> getUsers(){ List<User> users = userService.list(); return users; } }
-
测试
5、springboot静态资源
官网: https://www.webjars.org/
方式一:常规方式
-
创建相应静态包
-
引用静态资源
<script src="${pageContext.request.contextPath}/js/jquery.js"></script>
方式二:webjars方式
-
修改pom.xml
<!--Webjars版本定位工具(前端)--> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId> </dependency> <!--jquery--> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.5.1</version> </dependency> <!--bootstrap--> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.4.1</version> </dependency>
-
引用webjars资源
<script src="webjars/jquery/jquery.js"></script> <link rel="stylesheet" href="webjars/bootstrap/css/bootstrap.css"/>
-
测试
Springboot(三)
需要了解:
-
springboot中的注解
-
springboot环境切换
-
分页
常见问题:
- 怎么处理表单重复提交
session: 会话对象。唯一的id
- 了解权限管理框架有哪些及区别?
appche shiro: java权限框架
spring-security: 以spring为基础
-
高并发解决订单编号的几种方式
-
标识列,主键,自动增长
-
随机数类
-
rownum、序列sequenct。
-
reids缓存 单线程,运行在内存中的nosql数据库
-
使用各大厂商的方案:雪花算法
springboot中的YAML文件
YAML是JSON的超集,springboot默认使用YAML文件作为应用程序的配置文件,配置文件名:application.yml
springboot多环境切换
开发的项目存在多个环境,比如开发环境(dev)、生产环境(prod)、测试环境(test)。
-
创建三个yml文件
application.yml – 主环境文件(相当于application-default.yml)
# 主环境切换 spring: profiles: active: dev
application-dev.yml – 开发环境文件
# 设置端口(注意在属性值之间加空格) server: port: 80 # 工程名称 spring: application: name: springboot
application-prod.yml – 生产环境文件
# 设置端口(注意在属性值之间加空格) server: port: 8088 # 工程名称 spring: application: name: springboot
springboot中的注解(重点)
系统中的注解
1. @SpringBootApplication: 运行项目
@SpringBootConfiguration -- 读取springboot中的配置文件
@EnableAutoConfiguration -- 读取自动配置中的配置文件
@ComponentScan -- 包扫描(默认把主包下的文件扫描进行)
- @Bean: 相当于实例化bena对象
- @Scope:bean的作用域
- @Configuration: 配置类相当于xml文件
- @ConfiguationProperties(“person”) :默认从全局文件中获取值
- @Value():给属性赋值
- @PropertySource() :用于加载指定属性值
- @ImportSource():用于加载xml文件
- @Import():用于引入带有@Configuration的java类
Spring Web中的注解
@ControllerAdvice
@CookieValue
@CrossOrigin
@DeleteMapping
@ExceptionHandler
@GetMapping
@InitBinder
@Mapping
@MatrixVariable
@ModelAttribute
@package-info
@PatchMapping
@PathVariable
@PostMapping
@PutMapping
@RequestAttribute
@RequestBody
@RequestHeader
@RequestMapping
@RequestParam
@RequestPart
@ResponseBody
@ResponseStatus
@RestController
@RestControllerAdvice
@SessionAttribute
@SessionAttributes
Mybatis中的注解
@Delete
@Insert
@Many
@Mapper
@One
@Param
@Result
@ResultMap
@Results
@ResultType
@Select
@Update
Mybatis中的分页
-
自己写分页工具类: PagerUitl.java
-
使用分页插件: PageHelper
官网:https://github.com/pagehelper/pagehelper-spring-boot
- 使用Mybatis-plus中的分页
Springboot(四)
-
全局异常处理
-
数据统一封装
-
swagger2接口文档
-
测试工具postman使用
数据统一封装
-
为什么要封装数据
为了提高开发组的效率,统一为APP端、Web端、Java端制定开发规范。
{ "code": "返回的状态码", "iserror":"是否有错误", "msg": "返回的信息描述", "data": "返回的数据" }
-
怎么封装
- 统一返回状态码:类似于200、404等。 可以2000、2404
区间 表示的错误 0000 表示响应成功 1000 ~ 1999 表示参数错误 2000 ~ 2999 表示用户错误 3000 ~ 3999 表示接口异常 4000 表示服务端错误 - 统一错误消息:与返回状态码写在同一个类中
/** * @desc: 状态码 * */ public enum EnumCode { /** * 200请求成功 */ OK(200, "请求成功"), /** * 303登录失败 */ LOGIN_FAIL(303, "登录失败"), /** * 400请求参数出错 */ BAD_REQUEST(400, "请求参数出错"), /** * 401没有登录 */ UNAUTHORIZED(401, "没有登录"), /** * 403没有权限 */ FORBIDDEN(403, "没有权限"), /** * 410已被删除 */ GONE(410, "已被删除"), /** * 423已被锁定 */ LOCKED(423, "已被锁定"), /** * 500服务器出错 */ INTERNAL_SERVER_ERROR(500, "服务器出错"), /** * 异常 */ EXCPTION_ERROR(4001, "异常"); private final Integer value; private final String text; private EnumCode(Integer value, String text) { this.value = value; this.text = text; } /** * 获取value */ public Integer getValue() { return this.value; } /** * 获取Text */ public String getText() { return this.text; } }
-
创建一个结果集返回类
/** * 统一响应的数据返回类 */ public class ResponseResult implements Serializable { private Integer code; private Boolean hasError; private String message; private Object data;
-
controller层
@RestController public class UserController { /** * restful 风格(不能使用动名,只能是名词) * 对于实体对象,通过url就能返应状态 * 请求方式+实体名 * <p> * getMapping: 获取数据 /users /user/1 * postMapping: 添加数据 /user * putMapping: 修改数据 /user/1 * deleteMapping: 删除数据 /user/1 * * @return */ @GetMapping("/users") public ResponseResult getUsers() { List<User> userList = new ArrayList<>(); userList.add(new User(1, "a", "123")); userList.add(new User(2, "b", "123")); userList.add(new User(3, "c", "123")); userList.add(new User(4, "d", "123")); userList.add(new User(5, "e", "123")); return new ResponseResult().setCode(200) .setHasError(false) .setMessage(null) .setData(userList); } // 演示错误返回结果 @GetMapping("/user/{id}") public ResponseResult getUserById(@PathVariable("id") int id) { return new ResponseResult() .setCode(2001) .setHasError(true) .setMessage("用户密码错误") .setData(null); } }
全局异常处理
-
什么是异常
程序中出现的错误,称为异常
分类:Error(硬件)和Exception(运行时异常)
-
全局异常类:BasicErrorController
SpringBoot内置了一个BasicErrorController对异常进行统一的处理,当在页面发生异常的时候会自动把请求转到/error。
也可以自定义页面内容,只需在classpath路径下新建error页面即可。
-
全局异常解析器:HandlerExceptionResolver
-
自定义异常
-
创建一个MyException类,继承Exception类
-
重写构造方法
-
-
统一异常处理器(GlobalErrorHandler)
@ControllerAdvice 限定范围 例如扫描某个控制层的包@RestControllerAdvice 全部异常处理返回json
@ExceptionHandler 指定异常 例如指定处理运行异常,用于方法上。
-
全局异常的开发步骤
-
自定义异常解析器继承HandlerExceptionResolver
/** * 自定义一个异常解析器 * 作用:统一处理框架中的异常信息 */ public class MyExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) { ModelAndView mv = new ModelAndView(); mv.setViewName("error"); if(e instanceof MyException){ mv.addObject("ex",e.getMessage()); }else if(e instanceof IOException){ mv.addObject("ex","IO流异常"); }else{ mv.addObject("ex", "未知异常"); } return mv; } }
-
创建统一的异常处理类(把controlelr中的一个异常处理方法提升到全局方法)
@ControllerAdvice public class MyExceptionHandler { @ExceptionHandler public String handlerException(Exception e, Model model){ if(e instanceof MyException){ model.addAttribute("ex", e.getMessage()); }else if(e instanceof Exception){ model.addAttribute("ex", "哈哈哈,我就是黑客!"); } return "/error/error"; } }
-
在controller层抛出异常
@RequestMapping("/hello") public String hello() throws Exception { throw new MyException("你的网站错误!"); // return "Hello World!"; }
总结:开发时只需要在mappr层、server层、controller层中抛出异常,不需要处理。
-
Swagger2的应用
-
改pom.xml
<!--Swagger 引入依赖--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.6.0</version> </dependency>
-
改应用程全局配置application.propertis
# swagger配置 swagger.enable = true
-
swagger全局配置
@Configuration @EnableSwagger2 public class Swagger2Config { @Value("${swagger.enabled}") private boolean enableSwagger; @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) //是否开启 .enable(enableSwagger) .select() //扫描的路径包,设置basePackage会将包下的所有被@Api标记类的所有方法作为api .apis(RequestHandlerSelectors.basePackage("com.newer.springboot.controller")) //指定路径处理PathSelectors.any()代表所有的路径 .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() //设置文档标题 .title("Spring-boot项目") //文档描述 .description("V1.0接口规范") //服务条款URL .termsOfServiceUrl("http://127.0.0.1:80/") //版本号 .version("1.0.0") .build(); } }
-
controller层使用
@RestController @Api(value="用户接口",description="用户接口测试") public class UserController { @RequestMapping("/hello") @ApiOperation(value="测试",httpMethod="GET",notes="测试") public String hello() throws Exception { throw new MyException("你的网站错误!"); // return "Hello World!"; } /** * restful 风格(不能使用动名,只能是名词) * 对于实体对象,通过url就能返应状态 * 请求方式+实体名 * <p> * getMapping: 获取数据 /users /user/1 * postMapping: 添加数据 /user * putMapping: 修改数据 /user/1 * deleteMapping: 删除数据 /user/1 * * @return */ @GetMapping("/users") @ApiOperation(value="查询所有用户",httpMethod="GET",notes="查看所有用户详情") public ResponseResult getUsers() { List<User> userList = new ArrayList<>(); userList.add(new User(1, "a", "123")); userList.add(new User(2, "b", "123")); userList.add(new User(3, "c", "123")); userList.add(new User(4, "d", "123")); userList.add(new User(5, "e", "123")); return new ResponseResult().setCode(200).setHasError(false).setMessage(null).setData(userList); } // 演示错误返回结果 @GetMapping("/user/{id}") @ApiOperation(value="根据id获取用户",httpMethod="GET",notes="查看用户错误演示") public ResponseResult getUserById(@PathVariable("id") int id) { return new ResponseResult() .setCode(2001) .setHasError(true) .setMessage("用户密码错误") .setData(null); } }
-
-
测试
http://localhost/swagger-ui.html
Swagger2+swagger-bootstrap-ui的使用(去了解)
Springboot(五)
-
Aop日志
-
快速实现事务
-
拦截器Intercepote
-
数据校验
了解部分:
-
定时任务
-
发送email
-
解决前后端分离项目的后台跨域问题
-
了解RestTemplate进行服务调用
springboot实现快速事务
-
什么是事务?
把多条sql语句当作一个逻辑执行单元,要么同时成功,要么同时失败!
-
事务四个特性
原子性(atomic):要么都成功,要么都失败
一致性(consistent):事务提交前后数据保持一致
隔离性(isolate):事务互相不影响
持久性(durable):一旦提交,永久保存,不能回滚 -
事务并发产生的问题:
脏读:一个事务读取另一个事务未提交的一条数据
幻读:一个事务读取另一个事务添加的多条数据
不可重复读:一个事务读取另一个事务修改的一条数据 -
事务4种隔离性(级别越低数字越小):
- 读未提交(READ_UNCOMMITED):一个事务可以读取另一个未提交事务的数据,隔离级别最差。
- 读已提交(READ_COMMITED):一个事务要等另一个事务提交后才能读取数据,可避免脏读,不可重复读。
- 可重复读(REPEATABLE_READ):就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读。
- 串行化(SERIALIZABLE):完全符合ACID原则,可避免脏读、不可重复读、幻读,但效率最差。
-
事务7种传播机制
传播行为 意义 REQUIRED 如果当前有事务则加入事务,如果没有事务,则创建一个新的(默认值) NOT_SUPPORTED 支持当前事务,如果没有当前事务,就以非事务方法执行,相当于没有事务 REQUIRES_NEW 不管是否存在事务,都创建一个新的事务,原来的方法挂起,新的方法执行完毕后,继续执行老的事务 MANDATORY 必须在一个已有的事务中执行,否则报错 NEVER 必须在一个没有的事务中执行,否则报错 SUPPORTS 其他bean调用这个方法时,如果声明了事务,则就用这个事务,如果没有声明事务,那就不用事务 NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作 在springboot开发时一般使用数据库的默认隔离级别和默认传播行为,源码如下:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional { @AliasFor("transactionManager") String value() default ""; @AliasFor("value") String transactionManager() default ""; // 默认传播行为 Propagation propagation() default Propagation.REQUIRED; // 默认隔离级别 Isolation isolation() default Isolation.DEFAULT; int timeout() default -1; boolean readOnly() default false; Class<? extends Throwable>[] rollbackFor() default {}; String[] rollbackForClassName() default {}; Class<? extends Throwable>[] noRollbackFor() default {}; String[] noRollbackForClassName() default {}; }
-
事务的注解
@Transactional : 一般用于service业务层
@Service("userService") @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false ) public class UserServiceImpl implements UserService { @Resource UserMapper userMapper; @Override public User findById(int id) { User user = userMapper.selectById(id); return user; } @Override public List<User> findAll() { return userMapper.selectAll(); } @Override public Boolean updateById(String username, int id) throws SQLException { Boolean flag = userMapper.updateById(username, id); // 事务默认只对运行时的异常有效 // SQLSQLException不是runtimeException的子类 throw new SQLException("修改失败"); // throw new RuntimeException("修改失败"); } }
-
springboot中的事务坑
默认只对运行时异常有效。对sqlException无效。
@Transactional(rollbackFor = Exception.class)
数据校验
-
为什么前后台都要进行数据校验?
前台校验可以解决用户输入问题,后台校验正确性和准确性,一般可以跳过前台的验证机制。为了避免网站受到攻击。
-
springboot中校验数据开发步骤
- 改pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
- 在model层的实体类上加注解
数据校验注解
@AssertFalse
@AssertTrue
@DecimalMax
@DecimalMin
@Digits
@Email
@Future
@FutureOrPresent
@Max
@Min
@Negative
@NegativeOrZero
@NotBlank
@NotEmpty
@NotNull
@Null
@Past
@PastOrPresent
@Pattern
@Positive
@PositiveOrZero
@Size日期格式化注解
@JsonFormat:后台传到前台的json格式的日期
@DateTimeFormat:前台传到后台的日期格式- 在controller层加校验注解
注解:@Validated
@PostMapping("/user") @ApiOperation(value = "添加用户", httpMethod = "POST", notes = "添加用户详情") public ResponseResult addUser(@Validated User user) { log.info("user===>"+user); return new ResponseResult().setCode(200).setHasError(false).setMessage(null).setData(null); }
统一日志管理
Spring Boot默认使用slf4j日志门面+LogBack日志实现,也可以切换为其它日志框架。
常见的日志框架有:JUL , JCL , Jboss-logging , logback , log4j , log4j2 , slf4j等等,他们的分类如下:
日志门面(日志的抽象层) | 日志实现 |
---|---|
JCL,SLF4J,Jboss-logging | Log4j , JUL(java.util.logging ) , Log4j2, Logback |
JCL是Apache公司开发的一个框架,Jakarta小组开发的,Spring Framework在使用,但是2014年已经停止更新了。SLF4J , Log4j , Logback是同一个人写的,这个人想优化Log4j,但是认为重新写比较麻烦,于是写了SLF4J这个抽象层日志框架,又写了Logback这个实现类。Log4j2也是Apache公司的,好多框架都没适配。Hibernate底层使用Jboss-logging实现。
在控制台打印日志
方式一:使用lombak日志注解
@Slf4j // 统一日志注解
方式二:
private static final Logger log = LoggerFactory.getLogger(UserController.class);
如何将日志信息存储到文件
# 日志文件路径
# logging.path=d:/workspace/springboot/mylog
# 日志文件名(默认名springboot.log)
# logging.file=mylog.log
如果两者都配置了:logging.file=mylog.log、logging.path=D:/data/mylog,此时并不会在d盘下生成日志文件,只会在项目的根目录下创建一个mylog.log的文件。
其原因是,没有logback-spring.xml配置文件,系统只认识logging.file,不认识logging.path。
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--定义日志保存的路径-->
<!--1.更改默认的logback.xml为logback-spring.xml
SpringBoot当看到logback-spring.xml文件存在的时候,才会启动日志的环境切换
logback.xml文件没法做到
2. 在需要切换的环境上增加springProfile标签
-->
<springProfile name="dev">
<property name="LOG_HOME" value="d:/logs/dev/" />
</springProfile>
<!--线上-->
<springProfile name="prd">
<property name="LOG_HOME" value="d:/logs/prd/" />
</springProfile>
<!--定义一个控制台输出器,名为console-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!--按pattern指定的格式输出日志,编码为UTF-8-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{30} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--定义一个日滚动(每天生成一份)的日志文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--按pattern指定的格式输出日志,编码为UTF-8-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{30} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 定义保存的文件名 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--%d{yyyy-MM-dd}代表每天生成一个新的日志-->
<fileNamePattern>${LOG_HOME}/mysprintboot_%d{yyyy-MM-dd}.log</fileNamePattern>
<!--日志最多保存90天,也就是90份-->
<maxHistory>90</maxHistory>
</rollingPolicy>
<!-- 在日滚动文件中,强制只保存错误级别以上信息 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 定义日志全局最低输出级别是INFO,同时向控制台和日滚动文件输出 -->
<root level="INFO">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
</configuration>
如何设置日志级别
日志级别总共有TRACE < DEBUG < INFO < WARN < ERROR < FATAL ,且级别是逐渐提供,如果日志级别设置为INFO,则意味TRACE和DEBUG级别的日志都看不到。Spring Boot默认级别就是INFO。
logging.level.root=warn
如何设置日志格式
logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n
logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n
日志格式如下:
占位符 | 描述 |
---|---|
%d{yyyy-MM-dd HH:mm:ss.SSS} | 日期 |
%5p | 日志级别,5位字符长度显示,如果内容占不满5位则内容右对齐并在左侧补空格 |
%-5p | 5位字符长度显示日志级别,如果内容占不满5位则内容左对齐并在右侧补空格 -代表左对齐 |
%logger | 日志所在包和类 |
%M | 日志所在方法名 |
%L | 日志所在代码行 |
%m | 日志正文 |
%n | 换行 |
AOP实现日志
-
项目中为什么要使用日志功能。
记录用户的一系列操作,存储到数据库中。
-
日志功能的实现方式
-
aop方式实现
-
拦截器实现
-
过滤器实现
-
-
AOP日志:
-
改pom.xml
<!-- Spring Boot Aop依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
-
创建一个Aspect通知类
写一个日志注解(非必需)
@Target({TYPE, METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface LoginLog { String value(); }
Aspect通知类
@Aspect // 切面 通知+切入点 @Component @Slf4j public class LoginAspect { // 指定切入点 @Pointcut("@annotation(com.newer.springboot.aop.LoginLog)") public void loginPointCat() { } // 保存登录之后的用户信息 // 后置通知 @AfterReturning("loginPointCat()") public void saveUserLog(JoinPoint joinPoint) { // 获得request对象 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); HttpSession session = request.getSession(); // 获取用户 // User user = (User) session.getAttribute("user"); // 获取参数 Object[] args = joinPoint.getArgs(); log.info("params:"+ Arrays.toString(args)); // 操作的方法: MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); String value = method.getAnnotation(LoginLog.class).value(); log.info("method:"+value); // 操作用户的IP String remoteAddr = request.getRemoteAddr(); log.info("ipAddress:"+remoteAddr); // 操作时间 // 存数据库 } }
-
在目标方法中使用
@RequestMapping("/login") @LoginLog("login") // 使用日志注解 public String login(Model model) { model.addAttribute("username", "admin"); model.addAttribute("password", "123456"); return "index"; }
-
拦截器实现日志
aop方式可以在任意类上实现日志业务的打印或存储,如果我们只需要controller层对日志处理,可以使用拦截器。步骤如下:
-
改pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.60</version> </dependency>
-
创建类实现HanlerInterceptor接口
/** * 登录日志拦截器 */ @Slf4j public class WebInterceptor implements HandlerInterceptor { // 方法执行前拦截 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 请求路径 String url = request.getRequestURI(); // 获取请求参数 String paramData = JSON.toJSONString(request.getParameterMap(),SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue); // 请求客户ip String clientIp = request.getRemoteAddr(); // 请求方式:get/post/put/delete String methodName = request.getMethod(); // 设置请求的开始时间 request.setAttribute("STARTTIME", System.currentTimeMillis()); StringBuffer content = new StringBuffer(); content.append("url="+url); content.append(" ,paramData=").append(paramData); content.append( ", clientIp=").append(clientIp); content.append(" ,HTTP_METHOD=").append(methodName); log.info("content:"+content); return true; // 拦截开关 } // 视图渲染前拦截 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } // 方法执行后拦截 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 响应状态 int status = response.getStatus(); //当前时间 long currentTime = System.currentTimeMillis(); long startTime = Long.valueOf(request.getAttribute("STARTTIME").toString()); System.out.println("time2:"+(currentTime - startTime)+"ms"); } }
-
配置拦截器
@Configuration public class WebConfig implements WebMvcConfigurer { @Bean public HandlerInterceptor handlerInterceptor() { return new WebInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(handlerInterceptor()) // 拦截所有方法 .addPathPatterns("/**") // 以下url不拦截 .excludePathPatterns("/", "/login", "/error", "/logout", "/static/**", "/error/**"); } }
Hu-tool工具包
官网:https://www.hutool.cn/
Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。
包含组件
模块 | 介绍 |
---|---|
hutool-aop | JDK动态代理封装,提供非IOC下的切面支持 |
hutool-bloomFilter | 布隆过滤,提供一些Hash算法的布隆过滤 |
hutool-cache | 简单缓存实现 |
hutool-core | 核心,包括Bean操作、日期、各种Util等 |
hutool-cron | 定时任务模块,提供类Crontab表达式的定时任务 |
hutool-crypto | 加密解密模块,提供对称、非对称和摘要算法封装 |
hutool-db | JDBC封装后的数据操作,基于ActiveRecord思想 |
hutool-dfa | 基于DFA模型的多关键字查找 |
hutool-extra | 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等) |
hutool-http | 基于HttpUrlConnection的Http客户端封装 |
hutool-log | 自动识别日志实现的日志门面 |
hutool-script | 脚本执行封装,例如Javascript |
hutool-setting | 功能更强大的Setting配置文件和Properties封装 |
hutool-system | 系统参数调用封装(JVM信息等) |
hutool-json | JSON实现 |
hutool-captcha | 图片验证码实现 |
hutool-poi | 针对POI中Excel和Word的封装 |
hutool-socket | 基于Java的NIO和AIO的Socket封装 |
可以根据需求对每个模块单独引入,也可以通过引入hutool-all
方式引入所有模块。
Maven安装
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.9</version>
</dependency>