Spring Boot进阶之Web进阶
1. 表单验证
- 将单个的属性变成对象
这样就可以属性越来越多的时候,直接在对象的类中添加即可,接口参所不需要动
- 对参数进行限制
- 测试
2. 使用AOP处理请求
通过AOP来统一处理请求日志
- AOP:将通用逻辑从业务逻辑中分离出来
更简洁的一种写法
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
//使用@Component把HttpAspect类引入到spring容器中
@Component
public class HttpAspect {
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
@Pointcut("execution(public * com.imooc.controller.GirlController.*(..))")
public void log() {
}
@Before("log()")
public void doBefore(JoinPoint joinPoint) { logger.info("1111111111111111");
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//记录http请求的信息
//url
logger.info("url={}", request.getRequestURL());
//method:请求类型 get/post/put/delet
logger.info("method={}", request.getMethod());
//ip
logger.info("ip={}", request.getRemoteAddr());
//类方法
logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//参数
logger.info("args={}", joinPoint.getArgs());
}
@After("log()")
public void doAfter() {
logger.info("222222222222");
}
//获取http请求返回的内容
@AfterReturning(returning = "object", pointcut = "log()")
public void doAfterReturning(Object object) {
logger.info("response={}", object.toString());
}
}
使用Log打印日志
3. 统一异常处理
方式一
通过逻辑判断异常的发生,返回对应的信息
根据是否发生异常返回不同的内容
@Data
public class Result<T> {
/** 错误码. */
private Integer code;
/** 提示信息. */
private String msg;
/** 具体的内容. */
private T data;
}
所以的逻辑判断应该放在service里面,这里为了方便就放在了Controller里面
- 有重复代码不进行优化,写一个工具类
工具类
public class ResultUtil {
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;
}
}
使用工具类
/**
* 添加一个女生
* @return
*/
@PostMapping(value = "/girls")
public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return ResultUtil.error(1, bindingResult.getFieldError().getDefaultMessage());
}
girl.setCupSize(girl.getCupSize());
girl.setAge(girl.getAge());
return ResultUtil.success(girlRepository.save(girl));
}
方式二
使用throw抛出对应自定义的异常来完成相应的业务逻辑
- 抛出Exception:Exception抛出的已成为系统必须处理的异常
使用Exception直接抛出已成会返回一些我们不需要的信息
我们可以对异常进行捕获,包装一下,再返回
返回的内容就是我们设置的
方式三
由于Exception只能传入一个参数,我们可以继承RuntimeException自己写一个异常类
自定义异常
优化:
对异常 code和信息使用enum进行统一的管理
public enum ResultEnum {
UNKONW_ERROR(-1, "未知错误"),
SUCCESS(0, "成功"),
PRIMARY_SCHOOL(100, "我猜你可能还在上小学"),
MIDDLE_SCHOOL(101, "你可能在上初中"),
;
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;
}
}
4. 单元测试
- 添加以下注解
@RunWith(SpringRunner.class)
@SpringBootTest //表示测试时将启整个springBooot工程
对service测试
@RunWith(SpringRunner.class)
//@SpringBootTest表示测试时将启整个springBooot工程
@SpringBootTest
public class GirlServiceTest {
@Autowired
private GirlService girlService;
@Test
public void findOneTest() {
Girl girl = girlService.findOne(73);
Assert.assertEquals(new Integer(13), girl.getAge());
}
}
对controller测试
使用MockMvc类
- 添加以下注解
@RunWith(SpringRunner.class)
//@SpringBootTest表示测试时将启整个springBooot工程
@SpringBootTest
@AutoConfigureMockMvc
@RunWith(SpringRunner.class)
//@SpringBootTest表示测试时将启整个springBooot工程
@SpringBootTest
@AutoConfigureMockMvc
public class GirlControllerTest {
@Autowired
private MockMvc mvc;
@Test
public void girlList() throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/girls"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("abc"));
}
}
打包时跳过单元测试
mvn clean package -Dmaven.test.skip=true
或者使用IDEA