一.项目构建介绍
项目使用语言>Java
项目代码的组织模式>Maven
项目框架>SpringBoot
项目开发工具>IDEA
二.生成项目
由于使用Spring的项目配置复杂,有专门的网站为我们生成壳项目.
https://start.spring.io/

配置项目时注意dependencies要加入'REST API'选项.然后点击下载项目
三.say Hello World
注意是import项目,不是open项目(写给我这样的Java小白)import流程
-
1.建类AnyController
-
2.加入以下代码
@RestController
@RequestMapping("/sayHelloWorld")
public class AnyController {
@GetMapping
public Map<String,Object> sayHelloWorld(){
System.out.println("hello world!");
Map<String,Object> result = new HashMap<>();
result.put("pg_key","pg_value");
return result;
}
}
- 3.命令行跑起项目
命令>mvn spring-boot:run
- 4.本地访问

四.增加自己要的配置项
新建application.yml文件,这个文件在后面的配置会用到.(用application.properties文件其实也是可以的,只是application.properties的书写会麻烦)
当然配置工作只要就是在application.yml和pom.xml加东西.
- 0.时间戳返回
代码:
Map<String,Object> result = new HashMap<>();
result.put("pg_key1111","pg_value1111");
Calendar calendar = Calendar.getInstance();
calendar.set(2016,Calendar.OCTOBER,2,0,0);
result.put("pg_key2",calendar.getTime());
加入配置前
{"pg_key":"pg_value","pg_key2":"2016-10-01T16:00:57.555+0000"}
在application.yml内加入配置
spring:
jackson:
date-format: yyyy-MM-dd
time-zone: GMT+8
serialization:
write-dates-as-timestamps: true #使用数值timestamp表示日期,true时会忽略date-format
加入配置后
{"pg_key":"pg_value","pg_key2":1475337606386}
- 1.热部署
A.pom.xml加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
B.打开自动build选项

