Java 持久层框架访问数据库的方式大致分为两种。一种以 SQL 核心,封 装一定程度的 JDBC 操作,比如: MyBatis。另一种是以 Java 实体类为核心,将实体类 的和数据库表之间建立映射关系,也就是我们说的 ORM 框架,如:Hibernate、Spring Data JPA
Spring Data JPA 是建立的 JPA 的基础之上的。
JPA 全称为 Java Persistence API(Java 持久层 API),它是 Sun 公司在 JavaEE 5 中提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具,来管理 Java 应用 中的关系数据,JPA 吸取了目前 Java 持久化技术的优点,旨在规范、简化 Java 对象的持久 化工作。很多 ORM 框架都是实现了 JPA 的规范,如:Hibernate、EclipseLink。也就是 JPA 统一了 Java 应用程序访问 ORM 框架的规范,而 Hibernate 是一个 ORM 框架,Hibernate 是 JPA 的一种实现,是一个框架。
Spring Data 是 Spring 社区的一个子项目,主要用于简化数据访问,其主要目标是使得 数据库的访问变得方便快捷。它不仅支持关系型数据库,也支持非关系型数据库。
Spring Data JPA 是在实现了 JPA 规范的基础上封装的一套 JPA 应用框架,虽然 ORM 框架都实现了 JPA 规范,但是在不同的 ORM 框架之间切换仍然需要编写不同的代码,而使 用 Spring Data JPA 能够方便大家在不同的 ORM 框架之间进行切换而不需要更改代码。 Spring Data JPA 旨在通过将统一 ORM 框架的访问持久层的操作,来提高开发人的效率。 Spring Data JPA 给我们提供的主要的类和接口
总的来说 JPA 是 ORM 规范,Hibernate、TopLink 等是 JPA 规范的具体实现,这样的好 处是开发者可以面向 JPA 规范进行持久层的开发,而底层的实现则是可以切换的。Spring Data Jpa 则是在 JPA 之上添加另一层抽象(Repository 层的实现),极大地简化持久层开发 及 ORM 框架切换的成本
Cors 跨域配置 在实际开发过程中我们经常会遇到跨域问题(如一个项目区访问另一个项目的接口),跨域其实是浏览器对于 ajax 请求的一种安全限制。目前比较常用的跨域解决方案有 3 种: Jsonp:最早的解决方案,利用 script 标签可以跨域的原理实现。 nginx 反向代理:利用 nginx 反向代理把跨域转为不跨域,支持各种请求方式。 CORS:规范化的跨域请求解决方案,安全可靠。
CORS:全称"跨域资源共享"(Cross-origin resource sharing)。CORS 需要浏览器和服 务器同时支持,才可以实现跨域请求,目前几乎所有浏览器都支持 CORS,IE 则不能低于 IE10。CORS 的整个过程都由浏览器自动完成,前端无需做任何设置,跟平时发送 ajax 请求 并无差异。实现 CORS 的关键在于服务器(后台),只要服务器实现 CORS 接口,就可以 实现跨域通信。
CORS 实现跨域也是非常简单的,事实上,SpringMVC 已经帮我们写好了 CORS 的跨 域过滤器:CorsFilter ,内部已经实现了判定逻辑,我们直接用就好了。 项目下新建 GlobalCorsConfig 类用于跨域的全局配置,代码如下:
@Configuration public class GlobalCorsConfig { @Bean public CorsFilter corsFilter() { //1.添加 CORS 配置信息 CorsConfiguration config = new CorsConfiguration(); //1) 允许接收的域,不要写*,否则 cookie 就无法使用了 config.addAllowedOrigin("http://localhost:8081"); //2) 是否发送 Cookie 信息 config.setAllowCredentials(true); //3) 允许的请求方式 config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); // 4)允许的头信息 config.addAllowedHeader("*"); //2.添加映射路径,我们拦截一切请求 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3.返回新的 CorsFilter. return new CorsFilter(configSource); } }
配置项目一:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jdbctemplate</groupId> <artifactId>jdbctemplate</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <!-- 声明项目配置依赖编码格式为 utf-8 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <fastjson.version>1.2.24</fastjson.version> </properties> <dependencies> <!--Spring Data Jpa依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!--mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <version>8.0.13</version><!--$NO-MVN-MAN-VER$ --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <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> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
server.port =8089 server.servlet.context-path=/ spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb?serverTimezone=UTC&autoReconnect=true spring.datasource.username=root spring.datasource.password=admin ##spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.database=MySQL spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.show-sql=true spring.initialSize=5 spring.minIdle=5 spring.maxActive=20 spring.maxWait: 60000 spring.timeBetweenEvictionRunsMillis=60000 spring.minEvictableIdleTimeMillis=300000 spring.validationQuery=SELECT 1 FROM DUAL spring.testWhileIdle=true spring.testOnBorrow=false spring.testOnReturn=false spring.poolPreparedStatements=true spring.filter.stat.enabled=true spring.filter.stat.log-slow-sql=true spring.filter.wall.enabled=true
package com.tszr.jpa.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "t_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "username", unique = true, nullable = false, length = 64) private String username; @Column(name = "password", nullable = false, length = 64) private String password; @Column(name = "email", length = 64) private String email; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
package com.tszr.jpa.dao; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import com.tszr.jpa.entity.User; public interface UserRepository extends JpaRepository<User, Integer> { /* 相当于select * from t_user where username = ? and password = ? */ public User findByUsernameAndPassword(String username, String password); @Query("select u from User u where u.username like %?1%") public List<User> getUserByUsername(@Param("username") String username); }
package com.tszr.jpa.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.alibaba.druid.pool.DruidDataSource; @Configuration public class Config { /* 把配置文件中 spring.datasource.initialSize 等属性和 DruidDataSource 中属 性 进行绑定 */ @ConfigurationProperties(prefix = "spring.datasource") @Bean public DruidDataSource druidDataSource() { return new DruidDataSource(); } }
package com.tszr.jpa.config; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; @Configuration public class DuridConfig { /** * 配置 Druid 的监控 1、配置一个管理后台的 Servlet,拦截登陆 * * @return */ @Bean public ServletRegistrationBean<StatViewServlet> statViewServlet() { ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<StatViewServlet>( new StatViewServlet(), "/druid/*"); Map<String, String> initParams = new HashMap<>(); initParams.put("loginUsername", "admin"); initParams.put("loginPassword", "123456"); initParams.put("allow", ""); // 允许所有访问 servletRegistrationBean.setInitParameters(initParams); return servletRegistrationBean; } // 配置一个 web 监控的 filter,哪些请求会被监控,哪些排除。 @Bean public FilterRegistrationBean<WebStatFilter> webStatFilter() { FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<WebStatFilter>(new WebStatFilter()); Map<String, String> initParams = new HashMap<>(); initParams.put("exclusions", "*.js,*.css,/druid/*"); bean.setInitParameters(initParams); bean.setUrlPatterns(Arrays.asList("/*")); return bean; } }
package com.tszr.jpa.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @Configuration public class GlobalCorsConfig { @Bean public CorsFilter corsFilter() { // 1.添加CORS配置信息 CorsConfiguration config = new CorsConfiguration(); // 1) 允许的域,不要写*,否则cookie就无法使用了 config.addAllowedOrigin("http://localhost:8081"); // 2) 是否发送Cookie信息 config.setAllowCredentials(true); // 3) 允许的请求方式 config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); // 4)允许的头信息 config.addAllowedHeader("*"); // 2.添加映射路径,我们拦截一切请求 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); // 3.返回新的CorsFilter. return new CorsFilter(configSource); } }
package com.tszr.jpa; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
启动第一个项目。 创建第二个项目。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cors</groupId> <artifactId>SpringCors</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <!-- 声明项目配置依赖编码格式为 utf-8 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <fastjson.version>1.2.24</fastjson.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
server.port=8081
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="jquery-1.8.3.js"></script> </head> <body> <input type="button" value="添加数据" onclick="addUser()"> <br> <input type="button" value="删除数据" onclick="deleteUser()"> <script> function addUser() { $.ajax({ type : 'post', /*访问15.3.2小节项目中的添加接口*/ url : 'http://localhost:8080/users', data : JSON.stringify({ "username" : "admin", "password" : "123456", "email" : "635498720" }), dataType : "json", contentType : "application/json;charset=UTF-8", success : function(msg) {} }) } function deleteUser() { $.ajax({ type : 'delete', /*访问15.3.2小节项目中的删除接口*/ url : 'http://localhost:8080/users/5', success : function(msg) {} }) } </script> </body> </html>
package com.tszr.springcors; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); } }