参考源码地址 https://github.com/leechenxiang/imooc-springboot-starter
可选IDE STS Spring Tool Suit
快速开始:https://spring.io/quickstart
配置文件 application.properties
############################################################
#
# 开发模式设置
#
############################################################
# 热部署生效
spring.devtools.restart.enabled=true
# 监听目录
spring.devtools.restart.additional-paths=src/main/java
#spring.devtools.restart.exclude=static/**,public/**
#spring.devtools.restart.exclude=WEB-INF/**
############################################################
#
# server 服务端配置
#
############################################################
server.port=8080
#server.servlet.context-path=/demo
#server.error.path=/error
#server.address=192.168.1.2
#server.session-timeout=60
############################################################
#
# server.tomcat 服务端配置
#
############################################################
#server.tomcat.max-threads=250
server.tomcat.uri-encoding=UTF-8
#server.tomcat.basedir=H:/springboot-tomcat-tmp
#server.tomcat.access-log-enabled=true
#server.tomcat.access-log-pattern=
#server.tomcat.accesslog.directory=
#logging.path=H:/springboot-tomcat-tmp
#logging.file=myapp.log
二、接口返回json
# 时间格式化
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.jackson.serialization.write-dates-as-timestamps=false
package com.example.demo.pojo;
/**
* 统一的返回封装
*/
public class JsonResult {
private Integer code;
private String msg;
private Object data;
public JsonResult(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static JsonResult success(Object data){
return new JsonResult(0, "success", data);
}
public static JsonResult error(String errorMessage) {
return new JsonResult(-1, errorMessage, null);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
package com.example.demo.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.Date;
/**
* jackson注解使用示例
*/
@Data
public class User {
private String name;
private Integer age;
// 忽略显示
@JsonIgnore
private String password;
// 格式化
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", locale="zh", timezone="GMT+8")
private Date birthday;
// 为空不显示
@JsonInclude(JsonInclude.Include.NON_NULL)
private String desc;
}
三、热部署
org.springframework.boot
spring-boot-devtools
true
IDEA需要做额外的配置
四、资源属性配置resource.properties
# 配置文件
com.demo.name=MyBlog
com.demo.language=zh
package com.example.demo.pojo;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* 资源文件中的配置映射到实体类
*/
@Configuration
@ConfigurationProperties(prefix = "com.demo")
@PropertySource(value = "classpath:resource.properties")
public class Resource {
private String name;
private String language;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}
五、模板引擎
org.springframework.boot
spring-boot-starter-freemarker
org.springframework.boot
spring-boot-starter-thymeleaf
############################################################
#
# freemarker
#
############################################################
# 上线改为true
spring.freemarker.cache=false
#spring.freemarker.template-loader-path=classpath:/templates
#spring.freemarker.charset=UTF-8
#spring.freemarker.check-template-location=true
#spring.freemarker.content-type=text/html
#spring.freemarker.expose-request-attributes=true
#spring.freemarker.expose-session-attributes=true
#spring.freemarker.request-context-attribute=request
#spring.freemarker.suffix=.ftl
############################################################
#
# thymeleaf
#
#############################################################
# 上线改为true
spring.thymeleaf.cache=false
#spring.thymeleaf.prefix=classpath:/templates/
#spring.thymeleaf.suffix=.html
#spring.thymeleaf.mode=HTML5
#spring.thymeleaf.encoding=UTF-8
#spring.thymeleaf.servlet.content-type=text/html
# 静态文件
spring.mvc.static-path-pattern=/static/**
freemarker
freemarker
${resource.name}
${resource.language}
thymeleaf
基本使用方式 对象引用方式 时间类型转换 text与utext URL 引入静态资源文件js/css 条件判断th:if与th:unless 循环th:each 分支th:switch与th:case
Title
基本语法
日期格式化
简便写法
text与utext
text:
utext:
网址
www.baidu.com
表单
判断
age == 20
age > 20
age < 20
age >= 20
age
20
18
循环
分支
超级管理员
管理员
普通会员
六、异常处理
通用异常 web和ajax
package com.example.demo.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 处理错误页面
*/
@ControllerAdvice
public class CustomExceptionHandler {
public static final String ERROR_VIEW = "thymeleaf/error";
@ExceptionHandler(value = Exception.class)
public Object errorHandler(HttpServletRequest request,
HttpServletResponse response, Exception e) throws Exception {
if (isAjax(request)) {
ModelAndView model = new ModelAndView(new MappingJackson2JsonView());
model.addObject("data", null);
model.addObject("code", -1);
model.addObject("msg", e.getMessage());
return model;
} else {
ModelAndView model = new ModelAndView();
model.addObject("exception", e);
model.addObject("url", request.getRequestURL());
model.setViewName(ERROR_VIEW);
return model;
}
}
/**
* 判断是否为ajax
*
* @param request
* @return
*/
public boolean isAjax(HttpServletRequest request) {
String ContentType = request.getHeader("Content-Type");
String Accept = request.getHeader("Accept");
if (ContentType != null &&
ContentType.contains("json")) {
return true;
} else if (Accept != null &&
Accept.contains("json")) {
return true;
} else {
return false;
}
}
}
处理ajax错误
package com.example.demo.exception;
import com.example.demo.pojo.JsonResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 处理ajax错误
*/
@RestControllerAdvice
public class AjaxExceptionHandler {
@ExceptionHandler(value = Exception.class)
public JsonResult errorHandler(HttpServletRequest request,
HttpServletResponse response, Exception e) throws Exception {
return JsonResult.error(e.getMessage());
}
}
七、MyBatis
依赖引入pom.xml
mysql
mysql-connector-java
8.0.20
com.alibaba
druid
1.1.0
com.alibaba
druid-spring-boot-starter
1.1.9
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.1
tk.mybatis
mapper-spring-boot-starter
2.0.0
com.github.pagehelper
pagehelper-spring-boot-starter
1.2.3
org.mybatis.generator
mybatis-generator-core
1.3.2
compile
true
参数配置 application.properties
############################################################
#
# druid
#
############################################################
spring.datasource.url=jdbc:mysql://localhost:3306/data
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.initial-size=1
spring.datasource.druid.min-idle=1
spring.datasource.druid.max-active=20
spring.datasource.druid.test-on-borrow=true
#spring.datasource.druid.stat-view-servlet.allow=true
############################################################
#
# mybatis
# https://github.com/abel533/MyBatis-Spring-Boot
############################################################
mybatis.type-aliases-package=com.example.demo.pojo
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 通用mapper
mapper.mappers=com.example.demo.utils.MyMapper
mapper.not-empty=false
mapper.identity=MYSQL
# 分页插件
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
自动代码生成配置 generatorConfig.xml
逆向工程工具
package com.example.demo.utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorDisplay {
public void generator() throws Exception{
List warnings = new ArrayList();
boolean overwrite = true;
// 指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorDisplay generatorSqlmap = new GeneratorDisplay();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
通用Mapper
package com.example.demo.utils;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
/**
* 继承自己的MyMapper
*/
public interface MyMapper extends Mapper, MySqlMapper {
//TODO
//FIXME 特别注意,该接口不能被扫描到,否则会出错
}
package com.example.demo.mapper;
import com.example.demo.pojo.SysUser;
import com.example.demo.utils.MyMapper;
public interface UserMapper extends MyMapper {
}
自定义Mapper
package com.example.demo.mapper;
import com.example.demo.pojo.Person;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 自定义Mapper
public interface PersonMapper {
Person queryUserById(Integer id);
@Transactional(propagation= Propagation.REQUIRED)
void deleteById(Integer id);
@Transactional(propagation= Propagation.REQUIRED)
void updateById(Person person);
}
package com.example.demo.pojo;
import lombok.Data;
@Data
public class Person {
private Integer id;
private String name;
private Integer age;
}
select
id, name, age
from
person
where
id = #{id, jdbcType=INTEGER}
limit 1
update person
set name = #{name}, age = #{age}
where id = #{id}
delete from person
where id = #{id}
mybatis generatorConfig生成mapper和pojo 实现CURD mybatis-pagehelper实现分页 自定义mapper实现 xml形式的sql形式有利于后期调优 使用包含pagehelper分页的MyBatis的开源框架: https://github.com/abel533/MyBatis-Spring-Boot
事务: 事务隔离级别 default read_uncommitted read_committed repeatable_read serializable
事务传播行为 required 有事务直接用,没有新建事务 supports 有事务直接用,没有也可以 mandatory requires_new not_supported never nested
使用场景
@Transactional(propagation=Propagation.SUPPORTS)查询
@Transactional(propagation=Propagation.REQUIRED)增加,删除,修改
解决devtools与Mapper冲突
添加配置文件 META-INF/spring-devtools.properties
restart.include.hifi=/hifi-[\\w-\\.\\d]+.jar
restart.include.mybatis=/mybatis-[\\w-\\.\\d]+.jar
restart.include.mapper=/mapper-[\\w-\\.\\d]+jar
restart.include.pagehelper=/pagehelper-[\\w-\\.\\d]+jar
八、redis
引入依赖
org.springframework.boot
spring-boot-starter-data-redis
配置
############################################################
#
# REDIS
#
############################################################
spring.redis.database=1
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=1000
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=2
spring.redis.timeout=0
使用
package com.example.demo.controller;
import com.example.demo.pojo.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RedisController {
@Autowired
private StringRedisTemplate redisTemplate;
@GetMapping("/redis")
public JsonResult error() {
redisTemplate.opsForValue().set("name", "Tom");
return JsonResult.success(redisTemplate.opsForValue().get("name"));
}
}
九、定时任务
@EnableScheduling // 开启定时任务
package com.example.demo.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class HelloTask {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
// 每3秒执行一次
@Scheduled(fixedRate = 3000)
public void echo(){
System.out.println("echo: " + dateFormat.format(new Date()));
}
}
十、异步任务
@EnableAsync // 开启异步任务
package com.example.demo.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class HelloTask {
@Async
public void sayHello() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
十一、拦截器
定义拦截器
package com.example.demo.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloInterceptor implements HandlerInterceptor {
// 请求处理之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
if("Tom".equals(request.getParameter("key"))){
System.out.println("被拦截");
return false;
} else{
System.out.println("放行");
return true;
}
}
// 请求处理之后
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
注册拦截器
package com.example.demo.config;
import com.example.demo.interceptor.HelloInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//WebMvcConfigurerAdapter已经被废弃了
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
// 拦截器按照顺序执行
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HelloInterceptor()).addPathPatterns("/**");
}
}