报错>Error:Maven Resources Compiler: Maven project configuration required for module 'PogongChat' isn't available. Compilation of Maven projects is supported only if external build is started from an IDE.
遇到以上问题 要 Build>Rebuild Project.
然后改动项目里面的代码,就会立刻触发热部署.
- 2.日志
A.application.yml内添加配置
logging:
file: target/app.log
level:
ROOT: WARN
com.pogong: TRACE
B.代码内添加使用
public class AnyController {
private static final Log log = LogFactory.getLog(AnyController.class);
@GetMapping
public Map<String,Object> sayHelloWorld(){
if (log.isTraceEnabled()){
log.trace("sayHelloWorld 被调用了");
}
}
}
- 3.连接数据库
A.pom.xml添加
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
B.application.yml添加
spring:
datasource:
url: jdbc:mysql://localhost:3306/jdbc_db?rewriteBatchedStatements=true&characterEncoding=utf8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
C.代码添加(class AnyController内)
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping("/connectDB")
public int connectDB(){
String sql = "select * from tv_series";
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
for (Map<String, Object> map : list) {
System.out.println("pg see begin");
System.out.println(map.getClass());
System.out.println(map);
System.out.println("pg see end");
Set<Map.Entry<String, Object>> entries = map.entrySet( );
if(entries != null) {
Iterator<Map.Entry<String, Object>> iterator = entries.iterator( );
while(iterator.hasNext( )) {
Map.Entry<String, Object> entry =(Map.Entry<String, Object>) iterator.next( );
Object key = entry.getKey( );
Object value = entry.getValue();
System.out.println("pg see>"+key+":"+value);
}
}
}
return 1;
}
连接数据库可以用的工具库有很多,这里用的是JdbcTemplate
.
- 4.应用Mybatis创建数据映射关系
第一,因为要加入Mybatis
,建立数据映射关系.所以代码得向分层正规化靠拢一步.
我用的是:
Controller>Service>Dao>Pojo
的层级关系.
为什么是这样的层级关系,我现在还说不清楚.只能说一个大概:
Controller>Service 是 方法调用传递;
Dao 是 接口,不直接实现方法.Dao的接口会对应配置Dao的xml.
Dao的xml内包含sql语句以及数据库键名与数据模型类属性的关系;
Pojo 是 数据模型类;
第二,由于Mybatis
的接入方式多种多样,有高深(装逼)也有浅薄(朴实).这里为了更好的了解原理,会先浅薄的接入后高深的接入.
- 4.1 Mybatis浅薄接入
浅薄接入只用到Controller>Dao>Pojo,这三层.
A.pom.xml添加
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
B.加入mybatis的其他配置
mybaits-config.xml
jdbc.properties
mappers/AnyDao.xml
以上三项主要是mybaits-config.xml
,其他两项是附属于mybaits-config.xml
的.
mybaits-config.xml内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties" />
<!--配置加载的环境,可以配置多套环境,设置id名称,默认加载development环境-->
<environments default="development">
<environment id="development">
<!--事务管理器-->
<transactionManager type="JDBC"/>
<!--数据源 连接池配置-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!--配置SQL映射文件-->
<mappers>
<mapper resource="mappers/AnyDao.xml"/>
</mappers>
</configuration>
mybaits-config.xml
的内容其实很简单,就是将数据库的连接信息(即:jdbc.properties
)包含了,再加上与Dao接口
对应的Dao的xml
的文件路径.
数据库的连接信息:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jdbc_db?rewriteBatchedStatements=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
Dao的xml
如上所述:Dao的xml内包含sql语句以及数据库键名与数据模型类属性的关系;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pogong.PogongChat.Dao.AnyDao">
<resultMap id="TvSeriesResultMap" type="com.pogong.PogongChat.Pojo.AnyObj">
<result column="season_count" property="seasonCount" />
<result column="origin_release" property="originRelease" />
</resultMap>
<select id="getAll" resultMap="TvSeriesResultMap">
select * from tv_series
</select>
</mapper>
C.用起来
在Controller内加入代码
@GetMapping("/test_mybaits")
public int test_mybaits() {
// 1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2.加载SqlMapConfig.xml配置文件
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybaits-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
// 3.创建SqlSessionFactory对象
sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
AnyDao anyDao = sqlSession.getMapper(AnyDao.class);
List<AnyObj> list = anyDao.getAll();
for (AnyObj obj : list) {
System.out.println("pg see");
System.out.println(obj);
}
return 1;
}
代码也比较简单:
1.创建SqlSessionFactoryBuilder对象;
2.加载SqlMapConfig.xml配置文件;
3.由SqlSessionFactoryBuilder创建SqlSessionFactory对象;
4.SqlSessionFactory对象获取SqlSession对象;
5.SqlSession对象加载Dao接口实现类,调用对应方法;
打完收工
- 4.2 Mybatis高深的接入
之所以说4.1内Mybatis的接入比较浅薄是因为加载Dao的实现类每次都得明码进行.那么高深的方式是怎么做的呢?
A.pom.xml添加
<!--<dependency>-->
<!--<groupId>org.mybatis</groupId>-->
<!--<artifactId>mybatis</artifactId>-->
<!--<version>3.4.6</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
删除原有org.mybatis
的引用,加入org.mybatis.spring.boot
的引用.
B.更改其他配置
mybaits-config.xml如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 设置包扫描(别名) -->
<typeAliases>
<package name="com.pogong.PogongChat.Pojo"/>
</typeAliases>
<!--配置SQL映射文件-->
<mappers>
<mapper resource="mappers/AnyDao.xml"/>
</mappers>
</configuration>
application.yml加入:
jdbc:
url: jdbc:mysql://localhost:3306/jdbc_db?rewriteBatchedStatements=true&characterEncoding=utf8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
删除jdbc.properties
C.构建RootConfig
@Configuration
@MapperScan(basePackageClasses = {AnyDao.class})
@EnableTransactionManagement
public class RootConfig {
//pg point1>数据库连接配置(读取的数据在application.yml内)
@Value(value = "${jdbc.driver-class-name}")
private String driver;
@Value(value = "${jdbc.url}")
private String url;
@Value(value = "${jdbc.username}")
private String userName;
@Value(value = "${jdbc.password}")
private String password;
@Bean
public DataSource getDataSource() {
DataSource dataSource = new DriverManagerDataSource();
((DriverManagerDataSource) dataSource).setDriverClassName(driver);
((DriverManagerDataSource) dataSource).setUrl(url);
((DriverManagerDataSource) dataSource).setUsername(userName);
((DriverManagerDataSource) dataSource).setPassword(password);
return dataSource;
}
//pg point2>Dao映射配置(读取的数据在有mybatis-config.xml内)
@Value(value = "classpath:mybaits-config.xml")
private Resource configLocation;
@Bean(name="sqlSessionFactory")
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setConfigLocation(configLocation);
ssfb.setDataSource(getDataSource());
return ssfb;
}
//pg point3>[getDataSource方法]和[sqlSessionFactory方法]启动时会被调用一回,后面就不再会被调用
}
RootConfig
的作用也很明显就是:
构建数据库连接;
并为加载mybaits-config.xml
的内容(mappers和typeAliases);mappers内是Dao接口
对应的Dao的xml
的文件路径;typeAliases内是数据模型类
的路径;
RootConfig内的两个方法都只在启动时会被调用一回.具体用到什么高深的东西现在笔者还不得而知.
D.构建层级化调用
Mybatis浅薄接入:AnyController的代码内一步到位的完成数据库的读取与数据的返回;
而在本节的接入中是按照:AnyController>AnyService>AnyDao层级化调用的;
- 5.校验前端传入的数据
对于前端的态度:
不要相信前端传过来的数据;
一定不要相信前端传过来的数据;
绝对不要相信前端传过来的数据;
在判断传入数据时,我们不可能重复的写一些冗余的判断代码,而是用校验库内写好的注解(校验库SpringBooty已经自带,可以直接使用).
A.数据模型类加注解
public class AnyObj {
@Null private Integer id;
@NotNull private String name;
@Min(1) private int seasonCount;
private Date originRelease;
......
}
代码如上:
@Null>这项前端一定不能传入
@NotNull>这项前端一定要传入
@Min(1)>这项前端传入一定要大于等于1
B.接受数据方法加注解
@PostMapping("/add_obj")
public int add_obj(@Valid @RequestBody AnyObj anyObj) {
System.out.println("pg see add_obj");
System.out.println(anyObj);
return 1;
}
在接受前端数据方法的参数前加入@Valid
才会对接受数据做数据模型类内部写好的校验.
注意:不写
@Valid
,数据模型类内部写好的校验注解是不起作用的.(@Valid
>级联验证)
C.Postman测试

