本文共 4306 字,大约阅读时间需要 14 分钟。
以往,我们用spring开发web应用时,需要:
- ①Maven或Gradle,SpringMVC和Servlet API;
- ②web.xml(声明了Spring的DispatcherServlet);
- ③启用了Spring MVC的Spring配置;
- ④控制器类;
- ⑤Tomcat等。
其中只有控制器与我们的应用有关,剩下的都是Spring开发Web程序必需的通用样板。
boot的精要四个核心:
- ①自动提供配置(在classpath里发现和自动配置JPA、Spring MVC、模板、安全等);
- ②起步依赖,它能帮忙引库(利用传递依赖解析(maven+gradle)把常用库聚合在一起(版本都经过测试,不会不兼容));
- ③命令行界面,无需构建(非必要组成,简化开发,检测要向classpath添加哪些起步依赖);
- ④Actuator(运行时检视程序内部,eg.上下文配置bean、环境变量、配置属性和命令行参数、线程状态、最近的HTTP请求跟踪、内存用量,垃圾回收,web请求+数据源用量等)。
spring boot不是应用服务器(是内嵌的servlet容器提供),没有实现JPA或JMS规范(是配置了某JPA实现),没引入代码生成(用了spring4的条件化配置+传递依赖解析(maven+gradle))。本质上,spring boot就是spring。
boot开发推荐使用.yml格式的配置文件+gradle,这里我们还是采用和原有项目兼容的properties文件+maven,以下为部分示例:
在配置文件中,需要注意spring.jpa.properties.hibernate.hbm2ddl.auto
的配置,不符合该规范的命名会报错。 server.port=8997server.contextPath=/boot-server# 数据库访问配置spring.datasource.primary.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.primary.driverClassName=com.mysql.jdbc.Driverspring.datasource.primary.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8spring.datasource.primary.username=testspring.datasource.primary.password=test## 显示Sqlhibernate.show_sql=true## 建表方式,must be spring.jpa.properties格式#出现Table 'test.user' doesn't existspring.jpa.properties.hibernate.hbm2ddl.auto=update# 方言spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
我们使用spring data JPA时,注意使用注解映射实体类时,要implements Serializable,同时我们会发现JPA进行表与表之间的关联时,会出现外键,即使可通过注解或其他方式,防止建表时创建外键,但查询的时候造样生成了,这时候可以通过@Transient
注解巧妙地避开该问题。
生成外键示例:
类{ ... @ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.EAGER) @JoinTable(name = "user_authority", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "authority_id", referencedColumnName = "id")) private Listauthorities;}
避开外键生成示例:
类{ ... @Transient private Listauthorities;}
该种方法,把强依赖关系放到业务逻辑控制,这也是高性能mysql强烈推荐的基于单表开发。
同时hibernate5也为我们提供了很强大的校验功能,即使我们的项目不适用spring data JPA(即hibernate方案),也可以在使用mybatis的同时,兼用其校验功能。我们需要创建一个校验类。当实体类校验填入的数据,不符合规范的时候,抛给异常类,以便在前端返回数据。 实体类示例:@NotEmpty(message = "姓名不能为空") @Size(min=2, max=20) @Column(nullable = false, length = 20) // 映射为字段,值不能为空 private String name; @NotEmpty(message = "邮箱不能为空") @Size(max=50) @Email(message= "邮箱格式不对" ) @Column(nullable = false, length = 50, unique = true) private String email; @NotEmpty(message = "账号不能为空") @Size(min=3, max=20) @Column(nullable = false, length = 20, unique = true) // 用户账号,用户登录时的唯一标识 private String username; @NotEmpty(message = "密码不能为空") @Size(max=100) @Column(length = 100) // 登录时密码** private String password;
抛出异常的类:
public class ConstraintViolationExceptionHandler { /** * 获取批量异常信息 */ public static String getMessage(ConstraintViolationException e) { ListmsgList = new ArrayList<>(); for (ConstraintViolation constraintViolation : e.getConstraintViolations()) { msgList.add(constraintViolation.getMessage()); } String messages = StringUtils.join(msgList.toArray(), ";"); return messages; }}
除了该方法,当然也可以使用自定义异常类+@RestControllerAdvice
注解&@ExceptionHandler
注解来实现向前端抛出校验异常的信息,非常灵活。
/** * 自定义异常 */public class RRException extends RuntimeException { private String msg; private int code = 500; public RRException(String msg) { super(msg); this.msg = msg; } ...}@RestControllerAdvicepublic class RRExceptionHandler { private Logger logger = LoggerFactory.getLogger(getClass()); /** * 处理自定义异常 */ @ExceptionHandler(RRException.class) public String handleRRException(RRException e){ return FastJsonUtil.error(e.getMsg()); } @ExceptionHandler(Exception.class) public String handleException(Exception e){ logger.error(e.getMessage(), e); return FastJsonUtil.error(e.getMessage()); } ...}
最后,需要熟悉JpaRepository查询方法名的规范,相比mybatis,开发效率确实提升不少(虽然mybatis也可自动生成代码)。
引自高性能mysql
:
很多高性能应用都会对关联查询进行分解——对每一张表进行单表查询,再将结果在应用程序关联。
优势有:
- ①让缓存效率更高(eg.应用已缓存id为1、2、3,那下次在进行in查询,可少几个id,可复用缓存结果);
- ②查询分解,可减少锁竞争;
- ③应用层做关联,更容易对数据库进行拆分,更容易做到高性能、可扩展;
- ④缓存的id将按照顺序进行查询,可能比随机关联更高效;
- ⑤可减少冗余查询,在数据库中关联查询可能需重复访问一部分数据;
- ⑥相当于应用中实现了哈希关联,而不是mysql的嵌套循环关联(某些场景哈希关联效率更高)。
参考:
《Spring Boot实战》作者: @nanphonfy
转载出处 :