推进网站集约化建设,wordpress投稿验证码,网站开发微信端,如何提高网站的曝光率百日筑基第十一天-看看SpringBoot
创建项目
Spring 官方提供了 Spring Initializr 的方式来创建 Spring Boot 项目。网址如下#xff1a;
https://start.spring.io/
打开后的界面如下#xff1a; 可以将 Spring Initializr 看作是 Spring Boot 项目的初始化向导#xff…百日筑基第十一天-看看SpringBoot
创建项目
Spring 官方提供了 Spring Initializr 的方式来创建 Spring Boot 项目。网址如下
https://start.spring.io/
打开后的界面如下 可以将 Spring Initializr 看作是 Spring Boot 项目的初始化向导它可以帮助开发人员在一分钟之内创建一个 Spring Boot 骨架非常的傻瓜式。
来解释一下 Spring Initializr 初始化界面中的关键选项。
1Project项目的构建方式可以选择 Mavenopen in new window安装方式可以戳链接 和 Gradle构建脚本基于 Groovy 或者 Kotlin 等语言来编写而不是传统的 XML。编程喵默认采用的 Maven。
2Language项目的开发语言可以选择 Java、KotlinJetBrains开发的可以在 JVM 上运行的编程语言、Groovy可以作为 Java 平台的脚本语言来使用。默认 Java 即可。
3Spring Boot项目使用的 Spring Boot 版本。默认版本即可比较稳定。
4Project Metada项目的基础设置包括包名、打包方式、JDK 版本等。
Group项目所属组织的标识符比如说 top.codingmoreArtifact项目的标识符比如说 coding-moreName默认保持和 Artifact 一致即可Description 项目的描述信息比如说《编程喵实战项目Spring BootVue 前后端分离项目》Package name项目包名根据Group和Artifact自动生成即可。Packaging 项目打包方式可以选择 Jar 和 WarSSM 时代JavaWeb 项目通常会打成 War 包放在 Tomcat 下Spring Boot 时代默认 Jar 包即可因为 Spring Boot 可以内置 Tomcat、Jetty、Undertow 等服务容器了。Java项目选用的 JDK 版本。
5Dependencies项目所需要的依赖和 starter。如果不选择的话默认只有核心模块 spring-boot-starter 和测试模块 spring-boot-starter-test。
生成zip文件解压 重要的包
spring-boot-devtools 热部署
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-devtools/artifactId
/dependency整合Lombok简化代码
dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.6/versionscopeprovided/scope
/dependency然后就可以这样用了
Getter
Setter
class CmowerLombok {private int age;private String name;private BigDecimal money;
}其中 scopeprovided就说明 Lombok 只在编译阶段生效。也就是说Lombok 会在编译期静悄悄地将带 Lombok 注解的源码文件正确编译为完整的 class 文件。
SpringBoot 2.1.x 版本后不需要再显式地添加 Lombok 依赖了。之后还需要为 Intellij IDEA 安装 Lombok 插件否则 Javabean 的 getter / setter 就无法自动编译也就不能被调用。不过新版的 Intellij IDEA 也已经内置好了不需要再安装。
Getter / Setter 用起来很灵活比如说像下面这样
class CmowerLombok {Getter Setter private int age;Getter private String name;Setter private BigDecimal money;
}ToString 注解可以生成 toString 方法
ToString
class CmowerLombok {private int age;private String name;private BigDecimal money;
}Data 注解可以生成 getter / setter、equals、hashCode以及 toString是个总和的选项。
Data
class CmowerLombok {private int age;private String name;private BigDecimal money;
}
Slf4j 可以用来生成注解对象你可以根据自己的日志实现方式来选用不同的注解比如说Log、Log4j、Log4j2、Slf4j 等。
Slf4j
public class Log4jDemo {public static void main(String[] args) {log.info(level:{},info);log.warn(level:{},warn);log.error(level:{}, error);}
}Builder 注解可以用来通过建造者模式来创建对象这样就可以通过链式调用的方式进行对象赋值非常的方便。
Builder
ToString
public class BuilderDemo {private Long id;private String name;private Integer age;public static void main(String[] args) {BuilderDemo demo BuilderDemo.builder().age(18).name(沉默王二).build();System.out.println(demo);}
}
Lombok 还提供了同步注解 Synchronized、自动抛出异常注解 SneakyThrows、不可变对象 Value、自动生成 hashCode 和 equals 方法的注解 EqualsAndHashCode等等
Lombok 用起来虽然爽但需要团队内部达成一致就是要用大家都用否则有些用了有些没用就会乱成一锅粥很影响代码的整体风格。
整合 MySQL 和 Druid
Mysql
对应pom.xml文件中的代码
dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdscoperuntime/scope
/dependency
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactId
/dependency在 application.yml 文件中添加数据库链接驱动信息
spring:datasource:username: codingmore-mysqlpassword: YyfR4TDxCwrjZ2Fsurl:jdbc: mysql://118.190.99.232:3306/codingmore-mysql?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalseSpringBootTest
Slf4j
class CodingmoreMysqlApplicationTests {Resourceprivate JdbcTemplate jdbcTemplate;Testvoid contextLoads() {String sql select * from user;ListUser users jdbcTemplate.query(sql, new RowMapperUser() {Overridepublic User mapRow(ResultSet rs, int rowNum) throws SQLException {User user new User();user.setId(rs.getInt(1));user.setAge(rs.getInt(age));user.setName(rs.getString(name));user.setPassword(rs.getString(password));return user;}});log.info(查询成功);log.info(用户{},users);}
}
Spring Boot 的测试类主要放置在 src/test/java 目录下面项目创建成功后Spring Boot 会根据项目名称自动为我们生成测试类。
比如说本次项目名为 codingmore-mysql那么测试类名为 CodingmoreMysqlApplicationTests。
SpringBootTest 注解能够测试我们的项目主类该项目为 CodingmoreMysqlApplication。
Test 注解是 junit 单元测试的注解表示该方法为测试方法。
JdbcTemplate 一个通过 JDBC 连接数据库的工具类spring-boot-starter-jdbc 依赖中包含了该类。
Resource 注解会帮我们在 Spring Boot 启动的时候注入一个 JdbcTemplate 的对象。
jdbcTemplate.query() 方法通过 SQL 语句和匿名内部类参数的形式执行 SQL 并查询结果集。
RowMapper 就是查询到的每一行数据对象我们可以通过重写 mapRow 方法将数据结果集封装到 User 对象上。
Druid
Druid 是阿里巴巴开源的一款数据库连接池结合了C3P0、DBCP 等 DB 池的优点同时还加入了日志监控。
Druid 包含了三个重要的组成部分
DruidDriver能够提供基于 Filter-Chain 模式的插件体系DruidDataSource高效可管理的数据库连接池SQLParser支持所有 JDBC 兼容的数据库包括 Oracle、MySQL 等。
第一步在 pom.xml 文件中添加 Druid 的依赖官方已经提供了 starter我们直接使用。
dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.1.23/version
/dependency第二步在 application.yml 文件中添加 Druid 配置。
spring:datasource: type: com.alibaba.druid.pool.DruidDataSourcedruid:#初始化连接池大小initial-size: 5#配置最小连接数min-idle: 5#配置最大连接数max-active: 200#配置连接等待超时时间max-wait: 60000#配置间隔多久才进行一次检测检测需要关闭的空闲连接单位是毫秒time-between-eviction-runs-millis: 60000#配置一个连接在池中最小生存的时间单位是毫秒min-evictable-idle-time-millis: 300000#测试连接validation-query: SELECT 1 FROM DUAL#申请连接的时候检测建议配置为true不影响性能并且保证安全test-while-idle: true#获取连接时执行检测建议关闭影响性能test-on-borrow: false#归还连接时执行检测建议关闭影响性能test-on-return: false#是否开启PSCachePSCache对支持游标的数据库性能提升巨大oracle建议开启mysql下建议关闭pool-prepared-statements: false#开启poolPreparedStatements后生效max-pool-prepared-statement-per-connection-size: 20#配置扩展插件常用的插件有stat:监控统计 log4j:日志 wall:防御sql注入filters: stat,wall,slf4j#打开mergeSql功能慢SQL记录connection-properties: druid.stat.mergeSql\true;druid.stat.slowSqlMillis\5000#配置DruidStatFilterweb-stat-filter:enabled: trueurl-pattern: /*exclusions: *.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*#配置DruidStatViewServletstat-view-servlet:url-pattern: /druid/*#登录名login-username: root#登录密码login-password: root第三步启动项目。在日志信息里可以看到 Druid 的初始化信息。 第四步通过 http://localhost:9002/druid/ 地址就可以在浏览器访问 Druid 的监控页面了用户名和密码是我们在配置文件里指定的 root 和 root登录后是这样的。 Spring 对事务的支持
Spring 支持两种事务方式分别是编程式事务和声明式事务后者最常见通常情况下只需要一个 Transactional 就搞定了代码侵入性降到了最低就像这样
Transactional
public void savePosts(PostsParam postsParam) {// 保存文章save(posts);// 处理标签insertOrUpdateTag(postsParam, posts);
}1编程式事务
编程式事务是指将事务管理代码嵌入嵌入到业务代码中来控制事务的提交和回滚。
你比如说使用 TransactionTemplate 来管理事务
Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {transactionTemplate.execute(new TransactionCallbackWithoutResult() {Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {try {// .... 业务代码} catch (Exception e){//回滚transactionStatus.setRollbackOnly();}}});
}再比如说使用 TransactionManager 来管理事务
Autowired
private PlatformTransactionManager transactionManager;public void testTransaction() {TransactionStatus status transactionManager.getTransaction(new DefaultTransactionDefinition());try {// .... 业务代码transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);}
}就编程式事务管理而言Spring 更推荐使用 TransactionTemplate。
在编程式事务中必须在每个业务操作中包含额外的事务管理代码就导致代码看起来非常的臃肿但对理解 Spring 的事务管理模型非常有帮助。
2声明式事务
声明式事务将事务管理代码从业务方法中抽离了出来以声明式的方式来实现事务管理对于开发者来说声明式事务显然比编程式事务更易用、更好用。
当然了要想实现事务管理和业务代码的抽离就必须得用到 Spring 当中最关键最核心的技术之一AOP其本质是对方法前后进行拦截然后在目标方法开始之前创建或者加入一个事务执行完目标方法之后根据执行的情况提交或者回滚。
声明式事务虽然优于编程式事务但也有不足声明式事务管理的粒度是方法级别而编程式事务是可以精确到代码块级别的。
Spring Boot 对事务的支持
只需要在业务层添加事务注解Transactional就可以快速开启事务。
也就是说我们只需要把焦点放在 Transactional 注解上就可以了。
Transactional 的作用范围
类上表明类中所有 public 方法都启用事务方法上最常用的一种接口上不推荐使用
Transactional 的常用配置参数
虽然 Transactional 注解源码中定义了很多属性但大多数时候我都是采用默认配置当然了如果需要自定义的话前面也都说明过了。
Transactional 的使用注意事项总结
1要在 public 方法上使用在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断如果目标方法不是public则TransactionAttribute返回null即不支持事务。
2避免同一个类中调用 Transactional 注解的方法这样会导致事务失效。
过滤器、拦截器、监听器
过滤器Filter当有一堆请求只希望符合预期的请求进来。拦截器Interceptor想要干涉预期的请求。监听器Listener想要监听这些请求具体做了什么。
过滤器
过滤敏感词汇防止sql注入设置字符编码URL级别的权限访问控制压缩响应信息
添加一个过滤器 MyFilter
WebFilter(urlPatterns /*, filterName myFilter)
public class MyFilter implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {long start System.currentTimeMillis();chain.doFilter(request,response);System.out.println(Execute cost(System.currentTimeMillis()-start));}Overridepublic void destroy() {Filter.super.destroy();}
}WebFilter 注解用于将一个类声明为过滤器urlPatterns 属性用来指定过滤器的 URL 匹配模式filterName 用来定义过滤器的名字。
MyFilter 过滤器的逻辑非常简单重写了 Filter 的三个方法在 doFilter 方法中加入了时间戳的记录。然后我们在项目入口类上加上 ServletComponentScan 注解这样过滤器就会自动注册。
拦截器
登录验证判断用户是否登录权限验证判断用户是否有权限访问资源如校验token日志记录记录请求操作日志用户ip访问时间等以便统计请求访问量处理cookie、本地化、国际化、主题等性能监控监控请求处理时长等
Slf4j
public class LoggerInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info(preHandle{}...,request.getRequestURI());return true;}Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}
一个拦截器必须实现 HandlerInterceptor 接口preHandle 方法是 Controller 方法调用前执行postHandle 是 Controller 方法正常返回后执行afterCompletion 方法无论 Controller 方法是否抛异常都会执行。
只有 preHandle 返回 true 的话其他两个方法才会执行。
如果 preHandle 返回 false 的话表示不需要调用Controller方法继续处理了通常在认证或者安全检查失败时直接返回错误响应。
再来一个 InterceptorConfig 对拦截器进行配置
Configuration
public class InterceptorConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggerInterceptor()).addPathPatterns(/**);}
}Configuration 注解用于定义配置类干掉了以往 Spring 繁琐的 xml 配置文件。
编写一个用于被拦截的控制器 MyInterceptorController
RestController
RequestMapping(/myinterceptor)
public class MyInterceptorController {RequestMapping(/hello)public String hello() {return 沉默王二是傻X;}
}RestController 注解相当于 Controller ResponseBody 注解ResponseBody 注解用于将 Controller 方法返回的对象通过适当的 HttpMessageConverter 转换为指定格式后写入到 Response 对象的 body 数据区通常用来返回 JSON 或者 XML 数据返回 JSON 数据的情况比较多。