以上仅用id前端不能传
来举例,其他校验也是一样的,就不一一举例了.
D.校验分组
有的时候一个数据模型类内的多个字段会在不同的时机有不同的
校验规则(如:Person包含姓名,性别,手机号.注册用户时,用户可能是第一步先填入姓名+性别,第二步在填入手机号).
那么不同的时机就要应用不同的校验规则.校验注解为此提供了分组的功能.
public interface Groups {
interface addStep1{}
interface addStep2{}
}
------------------------------------------------------------------------------------
@Null(groups = {Groups.addStep1.class}) private Integer id;
@NotNull(groups = {Groups.addStep2.class}) private String name;
@Min(value = 1,groups = {Groups.addStep1.class,Groups.addStep2.class}) private int seasonCount;
------------------------------------------------------------------------------------
@PostMapping("/add_obj1")
public int add_obj1(@Validated({Groups.addStep1.class}) @RequestBody AnyObj anyObj) {
System.out.println("pg see add_obj1");
System.out.println(anyObj);
return 1;
}
@PostMapping("/add_obj2")
public int add_obj2(@Validated({Groups.addStep2.class}) @RequestBody AnyObj anyObj) {
System.out.println("pg see add_obj2");
System.out.println(anyObj);
return 1;
}
代码如上,
方法add_obj1
就应用了校验分组1
;
方法add_obj2
就应用了校验分组2
;
-
6.缓存
-
6.1 缓存注解
使用缓存,必须在启动类前加'@EnableCaching'
@EnableCaching
@SpringBootApplication
@MapperScan("com.pogong.PogongChat.Dao")
public class PogongChatApplication {
public static void main(String[] args) {
SpringApplication.run(PogongChatApplication.class, args);
}
}
缓存的实践标注写在Service内.
@Service
public class AnyService {
@Autowired
private AnyDao anyDao;
//加缓存
@Cacheable(cacheNames="AnyObj",key="#id")
public AnyObj getOneById(int id){
System.out.println("pg see Service getOneById");
return anyDao.getOneById(id);
}
//清除缓存
@CacheEvict(cacheNames="AnyObj",key="#id")
public void logicDelete(int id,String reason){
System.out.println("pg see Service logicDelete");
anyDao.logicDelete(id,reason);
}
}
以上存删缓存的键为字符串"AnyObj::{id}".
- 6.2 缓存工具>redis
以上用到了缓存,但存储是用的系统内存.这里介绍成型的缓存服务器redis
.
A.本地装redis
brew install redis
B.项目加redis配置
pom.xml加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.yml加
spring:
cache:
redis:
time-to-live: 300s
redis:
host: 127.0.0.1
port: 6379
jedis:
pool:
max-active: 8
max-wait: 10000
max-idle: 10
C.加redis功能代码
首先明确我们是要将一个对象
存进redis,而不是普通数据类型.所以要对redis进行配置,保证能存也能取对象
.
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(redisConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
以下是加+取+删
缓存的操作.
@Autowired RedisTemplate<?, ?> redisTemplate;
public AnyObj getOneById(int id){
String key = "AnyObj_"+id;
@SuppressWarnings("unchecked")
RedisTemplate<String, AnyObj> rt = (RedisTemplate<String, AnyObj>)redisTemplate;
AnyObj anyObj = rt.opsForValue().get(key);//<获取缓存数据
if(anyObj == null) {
anyObj = anyDao.getOneById(id);
rt.opsForValue().set(key,anyObj);//<设置缓存数据
Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, 5);
rt.expireAt(key, c.getTime());
System.out.println("set data to cache");
}else {
System.out.println("data form cache");
}
return anyObj;
}
public void logicDelete(int id,String reason){
System.out.println("pg see Service logicDelete");
RedisTemplate<String, AnyObj> rt = (RedisTemplate<String, AnyObj>)redisTemplate;
String key = "AnyObj_"+id;
rt.delete(key);//<删除缓存
anyDao.logicDelete(id,reason);
}
D.注意
1.测试时,先要把redis打开,命令>redis-server;
2.redis在application.yml内已经设置了全局的缓存超时时间,如果想更加精确的控制缓存时间可以像上文一样用Calendar来控制;
网友评论