可以加到类上,起到一个前缀的作用。注意不要用错成@RestController(”/user")
用在接收参数为Json格式时,让spring将其转化为对象。
实体类中必须要有无参构造器
使用spring-data-jpa的表单验证需要先导入如下依赖
org.springframework.boot spring-boot-starter-data-jpa
一种比较简单优雅的方法是在注解@RequestMapping中添加produces参数即可
@RestController
@RequestMapping("/api")
public class ApiController {
@RequestMapping(value = "/collection", produces="application/json;charset=UTF-8")
public String home(String op) {
}
spring只会对RuntimeException进行异常回滚所以编写自定义异常时都应该让其继承自Runtime Exception
为了统一格式,一般会对请求结果进行一次封装
package com.example.springbootstudynote.enums;
/**
* @Description: 请求结果枚举,方便对请求结果的统一维护
* @Auther: Administrator
* @date: 2018/7/24:21:47
*/
public enum ResultEnum {
SUCCESS(0, "成功"),
UNKONW_ERROR(-1, "未知错误");
private Integer code;
private String msg;
ResultEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
package com.example.springbootstudynote.dto;
import com.example.springbootstudynote.enums.ResultEnum;
/**
* @Description: 请求结果封装类
* @Auther: Administrator
* @date: 2018/7/24:21:34
*/
public class Result<T> {
/**
* 错误码
*/
private Integer code;
/**
* 提示信息
*/
private String msg;
/**
* 请求结果数据
*/
private T data;
public Result() {
}
public Result(ResultEnum resultEnum) {
this.code = resultEnum.getCode();
this.msg = resultEnum.getMsg();
}
public Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
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 T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
package com.example.springbootstudynote.utils;
import com.example.springbootstudynote.dto.Result;
import com.example.springbootstudynote.enums.ResultEnum;
/**
* @Description: 请求结果工具类,方便代码复用
* @Auther: Administrator
* @date: 2018/7/24:21:39
*/
public class ResultUtil {
public static Result success(Object object) {
Result result = new Result<>(ResultEnum.SUCCESS);
result.setData(object);
return result;
}
public static Result success(){
return success(null);
}
public static Result error(Integer code, String message) {
return new Result(code, message);
}
public static Result error(ResultEnum resultEnum) {
return new Result<>(resultEnum);
}
}
package com.example.springbootstudynote.exception;
import com.example.springbootstudynote.enums.ResultEnum;
/**
* @Description: 自定义异常
* @Auther: Administrator
* @date: 2018/7/24:21:33
*/
public class StudyNoteException extends RuntimeException{
/**
* 错误码
*/
private Integer code;
public StudyNoteException() {
}
public StudyNoteException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
}
public StudyNoteException(String message, Integer code) {
super(message);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
package com.example.springbootstudynote.exception.handle;
import com.example.springbootstudynote.dto.Result;
import com.example.springbootstudynote.enums.ResultEnum;
import com.example.springbootstudynote.exception.StudyNoteException;
import com.example.springbootstudynote.utils.ResultUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description: 统一异常处理类
* @Auther: Administrator
* @date: 2018/7/24:21:31
*/
@ControllerAdvice
public class ExceptionHandle {
private final Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result<String> handle(Exception e) {
if (e instanceof StudyNoteException){
StudyNoteException studyNoteException = (StudyNoteException) e;
return ResultUtil.error(studyNoteException.getCode(), studyNoteException.getMessage());
}else{
logger.error("【系统异常】{}", e); // 记录异常
return ResultUtil.error(ResultEnum.UNKONW_ERROR);
}
}
}
详解Gson使用
/**
* JSON转Map
*
* @param jsonString
* @return
*/
public static Map<String, String> toMap(String jsonString) {
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
Type type = new TypeToken<Map<String, String>>() {
}.getType();
return gson.fromJson(jsonString, type);
}
/**
* 更好的打印JSON字符串,增强日志的可读性
*
* @param object
* @return
*/
public static String prettyPrinting(Object object) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setPrettyPrinting();
Gson gson = gsonBuilder.create();
return gson.toJson(object);
}
Gson中的JsonObject与json-lib中的JSONObject不是同一个类
JsonObject的get方法获得的是一个JsonElement
而JsonElement的toString和getAsString方法需要注意区分,toString方法得到的字符串带有引号,getAsString方法得到的是字符串内的值。
public void toJsonObject(){
String jsonString = "{\"openId\":\"oGZUI0egBJY1zhBYw2KhdUfwVJJE\",\"nickName\":\"Band\",\"gender\":1,\"language\":\"zh_CN\",\"city\":\"Guangzhou\",\"province\":\"Guangdong\",\"country\":\"CN\",\"avatarUrl\":\"http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0\",\"unionId\":\"ocMvos6NjeKLIBqg5Mr9QjxrP1FA\",\"watermark\":{\"timestamp\":1477314187,\"appid\":\"wx4f4bc4dec97d474b\"}}";
JsonObject jsonObject = JsonUtil.toJsonObject(jsonString);
log.info(jsonObject.get("openId").toString());
// "oGZUI0egBJY1zhBYw2KhdUfwVJJE"
log.info(jsonObject.get("openId").getAsString());
// oGZUI0egBJY1zhBYw2KhdUfwVJJE
}
RestTemplate 官方 API
详解 RestTemplate 操作
RestTemplate restTemplate = new RestTemplate();
// 发起请求
String response = restTemplate.getForObject(url, String.class);
log.info("response={}", response);
SpringBoot(六):SpringBoot整合Redis
SpringBoot整合Redis
springboot 2.0 使用Hikari连接池(号称java平台最快的,替换druid)
Springboot 2.0选择HikariCP作为默认数据库连接池的五大理由
Spring Boot—(4)SpringBoot异步处理任务
Spring Boot 异步执行方法- 掘金
How To Do @Async in Spring | Baeldung
异步任务spring @Async注解源码解析- 只会一点java - 博客园
@EnableAsync
@Async
spring在未指定线程池的情况下使用的是默认的线程池SimpleAsyncTaskExecutor
来处理异步任务。如果要设置线程池的具体属性(如最大线程数、线程空闲时间等),就需要通过自定义线程池来实现。
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {
private static final int corePoolSize = 10; // 核心线程数(默认线程数)
private static final int maxPoolSize = 300; // 最大线程数
private static final int keepAliveTime = 10; // 允许线程空闲时间(单位:默认为秒)
private static final int queueCapacity = 200; // 缓冲队列数
private static final String threadNamePrefix = "Async-Service-"; // 线程池名前缀
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveTime);
executor.setThreadNamePrefix(threadNamePrefix);
// 线程池对拒绝任务的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
executor.initialize();
return executor;
}
}
使用时在注解中指定线程池的名字,如:@Async("taskExecutor")
通过实现接口AsyncConfigurer
来替换默认的线程池
@Configuration
@EnableAsync
public class SpringAsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolTaskExecutor();
}
}
SpringBoot启动结构图| ProcessOn免费在线作图,在线流程图,在线思维 …
SpringBoot源码分析之SpringBoot的启动过程
SpringBoot启动流程简析(一)
构造SpringApplication的时候会进行初始化的工作:
SpringApplication
属性中启动SpringApplication.run
方法执行的时候会做以下几件事: