1、springboot环境搭建
基本步骤:File——》new——》Project——》spring Initialzr——选择相关jar包配置——》选择本地路径——》OK
2、Spring Data JPA + Hibernate 集成
首先新建文件夹存储JPA相关配置。如下图。
pom.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.houseSearch</groupId>
<artifactId>house</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>house</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<!-- 使用自定义ES 版本 -->
<elasticsearch.version>5.6.1</elasticsearch.version>
<!-- thymeleaf 覆盖parent 选择自己的版本 -->
<thymeleaf.version>3.0.3.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
<thymeleaf-extras-springsecurity4.version>3.0.2.RELEASE</thymeleaf-extras-springsecurity4.version>
</properties>
<dependencies>
<!-- jpa相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 前端模板 thymeleaf 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>${thymeleaf.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<!-- SpringSecurity 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Thymeleaf方言支持SpringSecurity 依赖-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>${thymeleaf-extras-springsecurity4.version}</version>
</dependency>
<!-- redis session依赖 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- SpringBoot自带热加载开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.0</version>
</dependency>
<!-- 七牛依赖 -->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>[7.2.0, 7.2.99]</version>
</dependency>
<!-- ModelMapper Simple, Intelligent, Object Mapping. -->
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<!-- ES -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<!-- Kafka -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<!-- mail -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.2.3</version>
<!--<scope>system</scope>-->
<!--<systemPath>${project.basedir}/lib/aliyun-java-sdk-core-3.2.3.jar</systemPath>-->
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0.0</version>
<!--<scope>system</scope>-->
<!--<systemPath>${project.basedir}/lib/aliyun-java-sdk-dysmsapi-1.0.0.jar</systemPath>-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
JPA配置文件:
package com.housesearch.config;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
/** 加上Configuration成为配置类 */
@Configuration
/** 能够扫描到仓库类,用于取代xml形式的配置文件 */
@EnableJpaRepositories(basePackages = "com.housesearch.repository")
/** 开启事务支持 */
@EnableTransactionManagement
public class JPAConfig {
//建立数据源
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
//实体类的管理工厂
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
//实例化jpa适配器,由于使用的是hibernate所以用hibernatejpavendor
HibernateJpaVendorAdapter japVendor = new HibernateJpaVendorAdapter();
//不生成sql,自己掌握sql控制权
japVendor.setGenerateDdl(false);
//实例化管理工厂
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource());//设置数据源
entityManagerFactory.setJpaVendorAdapter(japVendor);//设置适配器
//设置扫描包名
entityManagerFactory.setPackagesToScan("com.housesearch.entity");
return entityManagerFactory;
}
//事务管理
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
application.properties配置文件
#JPAConfig
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/house?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root123
#控制台输出sql
spring.jpa.show-sql=true
#hibernate启动的时候只做sql表的格式验证
spring.jpa.hibernate.ddl-auto=validate
#打印debug级别的日志,因为默认情况下,spring boot从控制台打印出来的日志级别只有ERROR, WARN 还有INFO
logging.level.org.hibernate.SQL=debug
# session会话存储类型
spring.session.store-type=hash_map
# 关闭HTTP基本验证
security.basic.enabled=false
修改application文件验证项目启动是否成功
最后在控制台找到项目目录,输入mvn:spring-boot run或者idea直接启动,在浏览器输入如下成功启动。
对于启动方式有很多种,下面简单介绍下启动方式。
1、idea控制台输入:mvn spring-boot:run 启动项目
clean package spring-boot:run -Dmaven.test.skip=true
3、集成单元测试及H2
首先需要单元测试和h2数据库的依赖,上面pom.xml文件已经提供了,这里不做叙述。
一般单元测试都是直接和mysql数据库进行交互的,这里使用h2数据库,集成测试步骤如下:
新建实体类和 JPARepository,以及测试类UserRepositoryTest 如下图:
对应代码如下:
实体类user:
package com.houseSearch.entity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* Created by 小劭.
*/
@Entity
@Table(name = "user")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String password;
private String email;
//@Column用来标识实体类中属性与数据表中字段的对应关系
@Column(name = "phone_number")
private String phoneNumber;
private int status;
@Column(name = "create_time")
private Date createTime;
@Column(name = "last_login_time")
private Date lastLoginTime;
@Column(name = "last_update_time")
private Date lastUpdateTime;
private String avatar;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Transient
private List<GrantedAuthority> authorityList;
public List<GrantedAuthority> getAuthorityList() {
return authorityList;
}
public void setAuthorityList(List<GrantedAuthority> authorityList) {
this.authorityList = authorityList;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorityList;
}
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return name;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public Date getLastUpdateTime() {
return lastUpdateTime;
}
public void setLastUpdateTime(Date lastUpdateTime) {
this.lastUpdateTime = lastUpdateTime;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
}
UserRepository:
package com.houseSearch.repository;
import com.houseSearch.entity.User;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
/**
* Created by 小劭.
*/
public interface UserRepository extends CrudRepository<User, Long> {
User findByName(String userName);
User findUserByPhoneNumber(String telephone);
@Modifying
@Query("update User as user set user.name = :name where id = :id")
void updateUsername(@Param(value = "id") Long id, @Param(value = "name") String name);
@Modifying
@Query("update User as user set user.email = :email where id = :id")
void updateEmail(@Param(value = "id") Long id, @Param(value = "email") String email);
@Modifying
@Query("update User as user set user.password = :password where id = :id")
void updatePassword(@Param(value = "id") Long id, @Param(value = "password") String password);
}
UserRepositoryTest:
package com.houseSearch.entity;
import com.houseSearch.ApplicationTests;
import com.houseSearch.repository.UserRepository;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Created by 小劭.
*/
public class UserRepositoryTest extends ApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void testFindOne() {
User user = userRepository.findOne(1L);
Assert.assertEquals("小劭", user.getName());
}
}
这里测试类都是和mysql数据库交互的,还未创建h2数据库,下面新建h2数据库和修改一些配置文件的信息。其中把和mysql交互的配置信息放在application-dev.properties文件中,然后在application.properties文件上面加上 spring.profiles.active=dev,表示激活application-dev.properties配置文件。测试用例 ApplicationTests文件加上 @ActiveProfiles("test"),表示测试用例走的是 application-test.properties配置文件。
如下图
ApplicationTests配置文件如下:
package com.houseSearch;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@Configuration
//测试用例走的是 application-test.properties配置文件
@ActiveProfiles("test")
public class ApplicationTests {
@Test
public void test() {
}
}
application.properties配置文件如下
#激活application-dev.properties配置文件
spring.profiles.active=dev
#JPAConfig
#控制台输出sql
spring.jpa.show-sql=true
#hibernate启动的时候只做sql表的格式验证
spring.jpa.hibernate.ddl-auto=validate
#打印debug级别的日志,因为默认情况下,spring boot从控制台打印出来的日志级别只有ERROR, WARN 还有INFO
logging.level.org.hibernate.SQL=debug
# session会话存储类型
spring.session.store-type=hash_map
# 关闭HTTP基本验证
security.basic.enabled=false
application-dev.properties配置文件如下
# Mysql 注意替换相应配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/house?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root123
application-test.properties配置文件如下
spring.datasource.driver-class-name=org.h2.Driver
# 内存模式
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.schema=classpath:db/schema.sql
spring.datasource.data=classpath:db/data.sql
h2数据库语句如下:
schema.sql
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT(11) NOT NULL IDENTITY PRIMARY KEY ,
`name` VARCHAR(32) NOT NULL UNIQUE ,
`password` VARCHAR(32) NOT NULL ,
`email` VARCHAR(32) NOT NULL UNIQUE ,
`phone_number` VARCHAR(15) NOT NULL UNIQUE ,
`status` INT(2) NOT NULL ,
`avatar` VARCHAR(255),
`create_time` DATETIME NOT NULL DEFAULT NOW(),
`last_login_time` DATETIME NOT NULL ,
`last_update_time` DATETIME NOT NULL DEFAULT NOW()
);
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` INT(11) NOT NULL IDENTITY PRIMARY KEY ,
`user_id` INT(11) NOT NULL,
`name` VARCHAR(32) NOT NULL,
UNIQUE (`user_id`, `name`)
);
CREATE INDEX ON `role`(`user_id`);
DROP TABLE IF EXISTS `support_address`;
CREATE TABLE `support_address` (
`id` int(11) NOT NULL IDENTITY,
`belong_to` VARCHAR(32) NOT NULL,
`en_name` varchar(32) NOT NULL,
`cn_name` varchar(32) NOT NULL,
`level` varchar(16) NOT NULL,
`baidu_map_lng` DOUBLE NOT NULL ,
`baidu_map_lat` DOUBLE NOT NULL ,
PRIMARY KEY (`id`)
);
CREATE INDEX ON `support_address` (`belong_to`,`en_name`,`level`);
DROP TABLE IF EXISTS `house`;
CREATE TABLE `house` (
`id` int(11) NOT NULL IDENTITY COMMENT 'house唯一标识',
`title` varchar(32) NOT NULL,
`price` int(11) NOT NULL COMMENT '价格',
`area` int(11) NOT NULL COMMENT '面积',
`room` int(11) NOT NULL COMMENT '卧室数量',
`floor` int(11) NOT NULL COMMENT '楼层',
`total_floor` int(11) NOT NULL COMMENT '总楼层',
`watch_times` int(11) DEFAULT '0' COMMENT '被看次数',
`build_year` int(4) NOT NULL COMMENT '建立年限',
`status` int(4) NOT NULL DEFAULT '0' COMMENT '房屋状态 0-未审核 1-审核通过 2-已出租 3-逻辑删除',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`last_update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`city_en_name` varchar(32) NOT NULL COMMENT '城市标记缩写 如 北京bj',
`region_en_name` varchar(32) NOT NULL COMMENT '区域标记缩写 如 朝阳区cyq',
`cover` varchar(32) DEFAULT NULL COMMENT '封面',
`direction` int(11) NOT NULL COMMENT '朝向',
`distance_to_subway` int(11) NOT NULL DEFAULT '-1' COMMENT '距地铁距离 默认-1 附近无地铁',
`parlour` int(11) NOT NULL DEFAULT '0' COMMENT '客厅数量',
`district` varchar(32) NOT NULL COMMENT '所在小区',
`admin_id` int(11) NOT NULL COMMENT '所属管理员id',
`bathroom` int(11) NOT NULL DEFAULT '0' COMMENT '卫生间数量',
`street` varchar(32) NOT NULL COMMENT '街道',
PRIMARY KEY (`id`)
);
DROP TABLE IF EXISTS `house_detail`;
CREATE TABLE `house_detail` (
`id` int(11) NOT NULL IDENTITY,
`description` varchar(255) DEFAULT NULL COMMENT '详细描述',
`layout_desc` varchar(255) DEFAULT NULL COMMENT '户型介绍',
`traffic` varchar(255) DEFAULT NULL COMMENT '交通出行',
`round_service` varchar(255) DEFAULT NULL COMMENT '周边配套',
`rent_way` int(2) NOT NULL COMMENT '租赁方式',
`address` varchar(32) NOT NULL COMMENT '详细地址 ',
`subway_line_id` int(11) DEFAULT NULL COMMENT '附近地铁线id',
`subway_line_name` varchar(32) DEFAULT NULL COMMENT '附近地铁线名称',
`subway_station_id` int(11) DEFAULT NULL COMMENT '地铁站id',
`subway_station_name` varchar(32) DEFAULT NULL COMMENT '地铁站名',
`house_id` int(11) NOT NULL COMMENT '对应house的id',
PRIMARY KEY (`id`)
);
DROP TABLE IF EXISTS `house_tag`;
CREATE TABLE `house_tag` (
`house_id` int(11) NOT NULL COMMENT '房屋id',
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '标签id',
`name` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
);
data.sql
INSERT INTO `user`(`id`, `name`, `email`, `phone_number`, `password`, `status`, `last_login_time`) VALUES (1, '小劭',
'xiaoshao@imooc.com', '13888888888', 'wali', 1, NOW());
INSERT INTO `user`(`id`, `name`, `email`, `phone_number`, `password`, `status`, `last_login_time`) VALUES (2, 'admin',
'admin@imooc.com', '13999999999', '55b3d0936a3fb63168d57a6bda0ddbbf', 1, NOW());
INSERT INTO `role`(`id`, `user_id`, `name`) VALUES (1, 1, 'USER');
INSERT INTO `role`(`id`, `user_id`, `name`) VALUES (2, 2, 'USER');
INSERT INTO `role`(`id`, `user_id`, `name`) VALUES (3, 3, 'ADMIN');
-- address data
INSERT INTO `support_address`(`id`, `belong_to`, `en_name`, `cn_name`, `level`, `baidu_map_lng`, `baidu_map_lat`)
VALUES ('4', 'bj', 'bj', '北京', 'city', '116.395645','39.929986'),
('5', 'sh', 'sh', '上海', 'city', '121.487899', '31.249162'),
('6', 'hb', 'sjz', '石家庄', 'city', '114.522082', '38.048958'),
('7', 'hb', 'ts', '唐山', 'city', '118.183451', '39.650531'),
('8', 'hb', 'hd', '邯郸', 'city', '114.482694', '36.609308'),
('9', 'bj', 'dcq', '东城区', 'region', '116.42188470126446', '39.93857401298612'),
('10', 'bj', 'xcq', '西城区', 'region', '116.37319010401802', '39.93428014370851'),
('12', 'bj', 'hdq', '海淀区', 'region', '116.23967780102151', '40.03316204507791'),
('13', 'bj', 'cpq', '昌平区', 'region', '116.21645635689414', '40.2217235498323'),
('14', 'sh', 'ptq', '普陀区', 'region', '121.39844294374956', '31.263742929075534'),
('15', 'sjz', 'caq', '长安区', 'region', '114.59262155387033', '38.07687479578663'),
('16', 'sjz', 'qdq', '桥东区', 'region', '114.51078430496142', '38.06338975380927'),
('17', 'sjz', 'qxq', '桥西区', 'region', '114.43813995531943', '38.033364550068136'),
('18', 'sjz', 'xhq', '新华区', 'region', '114.4535014286928', '38.117218640478164'),
('19', 'bj', 'cyq', '朝阳区', 'region', '116.52169489108084', '39.95895316640668');
-- house data
INSERT INTO `house`(`id`, `title`, `price`, `area`, `room`, `floor`, `total_floor`, `watch_times`, `build_year`,
`status`, `create_time`, `last_update_time`, `city_en_name`, `region_en_name`, `cover`,
`direction`, `distance_to_subway`, `parlour`, `district`, `admin_id`, `bathroom`, `street`)
VALUES ('15', '富力城 国贸CBD 时尚休闲 商务办公 超棒瓦力', '6200', '70', '2', '10', '20', '2', '2005', '1', '2017-09-06 18:56:14', '2017-09-15 00:26:59', 'bj', 'hdq', 'FmD3zKG-gUPOrNv0HwzZN7IbkAC_', '2', '10', '1', '融泽嘉园', '2', '0', '龙域西二路'),
('16', '富力城 国贸CBD 时尚休闲 商务办公', '6300', '70', '2', '10', '20', '0', '2012', '1', '2017-09-06 19:53:35', '2017-09-11 00:35:13', 'bj', 'hdq', 'FmD3zKG-gUPOrNv0HwzZN7IbkAC_', '1', '-1', '1', '融泽嘉园', '2', '0', '龙域西二路'),
('17', '二环东直门地铁站附近、王府井、天安门、国贸、三里屯、南锣鼓巷', '3000', '35', '1', '5', '10', '0', '2013', '1', '2017-09-06 20:45:35', '2017-09-11 00:35:05', 'bj', 'hdq', 'FhVdDhzVDH1dLVVx4jOaVXOCfnea', '1', '200', '0', '融泽嘉园', '2', '0', '龙域西二路'),
('18', '华贸城 东向一居挑空loft 干净温馨 随时可以签约', '5700', '52', '1', '7', '20', '0', '2012', '1', '2017-09-06 21:01:02', '2017-09-11 00:35:01', 'bj', 'hdq', 'FsxiS6rOTpSg5pK7tv41e8Zpnn_c', '2', '1085', '1', '融泽嘉园', '2', '0', '龙域西二路'),
('19', '望春园板楼三居室 自住精装 南北通透 采光好视野棒!', '9200', '132', '3', '6', '14', '0', '2005', '1', '2017-09-06 22:44:25', '2017-09-11 00:34:55', 'bj', 'hdq', 'Fl1lNikhmMIecbTn-JTsurxugtFU', '2', '1108', '2', '融泽嘉园', '2', '0', '龙域西二路'),
('20', '高大上的整租两居室 业主诚意出租', '5400', '56', '2', '12', '20', '0', '2012', '1', '2017-09-06 23:39:50', '2017-09-11 00:34:21', 'bj', 'hdq', 'FtNl9uPM6p5PjEs8z2FnOuViNtOM', '2', '-1', '1', '融泽嘉园', '2', '0', '龙域西二路'),
('21', '新康园 正规三居室 精装修 家电家具齐全', '1900', '18', '1', '13', '25', '0', '2012', '1', '2017-09-07 00:52:47', '2017-09-11 00:34:13', 'bj', 'hdq', 'Fn9sHC3Wx7qpYCmSxt-z8FZluf0Z', '3', '1302', '0', '融泽嘉园', '2', '0', '龙域西二路'),
('24', '湖光壹号望京华府183-387㎡阔景大宅', '50000', '288', '5', '1', '1', '0', '2015', '1', '2017-09-07 11:42:20', '2017-09-18 20:14:14', 'bj', 'hdq', 'FvVqU8LneZZ5xaLBAOM1KXR2Pz1X', '5', '200', '3', '融泽嘉园', '2', '0', '龙域西二路');
-- house_detail data
INSERT INTO `house_detail` VALUES ('21', '国贸CBD商务区,近SOHO现代城,富顿中心,富力城商业街区,乐成中心,潘家园古玩城,八王坟长途客运站,北京游乐园,经由三环路可直达首都机场。附近有双井桥南,双井桥北,双井桥东双井桥西等30多条公交站牌!\n《天安门,故宫,王府井,三里屯,前门,天坛,北海,颐和园,雍和宫,奥林匹克公园,水立方,西单,欢乐谷,燕莎商城等》知名购物区及旅游名胜古迹,是您休闲旅游及商务下榻的理想选择', '房间采光良好,落地窗外景色宜人', '房子处于北京的CBD商务中心区国贸双井!紧邻双井地铁站,步行5分钟即到!这离国贸、中央电视台、潘家园、三里屯、团结湖、日坛使馆区、儿研所、大郊亭都很近', '房子闹中取静,地理位置优越,交通方便,紧邻呼家楼地铁站和东大桥地铁站;去机场可乘坐东直门机场快轨,非常方便。购物中心有双井购物中心、国贸购物中心和侨福芳草地购物中心、三里屯购物中心等,远道而来的朋友可尽览都市璀璨!', '0', '二号院7号楼', '4', '10号线', '58', '双井', '15'), ('22', '国贸CBD商务区,近SOHO现代城,富顿中心,富力城商业街区,乐成中心,潘家园古玩城,八王坟长途客运站,北京游乐园,经由三环路可直达首都机场。附近有双井桥南,双井桥北,双井桥东双井桥西等30多条公交站牌!\n《天安门,故宫,王府井,三里屯,前门,天坛,北海,颐和园,雍和宫,奥林匹克公园,水立方,西单,欢乐谷,燕莎商城等》知名购物区及旅游名胜古迹,是您休闲旅游及商务下榻的理想选择!', '房间采光良好,落地窗外景色宜人', '房子处于北京的CBD商务中心区国贸双井!紧邻双井地铁站,步行5分钟即到', '这离国贸、中央电视台、潘家园、三里屯、团结湖、日坛使馆区、儿研所、大郊亭都很近。房子闹中取静,地理位置优越,交通方便,紧邻呼家楼地铁站和东大桥地铁站;去机场可乘坐东直门机场快轨,非常方便。购物中心有双井购物中心、国贸购物中心和侨福芳草地购物中心、三里屯购物中心等,远道而来的朋友可尽览都市璀璨!', '0', '1号院1号楼', null, null, null, null, '16'), ('24', '我和我女盆友当房东已经一年了,也是超赞房东,希望能为大家提供舒适的住所~ 房间的大门和房门都是密码门,小区有保安24小时值班,非常安全方便。 通常入住时间是下午三点,提前来的同学可以先寄存行李和洗澡哦~\n\n', '房間非常漂亮,空間很大,鵝黃色的牆壁看起來非常舒服', '位置距離地鐵站不遠', '距故宫、天安门、王府井、三里屯、簋街、南锣鼓巷等景点均可地铁半小时内到达,交通便利~', '0', '1号院2号楼', '1', '13号线', '16', '东直门', '17'), ('25', '这个经纪人很懒,没写核心卖点', '此房是一居室的格局,上下两层,面宽,房间亮堂,进门右手厨房,正前方是25平米的客厅,楼上是卧室,带洗手间! 喧闹和安静隔开,适合居住', '小区距离地铁13号线北苑站500米的距离,交通出行便利....', '小区楼下就是华贸天地娱乐街,保利电影院,眉州东坡,中信银行,麦当劳等娱乐休闲设施齐全', '0', '1号院3号楼', '1', '13号线', '11', '北苑', '18'), ('26', '这个经纪人很懒,没写核心卖点', '此房为望春园小区板楼南北通透户型,主卧客厅朝南,次卧朝北,两个客厅双卫,居住很舒适。', '距离地铁5号线立水桥南站630米,有464,465,966,081,621等多条公交线路,交通出行四通八达。', '小区旁有大型购物商场易事达,物美超市,丰宁蔬菜基地,航空总医院、安贞医院北苑分院,中国银行、中国农业银行、中国工商银行、中国交通银行、中国建设银行、招商银行分布。小区旁有天奥健身房,还有立水桥公园..', '0', '6号院1号楼', '1', '13号线', '10', '立水桥', '19'), ('27', '高大上的整租两居室 业主诚意出租\n1、客厅挑高、宽敞舒适、阳光充足 2、卧室搭配的很新颖,使用之高 3、厨房带阳台,让您和家人有足够的空间展现私家厨艺', '客厅挑高、宽敞舒适、阳光充足 2、卧室搭配的很新颖,使用之高 3、厨房带阳台,让您和家人有足够的空间展现私家厨艺', '近地铁13号线东直门站', '社区环境好,环境优美,适宜居住,人文素质高,物业管理完善; 2、属于低密度社区 ,适宜居住 3、小区的林密树多,让您感受花园一样的家', '0', '1号院5号楼', '1', '13号线', '16', '东直门', '20'), ('28', '房子是正规三室一厅一厨一卫,装修保持的不错,家电家具都齐全。\n', '房子客厅朝北面积比较大,主卧西南朝向,次卧朝北,另一个次卧朝西,两个次卧面积差不多大。', '小区出南门到8号线育新地铁站614米,交通便利,小区500米范围内有物美,三旗百汇,龙旗广场等几个比较大的商场,生活购物便利,出小区北门朝东952米是地铁霍营站,是8号线和 13号线的换乘站,同时还有个S2线,通往怀来。(数据来源百度地图)', '小区西边300米就是物美超市和三旗百汇市场(日常百货、粮油米面、瓜果蔬菜、生鲜海货等等,日常生活很便利,消费成本低),北边200米是龙旗购物广场和永辉超市(保利影院,KFC,麦当劳等,轻松满足娱乐消费)。小区里还有商店,饭店,家政等。', '0', '2号院1号楼', '1', '13号线', '9', '霍营', '21'), ('31', '懒死了 不谢', '户型介绍', '交通出行', '周边配套', '0', '3号院1号楼', '1', '13号线', '12', '望京西', '24'), ('32', '房屋描述-编辑', '户型介绍', '交通出行', '周边配套-编辑', '0', '3号院2单元1003', '1', '13号线', '8', '回龙观', '25');
-- house tag data
INSERT INTO `house_tag` VALUES ('15', '18', '独立阳台'), ('15', '17', '空调'), ('16', '16', '光照充足'), ('17', '15', '随时看房'), ('17', '14', '集体供暖'), ('18', '13', '精装修'), ('19', '12', '独立卫生间'), ('19', '11', '独立阳台'), ('21', '19', '光照充足'), ('21', '20', '独立卫生间'), ('24', '10', '光照充足'), ('24', '3', '精装修'), ('24', '8', '集体供暖'), ('25', '21', '独立阳台');
4、前端集成
1、集成 Thymeleaf 及基本用法
2、集成Bootstrap
3、集成jQuery
首先Thymeleaf相关的jar包,已经在pom.xml文件中配置好了,可以向上查看相关配置。新建一个类WebMvcConfig,配置视图解析器、静态资源加载、模板资源解析器、Thymeleaf标准方言解释器。具体代码如下:
package com.houseSearch.config;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
/**
* Created by 小劭.
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
@Value("${spring.thymeleaf.cache}")
private boolean thymeleafCacheEnable = true;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 静态资源加载配置
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
/**
* 模板资源解析器
* @return
*/
@Bean
@ConfigurationProperties(prefix = "spring.thymeleaf")
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(thymeleafCacheEnable);
return templateResolver;
}
/**
* Thymeleaf标准方言解释器
*/
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
// 支持Spring EL表达式
templateEngine.setEnableSpringELCompiler(true);
// 支持SpringSecurity方言
SpringSecurityDialect securityDialect = new SpringSecurityDialect();
templateEngine.addDialect(securityDialect);
return templateEngine;
}
/**
* 视图解析器
*/
@Bean
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
/**
* Bean Util
* @return
*/
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}
spring.thymeleaf.mode=HTML spring.thymeleaf.suffix=.html spring.thymeleaf.prefix=classpath:/templates/
,表示使用HTML模版以及默认展示的路径;修改application-dev.properties文件,添加spring.thymeleaf.cache=false,表示禁用缓存,修改前端页面实时生效。
在正常的开发流程中,JavaWeb项目会先编译,再执行。我修改代码后台代码后,会再编译,再执行。那么这个过程可能是要花很多时间,所以这里推荐springboot自带的热加载工具spring-boot-devtools,在pom.xml文件中添加如下配置。
<!-- SpringBoot自带热加载开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
然后在idea中需要如下修改,才能使 SpringBoot自带热加载开发工具生效。步骤:IntelliJ IDEA ——》Preferences——》Build,Execution,Deployment——》compiler——》勾选上Build project automatically。如下图。
新建controller文件夹和 HomeController类,在resouces——》templates——新建index.html,截图如下。
最后启动项目,打开浏览器输入http://localhost:8080/index,项目成功启动。