转发与重定向
//转发:同一个服务器中不同的服务进行转发 //浏览器发送了一个请求 可以转发到项目中受保护的资源WEB-INF //转发是request对象执行forward方法 //forward":"redirect:https://www.baidu.com";/ 转发是在服务器内部完成的,不会通知客户端,因此浏览器地址栏的URL不会改变。 //重定向:可以再不同的服务之间跳转 //浏览器发送了两次请求 //重定向是通过response对象通知浏览器重新访问 redirect 重定向是由客户端浏览器发起的,因此浏览器地址栏的URL会随之改变。
AOP面向切面编程
相关概念
连接点Joint point:表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问 以及异常处理块的执行等等,他自身也可以嵌套其他的Joint point。
切点Pointcut:表示一组joint point,定义了切面应用的具体位置或条件,可以匹配一个或多个方法,构造块等
通知Advice:定义了切面在切入点(point cut)上要执行的操作
织入Weaving:将切面应用到目标对象的过程
切面Aspect:Aspect类似于java中的类声明,类Aspect中会包含这一些Pointcut以及响应的Advice。
通知Advice根据执行时机的不同,可以分为以下几种类型:
1.前置通知(before):在方法执行之前运行。
2.后置通知(after):在方法执行之后运行,不论方法是否抛出异常。
3.返回通知(After Returning):在方法成功返回后运行。
4.异常通知(After Throwing):在方法抛出异常后运行
5.环绕通知(Around):包围了目标方法的执行,可以在目标方法执行前后进行自定义操作。
AOP的应用场景
日志记录:在方法执行前后记录日志,而无需修改业务逻辑
安全性检查:在方法执行前进行权限验证
事务管理:在方法执行期间开启和关闭事务
异常处理:统一处理异常,不必再每个代码中重复写相同的处理代码
优点
- 解耦代码:通过将横切关注点分离到切面中,减少了代码的耦合度。
- 提高代码可维护性:修改横切关注点的逻辑只需调整切面,而不必修改业务逻辑代码。
- 代码复用性:相同的切面可以应用于多个模块,减少重复代码。
@Aspect //将类标识为一个切面类 @Component//声明为Spring的一个组件,可被Spring管理 public class AOPObj { //定义切点 切点pointCuttesta匹配了EasyController类中的testA方法 @Pointcut("execution(* org.example.controller.EasyAController.testA(..))") public void pointCuttesta(){ } @Before("pointCuttesta()")//定义一个前置通知,会在切点类方法执行前执行 public void before(){ System.out.println("前置通知"); } }
代理模式
代理模式是常见的设计模式之一,顾名思义,代理模式就是代理对象具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理。(为真实对象提供代理,然后供其他对象通过代理访问真实对象)
静态代理
真实类和代理类要实现同一个接口,在代理类中实现真实类的方法同时可以进行真实类方法的增强处理,在一个代理类中就可以完成对多个真实对象的注入工作。
自我总结:代理类proxy会声明一个 接口类的对象,然后再构造方法中将它指向真实类,这样就有了一个上转型对象,在proxy重写的方法中不仅可以调用该上转型指向的子类(真实类)的方法,也可以在它的方法前后添加某些操作。(因为都要使用同样的方法,所以代理类和真实类要实现同一个接口)
动态代理
从静态代理的代码中可以发现,静态代理的缺点显而易见,那就是当真实类的方法越来越多的时候,这样构建的代理类的代码量是非常大的,所以就引进动态代理.
动态代理允许使用一种方法的单个类(代理类)为具有任意数量方法的任意类(真实类)的多个方法调用提供服务(使用反射实现)
dk动态代理实现的是jdk自带InvocationHandler接口,实现了这个接口的类也叫拦截器类,也叫代理类。InvocationHandler
是一个接口,它定义了代理实例的处理方法。当代理对象调用方法时,实际会执行 InvocationHandler
接口的 invoke
方法。
还有许多场景是没有接口的,这个时候就需要cglib动态代理了,CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。被代理的类不能使用final修饰
自我总结:我们有一个接口和一个实现了该接口的真实类,
有一个要实现了InvocationHandler接口的类作为代理类,在代理类中声明一个Object类的对象,在构造方法中会传入一个真实类对象作为参数,然后同上,创建上转型对象;
关键点在于代理类中的invoke方法,它来自InvocationHandler接口,我们会在方法里面使用method.invoke(上转型对象,args)方法来调用真实类对象中的方法。
最后这个工厂类中声明了一个真实类的对象,并且用一个Object类的对象通过代理类方法getProxy指向了真实类,从而实现了上转型
InvocationHandler
是 Java 中动态代理机制的重要接口。实现 InvocationHandler
的主要目的是提供一种动态拦截方法调用的方式,以在运行时增强对象的行为,而无需修改对象的实际代码。
SpringMVC
Spring MVC 是 Spring 框架中的一个重要模块,用于构建基于 Java 的 Web 应用程序。Spring MVC(Model-View-Controller)实现了模型-视图-控制器设计模式,提供前端路由映射、视图解析等功能
MVC是Spring框架中的一种设计模式
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发
主要解决的问题
- 解决了应用程序中业务逻辑、数据和界面显示的耦合问题,使得开发和维护更加清晰和简单。
使用场景
- 当需要将数据、业务逻辑和界面显示分离,以便于独立开发和维护时。
实现方式
- 模型(Model):负责数据和业务逻辑,通常包含数据存储、检索和业务规则。
- 视图(View):负责显示数据(模型)的用户界面,不包含业务逻辑。
- 控制器(Controller):接收用户的输入,调用模型和视图去完成用户的请求
我的总结:模型是一个可以储存信息和业务逻辑的对象,比如一个拥有ID、姓名、性别、工资属性的类
视图则是在用户页面上显示这些信息的增删改
控制器是接收来自用户网页段的信息,调用响应Mapping标识的方法并返回结果给用户
常见注释
@Controller
@Controller是Spring框架中的一个注解,用于标记一个类为SpringMVC控制器,标注后的类可以通过Mapping标注的方法与网页端进行交互
@RestController
@RestController
注解用于定义 RESTful Web 服务的控制器类,自动将方法的返回值序列化为 JSON 或 XML 数据,并写入 HTTP 响应体中。
@RequestMapping
@RequestMapping
是 Spring 框架中用于处理 HTTP 请求的注解,它可以将 HTTP 请求映射到控制器的方法上。在控制器上标注以后,在网页端调用其中的Mapping类时都要在前面加上@RequestMapping指定的内容
@PathVariable
@PathVariable
是 Spring 框架中的一个注解,用于将 URL 模板中的路径变量绑定到控制器方法的参数上。从 URL 中提取路径变量并将其绑定到控制器方法的参数上。
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
// 获取用户信息
@GetMapping("/{id}")
public String getUser(@PathVariable("id") int userId) {
return "User ID: " + userId;
}
// 更新用户信息
@PutMapping("/{id}")
public String updateUser(@PathVariable("id") int userId, @RequestBody String newUserInfo) {
return "Updated user ID: " + userId + " with info: " + newUserInfo;
}
// 删除用户
@DeleteMapping("/{id}")
public String deleteUser(@PathVariable("id") int userId) {
return "Deleted user ID: " + userId;
}
}
@RequestParam
@RequestParam
是 Spring 框架中的一个注解,用于将请求参数绑定到控制器方法的参数上。
@RestController
public class UserController {
@GetMapping("/greet")
public String greet(@RequestParam(name = "name", defaultValue = "World") String name,
@RequestParam(name = "age", required = false) Integer age) {
return "Hello, " + name + (age != null ? " Age: " + age : "");
}
}
标注里面的内容被添加到方法的返回中
@Get/Post/Put/DeleteMapping
Spring 框架中用于处理 HTTP 请求的专用注解。它们是 @RequestMapping
注解的快捷方式,用于处理特定的 HTTP 方法
@GetMapping
: 处理 GET 请求,用于从服务器获取数据。@PostMapping
: 处理 POST 请求,用于向服务器提交数据。@PutMapping
: 处理 PUT 请求,用于更新资源或提交完整数据。@DeleteMapping
: 处理 DELETE 请求,用于删除资源。
MVC的运行原理
我的简化理解:(每个部件处理完后都会返回给核心处理器让它再送达到相应的处理部件)
1.所有请求到达核心处理器(前端控制器)DispatcherServlet
2.通过映射器(HandlerMapping)到达每一个具体的处理器(Handler)
3.通过处理器处理后返回一个ModelAndView,
4.核心处理器将ModelAndView传达给相应的视图解析器进行处理
5.视图解析器将视图渲染为HTML
6.DispatcherServlet将HTML响应给用户端
MVC中的拦截器
拦截器类通过实现Interceptor接口来定义请求处理的前后逻辑
与切点的不同:
切点主要在方法实现的前后进行操作
拦截器是在网页流程处理的前后进行操作,方法中的参数很不一样
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Before handling the request");
return true; // 继续处理请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("After handling the request but before rendering the view");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("After rendering the view");
}
}
preHandle
: 在请求到达控制器之前执行,用于检查或处理请求。postHandle
: 在控制器处理完请求但视图渲染之前执行,用于修改模型数据。afterCompletion
: 在请求处理完毕并且视图渲染之后执行,用于清理资源或记录日志。
参数解释:
HttpServletRequest request
: 当前 HTTP 请求对象。可以用来访问请求信息。HttpServletResponse response
: 当前 HTTP 响应对象。可以用来访问或修改响应信息。Object handler
: 处理器对象。通常是处理该请求的控制器(Controller)对象ModelAndView modelAndView
: 控制器返回的模型和视图对象。ModelAndView
包含了控制器返回的数据和视图名称。在此方法中,你可以修改模型数据或视图信息。Exception ex
: 处理请求过程中发生的异常。如果请求处理过程中没有异常,这个参数为null
。你可以使用它来进行异常处理或记录日志。
MVC异常处理机制
1.使用@ExceptionHandler注解
@ExceptionHandler允许在控制器类中定义异常处理方法,可以在方法中处理特定异常并返回自定义的响应
@RestController
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return new ResponseEntity<>("An error occurred: " + ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@ControllerAdvice
: 注解用于定义全局的异常处理器。它可以与@ExceptionHandler
一起使用来处理应用程序中的异常。@ExceptionHandler(Exception.class)
: 指定处理所有Exception
类型的异常。你也可以指定特定的异常类型。