Joinpoint(连接点) 指那些被拦截到的点,在 Spring 中,可以被动态代理拦截目标类的方法。
Pointcut(切入点) 指要对哪些 Joinpoint 进行拦截,即被拦截的连接点。
Advice(通知) 指拦截到 Joinpoint 之后要做的事情,即对切入点增强的内容。
Target(目标) 指代理的目标对象。
Weaving(植入) 指把增强代码应用到目标上,生成代理对象的过程。
Proxy(代理) 指生成的代理对象。
Aspect(切面) 切入点和通知的结合。
package todayTest.application.modle;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-08-18
* Time: 10:13
*/
public class DiyException extends Exception {
public DiyException(String message) {
super(message);
}
}
//访问test12直接返回自定义异常
@RequestMapping(value = "test12")
public Object test12() throws DiyException {
throw new DiyException("这是一个自定义异常");
}
package todayTest.application.interceptor;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import todayTest.application.modle.DiyException;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-08-18
* Time: 10:24
*/
//指名身份, 这是一个拦截Controller中web请求进行统一处理的类
@ControllerAdvice
public class AppControllerAdvice {
//指定处理请求方法中抛出的异常
@ExceptionHandler(DiyException.class)
@ResponseBody
public Object handler(DiyException d) {
return d.getMessage();
}
}
使用@ControllerAdvice注解实现 并且要实现ResponseBodyAdvice接口 (可以有多个)
package todayTest.application.modle;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-08-18
* Time: 10:41
*/
//这是一个统一的返回数据格式
@Getter
@Setter
@ToString
public class ReturnFormat {
private boolean success; //请求是否成功
private Object data; //成功返回的数据
private String code; // 错误的话返回的提示信息
private String message; //描述
}
//web请求访问这里我们直接返回一个bean对象 然后使用统一数据格式对其进行封装
@RequestMapping(value = "test13", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Object test13() {
return test1;
}
package todayTest.application.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import todayTest.application.modle.DiyException;
import todayTest.application.modle.ReturnFormat;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-08-18
* Time: 10:24
*/
//指名身份, 这是一个拦截Controller中web请求进行统一处理的类
@ControllerAdvice
//实现ResponseBodyAdvice接口实现统一数据的封装
//注意要设置为Object类型
public class AppControllerAdvice implements ResponseBodyAdvice<Object> {
//指定处理请求方法中抛出的异常
@ExceptionHandler(DiyException.class)
@ResponseBody
public Object handler(DiyException d) {
return d.getMessage();
}
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
//执行Controller中的web请求方法结束,返回数据到前端的时候,是否要重写响应体
//如果返回的是true就是要执行重写 反之不重写
//这里我们方便演示就让全部数据都要按照我们的自定义格式返回数据
return true;
}
@SneakyThrows
//大胆的抛出异常
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
//如果存在返回字符串的情况,需要返回字符串类型,否则会报错
//解决方案:判断o对象的类型:
//如果是字符串,就返回objectmapper序列化后的字符串,否则返回统一封装的类型
if (o.getClass().equals(String.class)) {
//判断是字符串类型将数据以json格式返回
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(o);
}
//在这里我们统一返回我的自定义的ReturnFormat格式 将数据封装到这个格式里
// o就是我们返回的数据
ReturnFormat returnFormat = new ReturnFormat();
returnFormat.setSuccess(true);
returnFormat.setData(o);
returnFormat.setMessage("返回的是我们自定义的格式");
return returnFormat;
}
}
通过在@Configuration注解下实现WebMvcConfigurer接口, 重写接口方法来完成配置
package todayTest.application.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import todayTest.application.interceptor.LoginIInterceptor;
import todayTest.application.modle.Person;
import java.util.HashMap;
import java.util.Map;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-08-17
* Time: 10:19
*/
@Configuration
//用于启动时完成的配置工作
public class PersonConfiguration implements WebMvcConfigurer {
//实现WebMvcConfigurer实现拦截器
//重写addInterpetor方法
@Override
public void addInterceptors(InterceptorRegistry registry) {
//实现用户会话管理的功能
//在这里进行路径拦截选择
//下面的设置表示我拦截以/per/开头的所有路径, 但是除了/per/test14我是不会拦截的
//如果拦截到我就去执行addInterceptor中LoginInterceptor的方法
registry.addInterceptor(new LoginIInterceptor()).addPathPatterns("/per/**").excludePathPatterns("/per/test14");
}
}
package todayTest.application.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.servlet.HandlerInterceptor;
import todayTest.application.modle.ReturnFormat;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Created with IntelliJ IDEA.
* Description: If you don't work hard, you will a loser.
* User: Listen-Y.
* Date: 2020-08-18
* Time: 13:54
*/
//如果拦截到路径会来到这里
//这里要实现HandlerInterceptor接口
public class LoginIInterceptor implements HandlerInterceptor {
/**
* Controller中请求方法执行前,就会调用preHandle,返回值决定是否在继续执行Controller中的方法
* return true:继续执行Controller中的方法
* return false:不执行了
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//这里实现的是一个登录会话管理
//我将获取request中的session
// 如果没有session表示他未进行登录就无法访问我们拦截到的这个路径
// 然后返回false 就不会执行Controller中的方法
HttpSession session = request.getSession(false);
if (session != null) {
//进行了登录
return true;
}
//未进行登录
ReturnFormat returnFormat = new ReturnFormat();
returnFormat.setSuccess(false);
returnFormat.setCode("ERROR");
returnFormat.setMessage("无法访问,请先登录");
response.setContentType("application/json; charset=utf-8");
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(returnFormat);
response.getWriter().write(jsonStr);
return false;
}
}
//这这里表示进行一个登录
@RequestMapping(value = "test14")
@ResponseBody
public Object test14(HttpServletRequest request) throws DiyException {
HttpSession session = request.getSession(true);
if (session.isNew()) {
//之前未进行登录
String username = request.getParameter("username");
String password = request.getParameter("password");
session.setAttribute("username", username);
session.setAttribute("password", password);
return "登录成功";
}
//之前已经登录过了
throw new DiyException("已经登录");
}