1.代理模式
代理模式分为静态代理和动态代理
代理模式,就是在想要执行的代码之前或之后添加代码块,并不会破坏原有的代码结构。可以理解成加上了一个访问层
1.静态代理
创建一个接口Shopping
java
public interface Shopping {
void shopping();
}
创建一个EasyA类实现接口Shopping,重写shopping方法
java
public class EasyA implements Shopping{
@Override
public void shopping() {
System.out.println("去购物");
}
}
创建一个Proxy类,实现接口,重写shopping方法
java
public class Proxy implements Shopping{
Shopping s;
public Proxy(Shopping s){
this.s=s;
}
@Override
public void shopping() {
System.out.println("--------- 一支穿云箭");
s.shopping();
System.out.println("--------- 千军万马来相见");
}
}
创建一个工厂类,主函数在这个类中演示
java
public class Factory {
public static Shopping getShopping(){
EasyA a=new EasyA();
Shopping s=new Proxy(a);
return s;
}
public static void main(String[] args) {
Shopping shopping = getShopping();
shopping.shopping();
}
}
最终效果为:
可以将两段输出-----,想象成添加的访问层
静态代理的优点:1.易于理解
静态代理的缺点:1.代码冗余 2.不易维护
2.动态代理
1.JDK动态代理 组合,被代理类必须实现接口
创建一个接口 EasyInterface
java
public interface EasyInterface {
void easy();
}
创建一个类实现接口
java
public class EasyObj implements EasyInterface{
@Override
public void easy() {
System.out.println("---- 正常业务逻辑");
}
}
创建第二个类(被代理对象,必须实现接口)
java
public class EasyInvocationHandler implements InvocationHandler {
private Object proxyedObj;//被代理对象
EasyInvocationHandler(Object proxyedObj){
this.proxyedObj=proxyedObj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=null;//定义方法的返回对象
System.out.println("----执行方法之前添加的业务");
//正常执行业务逻辑
result=method.invoke(proxyedObj,args);
System.out.println("----执行方法之后的处理");
return result;
}
}
创建一个工厂类:
java
public class Factory {
public static Object getproxy(Object obj){
//jdk代理只能实现接口中的方法
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(), //类加载器
obj.getClass().getInterfaces(),//实现的接口
new EasyInvocationHandler(obj)
);
}
public static void main(String[] args) {
EasyObj easy=new EasyObj();
Object obj=getproxy(easy);//动态生成的一个代理类的对象
if (obj instanceof EasyInterface){
System.out.println("obj是代理对象,是EasyInterface的实例");
}
Class c=obj.getClass();
System.out.println(c);
EasyA easya=new EasyA();
obj=getproxy(easya);
System.out.println(obj.getClass());
}
}
2.CGLIB动态代理 继承,被代理类不能被final修饰
java
@Component
public class EasyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("----preHandle");
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--整个请求处理完毕");
}
}
java
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
EasyInterceptor easyInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(easyInterceptor).addPathPatterns("/methodc");
}
}
2.AOP
定义:
AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。
作用:
AOP可以拦截指定的方法并且对方法增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离
AOP中一些专业术语:
Spring AOP中通知的分类:
3.SpringMVC
1.两种Controller注解的区别
两种Controller注解分别为:@Controller @RestController
当在类上写@Controller注解时,类中被标注为@RestMapping的方法的返回值,会被识别为地址,即我们在网址栏填写的地址。
当在类上写@RestController注解时,类中被标注为@RestMapping的方法的返回值,会被识别为返回内容。
2.@RestMapping注解
1.注解在方法时
当在类中方法标识上@RestMapping注解,在网站输入框中输入 http:/localhost:8080/注解地址,就会跳转到地址页
java
@RestController //Rest 请求资源状态转换
public class EasyDController {
@RequestMapping("nice")
public String nice(){
return "NICE METHOD";
}
}
2.注解在类时
注解在类时,需要在地址栏先输入父层地址,再输入子层地址
java
@RestController //Rest 请求资源状态转换
@RequestMapping("user")
public class EasyDController {
@RequestMapping("nice")
public String nice(){
return "NICE METHOD";
}
}
3.@PathVariable注解
不添加@PathVariable注解时需要在地址栏按实参填入
java
@RestController //Rest 请求资源状态转换
@RequestMapping("user")
public class EasyDController {
//接收前端的参数 方法的参数名称和前台传递的参数名一样才可以接收到
@RequestMapping("parama")
public String paramA(String name){
return "SpringMVC接收到的参数是:"+name;
}
}
在方法参数列表中填入,在地址栏就不需要按照实参名称输入值
java
@RequestMapping("paramd/{id}")
public String paramd(@PathVariable Integer id, HttpServletRequest request){
String username = request.getParameter("username");
return "接收到的参数是:"+id+"----username="+username;
}
4.请求转发 和 重定向 的区别
1.请求转发:
同一个服务器中不同的服务进行转发,浏览器发送了一个请求,可以转发到项目中受保护的资源WEB-INF 转发是request对象执行forward方法
java
@Controller
public class EasyEController {
@RequestMapping("methoda")
public String methodA(){
System.out.println("----methodA");
return "forward:/methodb";
}
@RequestMapping("methodb")
@ResponseBody
public String methodB(){
System.out.println("----methodB");
return "this is methodb";
}
}
注意地址栏为localhost:8080/methoda,说明是先访问到methoda,在methoda下的方法中请求转发到了methodb,显示的是methodb中方法的内容
2.重定向:
可以在不同的服务之间跳转,浏览器发送两次请求,重定向是通过response对象通知浏览器重新访问 执行的是redirect方法
java
@Controller
public class EasyEController {
@RequestMapping("methoda")
public String methodA(){
System.out.println("----methodA");
return "redirect:/methodb";
}
@RequestMapping("methodb")
@ResponseBody
public String methodB(){
System.out.println("----methodB");
return "this is methodb";
}
}
注意此时的地址栏,我们访问的是 localhost:8080/methoda,但是访问后却变成了localhost:8080/methodb,说明在我们访问methoda时,我们的访问请求直接重定向到了methodb
4.SpringMVC 运行原理
我们的MVC,即Model View Controller,在下面的图中有体现
5.拦截器
拦截器(Interceptor)是 Spring MVC 提供的一种强大的功能组件。它可以对用户请求进行拦截,并在请求进入控制器(Controller)之前handler、控制器处理完请求后、甚至是渲染视图后,执行一些指定的操作。在 Spring MVC 中,拦截器主要用于拦截用户请求并做相应的处理,例如通过拦截器,我们可以执行权限验证、记录请求信息日志、判断用户是否已登录等操作。
java
@Component
public class EasyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("----preHandle");
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--整个请求处理完毕");
}
}