springboot常用的技巧
启动springboot方法
1:直接run main方法
public static void main(String[] args) {
SpringApplication.run(GirlApplication.class, args);
}
2:进入到工作目录
执行:mvn spring-boot :run
3:进入工作目录
执行:mvn install
进入target目录:cd target
执行 :java -jar demo-0.0.1-SNAPSHOT.jar
Controller里的注解
@Controller
: 只负责跳转页面
@ResponseBody
: 跳转页面后返回值
@RestController
:跳转页面后返回JSON类型的值
@component
: 把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>
@ConfigurationProperties
:(prefix = “Girl”)配置文件的信息,读取并自动封装成实体类
@Value
:注解来获取配置文件的值
perperties文件如下
@Component
@ConfigurationProperties(prefix = "Girl")
public class GirlProperties {
private String cupSize;
private Integer age;
//省略setter getter
@Value("${Age}")
private Integer age;
.yml文件:需要严格的格式,配置多个yml文件方便维护
application.yml
spring:
profiles:
##通过active配置,指定对应的配置文件
active: dev
##数据库连接配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/dbgirl
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
application-dev.yml
##指定一个端口
server:
port: 8080
girl:
age: 18
cup-size: F
##content: "cupSize: ${cupSize}, age: ${Age}"
application-prod.yml
##指定另外的端口
server:
port: 8081
girl:
age: 18
cup-size: D
##content: "cupSize: ${cupSize}, age: ${Age}"
@Autowire
:注解配合setter getter方法获取值
@RequestMapping(value = "/say/{id}"
@PathVariable("id")
//配合获取id的值
@RequestMapping(value = "/say")
@PathParam("id")//获取id值
RESTClient 火狐插件POST方法传递参数
1.设置Headers,增加一个
Name:Content-type
Value:application/x-www-form-urlencoded;charset=UTF-8
2.在body中传参数
变量名1=x&变量名2=y
3.对应测试
@GetMapping @PostMapping
数据的校验@Valid
通过保存的方法来演示
实体类
@Min(value = 18,message = "未成年人")
private Integer age;
方法:使用BindingResult 对象的方法返回错误信息
@PostMapping(value = "/girls")
public Girl girlAdd(@Valid Girl girl, BindingResult bindingResult){
if(bindingResult.hasErrors()){
//使用BindingResult返回错误信息
System.out.println(bindingResult.getFieldError()
.getDefaultMessage());
return null;
}
girl.setCupSize(girl.getCupSize());
girl.setAge(girl.getAge());
return girlResponsitory.save(girl);
改进一:上述方法返回的数据格式不一致,定义一个Result对象封装返回的信息,统一格式
定义Result对象
public class Result<T> {
/** 错误码 */
private Integer code;
//提示信息
private String msg;
//具体内容
private T data;
//省略setter getter 方法
}
改进方法
@PostMapping(value = "/girls")
public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult){
if(bindingResult.hasErrors()){
Result result = new Result();
result.setCode(1);
result.setMsg(bindingResult.getFieldError().getDefaultMessage());
result.setData(null);
return result;
}
girl.setCupSize(girl.getCupSize());
girl.setAge(girl.getAge());
Result result = new Result();
result.setCode(0);
result.setMsg("成功");
result.setData(girl);
return result;
}
改进二:上述的方法重复代码太多了,写个工具类ResultUtills
public class ResultUtills {
public static Result success(Object object){
Result result = new Result();
result.setCode(0);
result.setMsg("成功");
result.setData(object);
return result;
}
public static Result success(){
return success(null);
}
public static Result error(Integer code, String msg){
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
return result;
}
}
改进二的方法
@PostMapping(value = "/girls")
public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult){
if(bindingResult.hasErrors()){
return ResultUtills.error(1,bindingResult.getFieldError().getDefaultMessage());
}
return ResultUtills.success(girlResponsitory.save(girl));
}
AOP切面编程,重点log日志打印的使用
AOP的注解实现
一:@Pointcut定义切入点 拦截包下*方法
二:@Before(“log()”)等方法调用切入点
三:Logger 的使用 slf4j的 Logger
四:logger.info()的格式
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
@Pointcut("execution(public * com.girl.demo.Controller.GirlController.*(..))")
public void log(){
}
@Before("log()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes servletRequestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
//URL
logger.info("URl={}",request.getRequestURL());
//method
logger.info("method={}",request.getMethod());
//ip
logger.info("ip={}",request.getRemoteAddr());
//类方法
logger.info("ClassMethod={}",joinPoint.getSignature().getDeclaringTypeName());
//参数
logger.info("param={}",joinPoint.getArgs());
}
@After("log()")
public void doAfter(){
logger.info("iiiiiiiiii");
}
@AfterReturning(returning ="obj",pointcut = "log()")
public void doAfterReturn(Object obj){
//方法执行之后 返回结果
logger.info("response={}",obj.toString());
}
统一异常处理:返回的不是一种类型,不能单纯返回值类型是String
1 首先采用Result对象,固定三个字段
2 为了解决逻辑在一个地方处理,另外的地方不用再接收它返回的信息,引入异常
3 默认的Exception 只接受msg字段,但是还有code,因此定义自己的异常类GirlException
4 有了异常,需要捕获,写了捕获异常类:ExceptionHandlers
5 最后将 code msg 字段定义成枚举统一管理
6 在Service中处理逻辑,若验证不通过的话,直接抛出异常
Controller中直接调用Service中的方法,也抛出异常
类ExceptionHandlers 接收异常并且处理异常
以查询 方法为例子
public void getAge(Integer id) throws Exception{
Girl girl = girlResponsitory.findOne(id);
if(girl.getAge() < 10){
//返回小学生,code=100
throw new GirlException(100,"小学生");
}
改进方法:
异常处理类
@ControllerAdvice
public class ExceptionHandlers {
//记录下异常
private final static Logger logger = LoggerFactory.getLogger(ExceptionHandlers.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handl(Exception e){
/**
* 捕获异常,判断code是100还是101
*/
if (e instanceof GirlException) {
GirlException girlException = (GirlException)e;
return ResultUtills.error(girlException.getCode(),girlException.getMessage());
}else{
//logger的使用 格式("【系统异常】{}",e),内容会出现在{}里面
logger.info("【系统异常】{}",e);
return ResultUtills.error(-1,"未知错误");
}
}
}
查询方法
public void getAge(Integer id) throws Exception{
Girl girl = girlResponsitory.findOne(id);
if(girl.getAge() < 10){
//构造Exception方法,传入message
//改进 使用枚举类型便于维护
throw new GirlException(ResultEnums.PRIMARY_SCHOOL);
else if(girl.getAge() >10 && girl.getAge() <16){
//返回初中生,code=101
throw new GirlException(ResultEnums.MIDDLE_SCHOOL);
}
枚举的使用
/**
* 枚举的使用,便于后期的维护
*
*/
public enum ResultEnums {
UNKUNOW_ERROR(-1,"未知错误"),
SUCCESS(0,"成功"),
PRIMARY_SCHOOL(100,"上小学"),
MIDDLE_SCHOOL(101,"上初中")
;
private Integer code;
private String msg;
ResultEnums(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
实现RuntimeException
public class GirlException extends RuntimeException {
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
//构造方法里 传入message
/*public GirlException(Integer code ,String message) {
super(message);
this.code = code;
}*/
//改进 传入枚举类型的 构造方法
public GirlException(ResultEnums resultEnums) {
super(resultEnums.getMsg());
this.code = resultEnums.getCode();
}
}
单元测试
1测试Service
2测试带有URL的测试
3在powershell中进入工作目录 mvn clean package 直接测试所有的TEST
跳过错误的测试 mvn clean package -Dmaven .test.skip=true