Spring MVC是一种基于Java的轻量级Web应用开发框架,它是Spring框架的一部分。Spring MVC采用了经典的MVC(Model-View-Controller)设计模式,用于构建可扩展、高效和灵活的Web应用程序。
在Spring MVC中,模型(Model)表示应用程序的数据和业务逻辑,视图(View)负责展示数据给用户,控制器(Controller)负责接收用户的请求并处理相应的逻辑。通过这种分层的架构,实现了业务逻辑与用户界面的解耦,提高了代码的可维护性和可测试性。
Spring MVC的核心是DispatcherServlet,它是前端控制器(Front Controller),负责接收所有的请求,并将请求分发给相应的处理器(Handler)。处理器可以是一个简单的Java类,也可以是一个注解了@Controller的类,通过处理器适配器(Handler Adapter)将请求映射到处理器方法上。
骚戴扩展:Spring MVC还提供了丰富的功能,如请求参数绑定、数据验证、异常处理、国际化支持等。它采用了基于注解的配置方式,简化了开发过程,同时也提供了灵活的配置选项,以适应不同项目的需求。
Spring MVC作为一种轻量级的MVC框架,具有以下几个优点:
1. 松耦合:Spring MVC采用了松耦合的设计,通过依赖注入和面向接口编程,使得各个组件之间的耦合度降低。这样可以提高代码的可维护性和可测试性。
2. 灵活性:Spring MVC框架提供了灵活的配置选项,可以根据项目需求进行定制。开发人员可以选择适合自己的视图解析器、处理器映射器、异常处理器等组件,以及配置拦截器和过滤器等。
3. 易于集成:Spring MVC框架与其他Spring框架(如Spring Boot、Spring Security等)无缝集成,可以方便地与其他技术栈进行整合,如持久层框架、前端框架等。
4. 强大的扩展性:Spring MVC框架提供了丰富的扩展点和插件机制,可以通过自定义拦截器、处理器适配器等来扩展框架的功能。同时,Spring MVC也支持自定义注解、数据绑定和验证器等,以满足不同项目的需求。
5. 高效性能:Spring MVC框架在处理请求时采用了基于注解的映射方式,可以快速地将请求映射到对应的处理器方法上,提高了请求的处理效率。同时,Spring MVC还提供了缓存机制、视图解析器缓存等优化手段,进一步提升了系统的性能。
前端控制器【中央控制器】(DispatcherServlet):DispatcherServlet是Spring MVC的核心组件,它负责接收所有的请求,并将请求分发给适当的处理器(Controller)进行处理。它还负责处理请求的生命周期、请求参数的解析、视图的渲染等。
处理器映射器(HandlerMapping):HandlerMapping负责将请求映射到对应的处理器(Controller)。它根据请求的URL、请求方法等信息来确定使用哪个处理器来处理请求。Spring MVC提供了多种HandlerMapping的实现,例如基于注解的RequestMappingHandlerMapping、基于路径的SimpleUrlHandlerMapping等。
处理器适配器(HandlerAdapter):将请求的处理委派给不同类型的处理器进行处理。它负责根据处理器的类型和特性,调用合适的方法来执行请求的处理逻辑,并将处理结果返回给DispatcherServlet
后端控制器(处理器)(Handler):Handler是真正处理请求的组件,它负责处理特定的请求,并生成相应的结果。Handler可以是一个POJO(Plain Old Java Object)类,使用@Controller注解标记,或者实现特定的接口(如HttpRequestHandler、Controller等)。处理器可以执行业务逻辑、调用服务、查询数据库等。
视图解析器(ViewResolver):ViewResolver负责将处理器返回的逻辑视图名解析为具体的视图对象。视图对象可以是JSP、Thymeleaf模板、Freemarker模板等。ViewResolver还负责对视图进行渲染,生成最终的响应内容。
View(视图):View是最终呈现给用户的内容,它负责将模型数据渲染为HTML、XML、JSON等格式的响应。视图通常使用模板引擎来生成最终的内容。
DispatcherServlet是Spring MVC框架的核心组件之一,也是整个请求处理流程的入口点。它充当了前端控制器(Front Controller)的角色,负责接收所有的请求,并将请求分发给相应的处理器(Handler)进行处理。
当客户端发送一个请求时,DispatcherServlet首先接收到该请求。然后,它会根据配置的请求映射规则,将请求分发给对应的处理器。处理器可以是一个简单的Java类,也可以是一个注解了@Controller的类。
DispatcherServlet还负责协调和管理请求处理过程中的其他组件,如处理器适配器(Handler Adapter)、视图解析器(View Resolver)、数据绑定、数据验证、异常处理等。它将处理器的处理结果封装为一个ModelAndView对象,并选择合适的视图进行渲染。
除了请求分发和协调功能,DispatcherServlet还提供了一些其他的特性和配置选项,如拦截器(Interceptor)、过滤器(Filter)、文件上传、国际化支持等。
通过DispatcherServlet的统一入口,Spring MVC框架能够实现请求的集中处理和统一管理,提高了代码的可维护性和可扩展性。它简化了开发流程,并提供了灵活的配置选项,以适应不同项目的需求。
在Spring MVC框架中,控制器(Controller)是负责处理用户请求并返回响应的组件。控制器是整个请求处理流程中的核心部分,它接收来自前端控制器(DispatcherServlet)的请求,并根据请求的类型和内容执行相应的业务逻辑。
在Spring MVC中,控制器可以是一个简单的Java类,也可以是一个注解了@Controller的类。控制器类通常包含多个处理器方法(Handler Method),每个处理器方法对应一个具体的请求处理逻辑。
处理器方法通常使用@RequestMapping注解来标识其对应的URL路径。当DispatcherServlet接收到请求后,会根据请求的URL路径和请求方法,选择合适的控制器和处理器方法进行处理。
处理器方法可以接收请求参数,包括路径参数、查询参数、表单参数等。Spring MVC框架提供了多种方式来绑定请求参数到方法的参数上,如@RequestParam注解、@PathVariable注解等。
控制器方法执行完成后,会将处理结果封装为一个ModelAndView对象,其中包含了要显示的视图名称和模型数据。然后,DispatcherServlet会根据配置的视图解析器(View Resolver)来解析视图,并将模型数据传递给视图进行渲染。
控制器在Spring MVC框架中起到了连接前端和后端的作用,它负责接收用户请求、处理业务逻辑,并将结果返回给前端。通过控制器的灵活配置和处理器方法的定义,开发者可以实现各种复杂的请求处理逻辑,实现高效、可维护的Web应用程序。
答:是单例模式,所以在多线程访问的时候有线程安全问题
如果要保证Controller的线程安全,有以下解决办法:
1、尽量不要在 Controller 中定义成员变量;
2、如果必须要定义一个非静态成员变量,那么可以通过注解 @Scope(“prototype”),将Controller设置为多例模式。
Controller
@Scope(value="prototype")
public class TestController {
private int num = 0;
@RequestMapping("/addNum")
public void addNum() {
System.out.println(++num);
}
}
简而言之就是最好不要在控制器里定义成员变量,因为它是线程不安全的,如果非要定义那就把单例模式改成多例模式
1、用户点击某个请求路径,发起一个request请求,此请求会被前端控制器处理。
2、前端控制器请求处理器映射器去查找Handler。可以依据注解或者XML配置去查找。
3、处理器映射器根据配置找到相应的Handler(可能包含若干个Interceptor拦截器),返回给前端控制器。
4、前端控制器请求处理器适配器去执行相应的Handler处理器(常称为Controller)。
5、处理器适配器执行Handler处理器。
6、Handler处理器执行完毕之后会返回给处理器适配器一个ModelAndView对象(SpringMVC底层对象,包括Model数据模型和View视图信息)。
7、处理器适配器接收到Handler处理器返回的ModelAndView后,将其返回给前端控制器。
8、前端控制器接收到ModelAndView后,会请求视图解析器(ViewResolver)对视图进行解析。
9、视图解析器根据View信息匹配到相应的视图结果,反馈给前端控制器。
10、前端控制器收到View具体视图后,进行视图渲染,将Model中的模型数据填充到View视图中的request域,生成最终的视图(View)。
11、前端控制器向用户返回请求结果。
MVC(Model-View-Controller)是一种软件设计模式,用于将应用程序的逻辑和用户界面分离,以提高代码的可维护性和可扩展性。MVC模式将应用程序分为三个主要部分:模型(Model)、视图(View)和控制器(Controller)。
- 模型(Model):模型表示应用程序的数据和业务逻辑。它负责处理数据的读取、存储和更新,以及执行业务操作。模型是独立于用户界面的,它不直接与用户交互。
- 视图(View):视图负责展示数据给用户。它是用户界面的一部分,负责将模型中的数据以适当的方式呈现给用户。视图通常是被动的,它根据模型的状态来更新自己的显示。
- 控制器(Controller):控制器接收用户的输入,并根据输入来更新模型和视图。它负责处理用户的请求,调用相应的业务逻辑,并更新模型的状态。控制器还负责将模型的数据传递给视图进行显示。
MVC设计模式的好处包括:
1. 解耦合性:MVC模式可以降低耦合性,提高代码的可维护性和可扩展性。
2. 可重用性:通过将应用程序的逻辑和用户界面分离,可以更容易地重用模型和视图。模型可以在不同的控制器中共享,视图可以在不同的模型上重用。
3. 并行开发:MVC模式允许团队中的不同开发人员同时开发不同的模块。模型、视图和控制器的独立性使得并行开发更加容易。
4. 可测试性:由于模型、视图和控制器的分离,可以更容易地对它们进行单元测试和集成测试。模型的业务逻辑可以独立测试,视图的显示逻辑可以独立测试,控制器的请求处理逻辑也可以独立测试。
注解质上是一个继承了Annotation接口的特殊接口,用于在代码中添加元数据信息。当你用注解修饰某个元素(如类、方法、字段等),编译器会在编译期扫描每个元素上的注解,并将注解信息写入元素的属性表。
在运行时,当通过反射获取注解时,虚拟机将会将所有生命周期为RUNTIME的注解取出,并创建一个AnnotationInvocationHandler实例,将注解信息传递给它。AnnotationInvocationHandler是一个代理处理器,通过代理对象调用注解的方法时,最终会调用AnnotationInvocationHandler的invoke方法。
在invoke方法中,会从注解的属性表(memberValues)中索引出对应的值,并将这些值设置到使用该注解的元素中。注解的属性值来自于注解在代码中的声明,可以是常量、枚举值、其他注解或基本类型的值。
骚戴理解:简单来说就是通过方法名返回注解属性值。但需要注意的是,注解的属性值是从注解的属性表中获取。属性表(memberValues)是一个 Map 键值对,键是我们注解属性名称,值就是该属性当初被赋上的值
好文参考:JAVA 注解的基本原理 - Single_Yam - 博客园
@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,即指明处理器可以处理哪些URL请求,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody
将HTTP请求的内容(如JSON、XML等)转换为java对象。
@ResponseBody
@ResponseBody
注解用于指示控制器方法的返回值应该作为响应体直接返回给客户端,而不是解析为视图。它可以用于控制器类级别或方法级别。
@ResponseBody
注解,表示该控制器类的所有方法都会返回JSON格式的数据。这意味着不需要为每个方法都添加@ResponseBody
注解。@ResponseBody
注解,表示只有该方法返回的数据会被解析为JSON格式的数据,其他方法的返回值则会根据配置进行处理(例如解析为视图),但如果返回的是一个普通的字符串,Spring并不会自动将其转换为JSON格式。当方法返回值是字符串,那么直接将字符串写到客户端;如果你希望返回的字符串按照JSON格式传递给前端,可以使用@RestController
注解来代替@Controller
注解。@RestController
注解相当于@Controller
和@ResponseBody
的组合,它会将所有方法的返回值自动转换为JSON格式答:一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外,一般不用别的注解代替。
`@Controller`是Spring框架中的一个注解,用于标识一个类为控制器(Controller)。控制器是Spring MVC框架中的组件,用于处理用户请求并返回相应的视图或数据。控制器类中的方法可以使用`@RequestMapping`等注解来处理特定的请求路径和HTTP方法。当请求匹配到某个控制器方法时,Spring框架会调用相应的方法来处理请求。控制器方法可以调用服务层(Service)或其他组件来执行业务逻辑,处理用户请求,并根据需要返回相应的视图或数据。控制器方法通常返回一个逻辑视图名,由Spring MVC的视图解析器解析为实际的视图。视图解析器可以根据逻辑视图名找到对应的视图模板,并生成最终的视图。Spring MVC框架提供了数据绑定和验证的功能,控制器方法可以使用`@ModelAttribute`、`@Valid`等注解来进行数据绑定和验证操作。
总之,`@Controller`注解的作用是将一个类标识为Spring MVC框架中的控制器,用于处理用户请求并返回相应的视图或数据。
骚戴理解:这里注意@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是Spring MVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。
有两种方式
1、在spring的配置文件中创建该类的实例
上述这种方式是在spring容器中注入单个bean,当项目比较大,控制器类比较多时,用这种方式向Spring容器中注入bean非常的让人苦恼,索性有第二种方式。
2、在Spring MVC的配置文件中,使用
这种方式会扫描指定包中的所有类,并生成相应的bean注入到spring容器中。使用这种方式当然能够极大提高我们的开发效率,但是有时候我们不想某一类型的类注入到spring容器中。可以通过下面的方法解决
上述代码表示扫描test包中除有@Service注解之外的类。
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
RequestMapping注解有六个属性如下所示
value: 指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
method: 指定请求的method类型,GET、POST、PUT、DELETE等 ;
@RequestMapping(value="/toLogin",method = RequestMethod.GET)
consumes: 指定处理request请求中Content-Type为某种类型的请求,例如application/json, text/html;
produces: 指定处理request请求中Accept头中包含了了某种类型的请求,并且表明返回的内容类型是这种类型,例如application/json, text/html;
/**
* consumes 标识处理request请求中Content-Type为“application/json”类型的请求.
* produces标识处理request请求中Accept头中包含了"application/json"的请求.
* 同时暗示了返回的内容类型为application/json;
*/
@ApiOperation(value = "保存用户")
@PostMapping(value = "/execute",produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.APPLICATION_JSON_VALUE)
public String saveUser(@RequestBody User userl){
//TO DO
return "保存成功";
}
params: 限定要处理请求的参数,只有匹配该参数的请求,才会被该方法处理;
@GetMapping(value = "list",params="version=1")
public Object list() {
return "ok";
}
骚戴理解:说白了就是请求url中必须带指定参数才会被这个方法处理
例如 localhost:8080/api/v1/books2/12?version=1这样的请求才会被这个方法处理
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
骚戴理解:其实就是用来匹配特定的请求头
@RequestMapping(
value = "/testParamsAndHeaders",
params = {"username","password!=123456"},
headers = {"Host=localhost:8080"}
)
public String testParamsAndHeaders(){
return "success";
}
@ResponseBody
注解用于指示控制器方法的返回值应该作为响应体直接返回给客户端,而不是解析为视图。它可以用于控制器类级别或方法级别。
@ResponseBody
注解,表示该控制器类的所有方法都会返回JSON格式的数据。这意味着不需要为每个方法都添加@ResponseBody
注解。@ResponseBody
注解,表示只有该方法返回的数据会被解析为JSON格式的数据,其他方法的返回值则会根据配置进行处理(例如解析为视图),但如果返回的是一个普通的字符串,Spring并不会自动将其转换为JSON格式。当方法返回值是字符串,那么直接将字符串写到客户端;如果你希望返回的字符串按照JSON格式传递给前端,可以使用@RestController
注解来代替@Controller
注解。@RestController
注解相当于@Controller
和@ResponseBody
的组合,它会将所有方法的返回值自动转换为JSON格式`@ResponseBody`注解用于指示控制器方法返回的内容应作为响应体直接返回给客户端,而不是解析为视图。当返回对象时,默认情况下会使用UTF-8编码进行处理。
然而,当返回的是字符串类型(`String`)时,默认编码是根据请求头中的`Accept-Charset`来确定的,而不是ISO-8859-1编码。如果请求头中没有指定编码,那么默认使用ISO-8859-1编码。这可能导致在某些情况下出现乱码问题。
为了避免乱码问题,可以在`@RequestMapping`注解中使用`produces`属性来指定返回结果的编码格式,例如:
@RequestMapping(value = "/cat/query", produces = "text/html;charset=utf-8")
这样,无论返回的是对象还是字符串,都会使用UTF-8编码进行处理,确保返回结果在页面上正常显示。
Spring MVC中的消息转换器(HttpMessageConverter)负责将Java对象转换为特定格式的响应数据。当控制器方法返回值需要转换为响应体时,Spring会根据配置的消息转换器,选择合适的实现类进行转换。常见的转换器包括MappingJackson2HttpMessageConverter(用于将对象转换为JSON格式)和StringHttpMessageConverter(用于将字符串转换为响应体)等。
转换后的响应数据会通过HttpServletResponse对象进行设置,设置响应的Content-Type等头部信息,并将转换后的数据作为响应体写入到响应流中,最终返回给客户端。
对于返回的bean对象,会调用对象的getXXX()方法获取属性值,并以键值对的形式进行封装,然后转换为JSON格式的响应数据。
1、导入jackson的依赖
com.fasterxml.jackson.core
jackson-databind
2.11.3
2、在方法前面要加上@ResponseBody 注解。
`@PathVariable`和`@RequestParam`是Spring MVC框架中用于获取请求参数的注解,它们有以下区别:
1. 用途:
- `@PathVariable`:用于从URL路径中提取参数值,适用于RESTful风格的URL,如 `/users/{id}`。
- `@RequestParam`:用于从请求的查询参数中获取参数值,适用于通过查询字符串传递参数,如 `?name=value`。
2. 参数位置:
- `@PathVariable`:通常用于在控制器方法的参数上,用于获取URL路径中的参数值。
- `@RequestParam`:通常用于在控制器方法的参数上,用于获取查询参数的值。
3. 参数名称:
- `@PathVariable`:在注解中需要指定路径变量的名称,例如 `@PathVariable("id")`,其中 "id" 是路径变量的名称。
- `@RequestParam`:在注解中可以指定参数的名称,也可以省略不指定,默认使用方法参数的名称作为参数的名称。
4. 是否必需:
- `@PathVariable`:默认情况下,路径变量是必需的,如果路径中没有对应的变量,会导致请求映射失败。
- `@RequestParam`:默认情况下,查询参数是可选的,如果请求中没有对应的参数,参数值将为 `null`。
骚戴理解:
@PathVariable
:它可以用于接收URL路径中的参数,例如 /users/{id}
中的 {id}
可以通过 @PathVariable
注解来获取。但它也可以用于请求的URL路径中的其他部分,例如 /users/{id}/orders
中的 {id}
部分也可以使用 @PathVariable
注解来获取。
@RequestParam
:它通常用于接收请求的查询参数,例如 ?name=value
中的 name
可以通过 @RequestParam
注解来获取。但它也可以用于接收表单参数、请求头参数等。
我们在使用SpringMVC的时候,经常返回ModelAndView类型,现在前后端分离后,后端都是返回JSON格式数据为主。
返回 ModelAndView类型,我们可以在ModelAndView对象中指定视图名称,然后也可以绑定数据,如下面代码:
@RequestMapping("/userList")
public ModelAndView getAllUser(ModelAndView mv) {
List users= userService.getAllUser();
//添加数据模型到request域中
mv.addObject("users", users);
mv.setViewName("userList");//指定视图名
return mv;
}
如果返回值为void的话,并不是真正没有返回值,而是会出现以下几种情况:
(1)如果方法内真的没有返回值,那么SpringMVC默认把deleteUser(映射的URL)当成视图名称来解析,如果存在该视图,就返回给客户端;如果不存在该视图,就会报视图找不到异常。
@RequestMapping("/deleteUser")
public void deleteUser() {
//删除操作
}
通过加@ResponseBody来修改默认行为,加上该注解表示返回JSON数据,这里返回空JSON数据,而不是把URL当成视图名称来解析
@RequestMapping("/deleteUser")
@ResponseBody
public void deleteUser() {
//删除操作
}
(2)请求转发
@GetMapping("/")
public void root(HttpServletRequest req,HttpServletResponse resp) {
req.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(req,resp);
}
req.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(req,resp);
(3)重定向
@RequestMapping("/")
@ResponseBody
public void root(HttpServletResponse resp){
resp.setStatus(302);
resp.addHeader("Location","/WEB-INF/jsp/index.jsp");
}
@RequestMapping("/")
@ResponseBody
public void root(HttpServletResponse resp){
resp.sendRedirect("/WEB-INF/jsp/index.jsp");
}
resp.sendRedirect("/WEB-INF/jsp/index.jsp");
当方法的返回值为String的时候,也会出现下面几种情况:
(1)逻辑视图名
返回String最常见的是逻辑视图名,这种时候一般利用默认的参数Model来传递数据
@RequestMapping("/deleteUser")
//方法返回JSON数据
@ResponseBody
public String deleteUser(Model model) {
model.addAttribute("msg","删除成功");
return "userList";
}
(2)重定向
登录失败的时候重定向到登录页面。
@RequestParam("/login")
public String redirect(User user){
if{
//登录成功...
}else{
//登录失败,重定向到登录页面
return "redirect:tologin";
}
}
return "redirect:tologin";
(3)请求转发
登录失败的时候请求转发到登录页面。
@RequestParam("/login")
public String redirect(User user){
if{
//登录成功...
}else{
//登录失败,转发到登录页面
return "forward:tologin";
}
}
return "forward:tologin";
(4)真的返回String,相当于JSON格式的数据
@RequestMapping("/deleteUser")
@ResponseBody
public String deleteUser() {
try{
//删除成功
return "删除成功";
}catch(Exception e){
return "删除失败";
}
}
现在前后端分离的情况下,大部分后端只需要返回JSON数据即可,List 集合、Map集合,实体类等都可以返回,这些数据由 HttpMessageConverter自动转为JSON ,如果使用了Jackson或者Gson,不需要额外配置就可以自动返回JSON了,因为框架帮我们提供了对应的HttpMessageConverter ,如果使用了Alibaba的Fastjson的话,则需要自己手动提供一个相应的 HttpMessageConverter的实例,方法的返回值如下面代码:
@GetMapping("/getUser")
@ResponseBody
public User getUser() {
User user = userService.getUser();
return user;
}
@RequestMapping("/userList")
@ResponseBody
public List getAllUser() {
List users = userService.getAllUser();
return users;
}
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理。如果返回的字符串中带 forward: 或 redirect: 前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和redirect: 当成指示符,其后的字符串作为 URL 来处理。
(1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4"
@RequestMapping("/springMvc")
@Controller
public class handler {
//测试转发
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "forward:/index.jsp";
}
}
(2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
@RequestMapping("/springMvc")
@Controller
public class handler {
//测试重定向
@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "redirect:/index.jsp";
}
}
Spring MVC和AJAX可以相互调用以实现前后端的数据交互。下面是一种常见的方式:
1. 前端使用AJAX发送HTTP请求到Spring MVC的控制器。
2. Spring MVC控制器接收到请求后,处理请求并返回数据。
3. 前端通过AJAX接收到Spring MVC控制器返回的数据。
4. 前端根据接收到的数据进行相应的处理,如更新页面内容或执行其他操作。
以下是一个简单的示例:
前端代码(使用jQuery的AJAX)
$.ajax({
url: "/getData", // Spring MVC控制器的请求路径
method: "GET", // 请求方法,可以是GET、POST等
dataType: "json", // 响应数据的类型,这里指定为JSON
success: function(response) {
// 请求成功时的回调函数
// response为Spring MVC控制器返回的数据
// 在这里可以对数据进行处理,如更新页面内容
},
error: function(xhr, status, error) {
// 请求失败时的回调函数
// 可以在这里处理错误情况
}
});
Spring MVC控制器代码
@Controller
public class MyController {
@GetMapping("/getData")
@ResponseBody // 将返回值直接写入响应体中
public Map getData() {
// 处理请求并返回数据
Map data = new HashMap<>();
data.put("message", "Hello, world!"); // 示例数据
return data;
}
}
在上述示例中,前端通过AJAX发送GET请求到`/getData`路径,Spring MVC控制器的`getData()`方法接收到请求并返回一个包含示例数据的Map。前端通过AJAX的`success`回调函数接收到数据,并可以根据需要进行处理。
需要注意的是,控制器方法上使用`@ResponseBody`注解将返回值直接写入响应体中,以便前端能够接收到返回的数据。
要解决POST请求中文乱码问题,可以按照以下步骤进行处理:
1. 在Spring MVC的配置文件(如`application.properties`或`application.yml`)中添加以下配置:
properties
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
这样配置后,Spring MVC会将请求和响应的字符编码都设置为UTF-8,确保正确处理中文字符。
2. 在控制器方法中,使用`@RequestMapping`注解指定请求的`produces`属性为`"application/json;charset=UTF-8"`,确保响应的Content-Type为UTF-8编码的JSON格式。
java
@PostMapping(value = "/postData", produces = "application/json;charset=UTF-8")
@ResponseBody
public Map postData(@RequestBody Map data) {
// 处理请求并返回数据
// ...
}
这样配置后,Spring MVC会将响应的Content-Type设置为UTF-8编码的JSON格式,确保正确返回中文字符。
对于GET请求,由于参数通常是通过URL传递的,可以采用以下方式处理中文乱码问题:
1. 在Spring MVC的配置文件中添加以下配置:
properties
server.tomcat.uri-encoding=UTF-8
这样配置后,Tomcat服务器会将请求的URL编码设置为UTF-8,确保正确处理中文字符。
2. 在控制器方法中,对接收到的参数进行手动解码:
java
@GetMapping("/getData")
@ResponseBody
public Map getData(@RequestParam("param") String param) {
try {
param = URLDecoder.decode(param, "UTF-8");
} catch (UnsupportedEncodingException e) {
// 处理解码异常
}
// 处理请求并返回数据
// ...
}
这样配置后,Spring MVC会将接收到的参数按照UTF-8编码进行解码,确保正确处理中文字符。
通过以上配置和处理,可以解决POST请求和GET请求中文乱码的问题,确保正确处理中文字符。
POST请求中文乱码的原因是因为在HTTP请求中,POST请求的请求体(Body)中的数据默认使用的是ISO-8859-1编码,而不是UTF-8编码。因此,如果请求体中包含中文字符,会导致乱码问题。
GET请求中文乱码的原因是因为在URL中传递参数时,浏览器默认使用的是URL编码(URL encoding),而不是UTF-8编码。URL编码会将中文字符转换为特殊的编码形式,例如"%E4%BD%A0%E5%A5%BD"代表"你好"。如果服务器没有正确解码这些编码,就会导致中文乱码问题。
为了解决这些问题,需要进行相应的字符编码设置和解码操作。在Spring MVC中,可以通过配置和代码来指定字符编码,确保正确处理中文字符,从而解决乱码问题。
使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:
@Controller
public class GlobalController {
/**
* 局部异常
* @return
*/
@ExceptionHandler({MyException.class})
public String exception(MyException e) {
System.out.println(e.getMessage());
e.printStackTrace();
return "exception";
}
@RequestMapping("test")
public void test() {
throw new MyException("出错了!");
}
}
骚戴理解:这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。简单来说就是局部异常处理器就是写在某个控制器里的一个方法,也就是这个控制器出现的任何异常都会执行这个局部异常处理器,但是其他控制器出现异常不会执行这个局部异常处理器
Spring MVC 通过 HandlerExceptionResolver 处理程序异常,包括处理器异常、数据绑定异常以及控制器执行时发生的异常。HandlerExceptionResolver 仅有一个接口方法,源码如下。
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest var1,
HttpServletResponse var2,
Object var3,
Exception var4);
}
发生异常时,Spring MVC 会调用 resolveException() 方法,并转到 ModelAndView 对应的视图中,返回一个异常报告页面反馈给用户。
创建一个 HandlerExceptionResolver 接口的实现类 MyExceptionHandler,重写resolveException方法,代码如下。
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@Component
public class MyExceptionHandler implements HandlerExceptionResolver {
//定义一个全局异常处理器
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o,
Exception e) {
Map model = new HashMap();
model.put("errorMessage", "程序运行出错");
//根据不同错误转向不同页面(统一处理),即异常与View的对应关系
if (e instanceof ArithmeticException) {
return new ModelAndView("error", model);
}
return new ModelAndView("other_error", model);
}
}
上文说到 @ ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。请确保此ExceptionAspect类能被扫描到并装载进 Spring 容器中。
// 全局的异常处理器类
@ControllerAdvice
public class ExceptionAspect {
//定义异常类型
@ExceptionHandler(Exception.class)
public String exception(Exception e) {
System.out.println("全局异常处理方法..." + e.getMessage());
return "error";
}
}
也就是定义一个全局处理器,所有控制器的异常都交给这处理器来处理
1、可以在@RequestMapping注解里面加上method=RequestMethod.GET。
@RequestMapping(value="/toLogin",method = RequestMethod.GET) public ModelAndView toLogin(){}
2、可以使用@GetMapping注解。
@GetMapping(value="/toLogin") public ModelAndView toLogin(){}
将HttpServletRequest作为Spring MVC 的方法参数传入。然后通过request间接的获取到session。
public void getSessionAction(HttpServletRequest request){ HttpSession session = request.getSession(); }
直接在控制器方法的形参里面声明这个参数就可以,但名字必须和传过来的参数名称一样,否则参数映射失败。
下面方法形参中的userId,就会接收从前端传来参数名称为userId的值。
@RequestMapping("/deleteUser") public void deleteUser(Long userId){ //删除用户操作... }
直接在控制器方法的形参里面声明这个参数就可以,Springmvc就会自动会请求参数赋值到这个对象的属性中。
下面方法形参中的user用来接收从前端传来的多个参数,参数名称需要和User实体类属性名称一致。
@RequestMapping("/saveUser")
public void saveUser(User user){
//保存用户操作...
}
@Data
public class User {
private Long userId;
private String username;
private String password;
//...
}
骚戴理解:一般常用于前端表单的提交,后端把前端的表单提交的参数封装成实体类对象作为形参来接受前端传来的数据,这里会自动把表单里的数据一一对应的注入到这个实体类中去,实现原理就是调用了这个实体类的构造方法来进行初始化,也就是自动注入
(1)使用model对象往前台传递数据 attribute
model.addAtrribute()
(2)在jsp中接收从后台传递过来的参数
(1)使用HttpServletRequest对象往前台传递数据
HttpServletRequest.setAtrribute()
(2)jsp中接收,同上!!!
把Model改成Map即可。
在控制器头部使用@SessionAttributes("user")注解,里面包含的字符串就是要放入session里面的key。
1、实体类
public class User {
private int id; //递增主键
private String username; //用户账号
private String password; //用户密码
//省略set和get方法
}
2、控制器头部
@SessionAttributes("user")
@Controller
@RequestMapping("/login")
public class LoginController {
//省略代码
}
在控制器头部使用@SessionAttributes("user")注解,里面包含的字符串就是要放入session里面的key。
3、控制器方法
@RequestMapping(method=RequestMethod.POST)
public String login(ModelMap modelMap,String username)
{
User user=userService.getUser(username);
modelMap.addAttribute("user", user);
return "index";
}
4、在jsp页面获取session中的值
${ sessionScope.user.id }
骚戴理解:@SessionAttributes(“user”)必须和modelMap.addAttribute(“user”, user)以及${ sessionScope.user.id }中"user"相同。id是User实体类的属性。
(1)实现自定义的拦截器
package net.biancheng.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle方法在控制器的处理请求方法调用之前执行");
return false;
}
@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方法在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行");
}
}
HandlerInterceptor接口是Spring MVC中用于定义拦截器的接口,它包含了三个方法,分别是preHandle、postHandle和afterCompletion。下面对这三个方法进行详细讲解:
1. preHandle方法:
- 方法签名:`boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception`
- 功能:在请求处理之前进行预处理。
- 返回值:返回一个布尔值,表示是否继续执行后续的请求处理。如果返回true,则继续执行后续的拦截器和请求处理器;如果返回false,则中断请求处理流程,不再执行后续的拦截器和请求处理器。
- 应用场景:preHandle方法常用于权限验证、参数校验、请求限流等操作。可以在该方法中进行必要的逻辑判断和处理,例如检查用户是否登录、校验请求参数的合法性等。
2. postHandle方法:
- 方法签名:`void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception`
- 功能:在请求处理之后进行后,视图解析之前执行。
- 参数:
- request:当前请求的HttpServletRequest对象。
- response:当前请求的HttpServletResponse对象。
- handler:当前请求的处理器(即Controller)。
- modelAndView:当前请求的处理结果,可以对其进行修改。
- 应用场景:postHandle方法常用于对请求处理结果进行修改或者添加额外的处理逻辑。可以在该方法中对返回的ModelAndView进行修改,例如添加一些公共的数据、修改视图名称等。
3. afterCompletion方法:
- 方法签名:`void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception`
- 功能:在请求完成之后进行清理资源的操作。
- 参数:
- request:当前请求的HttpServletRequest对象。
- response:当前请求的HttpServletResponse对象。
- handler:当前请求的处理器(即Controller)。
- ex:当前请求的异常对象,如果没有异常则为null。
- 应用场景:afterCompletion方法常用于进行一些清理操作,例如释放资源、记录日志等。可以在该方法中进行一些清理工作,确保请求处理完成后的资源释放和日志记录。
通过实现HandlerInterceptor接口并重写这三个方法,可以自定义拦截器的处理逻辑,实现对请求的预处理、后处理和清理操作。需要注意的是,拦截器的执行顺序由配置顺序决定,可以通过配置文件中的拦截器顺序来控制拦截器的执行顺序。
(2)在Spring的配置文件中添加如下配置
骚戴理解:
拦截器在Spring MVC中常见的应用场景:
1. 权限验证:拦截器可以用于验证用户的权限,例如检查用户是否登录、是否有权限访问某个资源等。
2. 日志记录:拦截器可以用于记录请求的日志信息,包括请求的URL、参数、处理时间等,方便后续的分析和排查问题。
3. 参数校验:拦截器可以用于对请求参数进行校验,确保参数的合法性和完整性,避免错误的数据进入业务处理流程。
4. 缓存管理:拦截器可以用于管理缓存,例如在请求处理之前检查缓存中是否存在需要的数据,如果存在则直接返回缓存数据,减少数据库访问。
5. 异常处理:拦截器可以用于捕获并处理请求处理过程中的异常,例如记录异常信息、返回统一的错误页面等。
6. 请求重定向:拦截器可以用于在请求处理之前进行重定向操作,例如根据用户的请求路径或者参数进行重定向到不同的页面。
7. 请求限流:拦截器可以用于限制用户的请求频率,防止恶意请求或者过多的请求对系统造成压力。
这些只是一些常见的应用场景,实际上拦截器可以根据业务需求进行自定义的处理逻辑。在使用拦截器时,需要根据具体的业务需求和系统架构进行合理的设计和配置。
WebApplicationContext是Spring框架中的一个接口,用于在Web应用程序中管理和配置Bean的上下文环境。
WebApplicationContext的特点和作用如下:
1. 生命周期:WebApplicationContext的生命周期与Web应用程序的生命周期相对应。它在Web应用程序启动时创建,并在Web应用程序关闭时销毁。这样可以确保在整个Web应用程序的生命周期内,容器中的Bean都可以正确地被管理和使用。
2. 层次结构:WebApplicationContext支持层次结构,可以通过父子关系连接多个WebApplicationContext。这样可以将一些公共的配置和资源定义在父上下文中,子上下文可以继承和覆盖父上下文中的配置。这种层次结构的特性可以方便地进行模块化开发和配置的管理。
3. Web特定的功能:WebApplicationContext提供了一些与Web相关的特定功能。例如,它可以通过ServletContext对象获取Web应用程序的上下文路径、获取请求和响应对象等。此外,WebApplicationContext还可以与Spring MVC等Web框架无缝集成,提供更强大的功能和灵活性。
4. 配置和管理Bean:WebApplicationContext负责加载和管理Web应用程序中的Bean。它可以通过XML配置文件、Java注解或者Java代码来定义和配置Bean。在WebApplicationContext中,可以使用Spring的IoC容器和AOP功能,实现依赖注入、面向切面编程等高级特性。
总的来说,WebApplicationContext是Spring框架中专门用于Web应用程序的上下文环境。它提供了生命周期管理、层次结构、Web特定功能以及Bean的配置和管理等特性,使得在Web应用程序中可以方便地使用和管理Spring的各种功能和组件。
Restful风格就是一种简洁、可读性强、易于理解和扩展的API设计方式。它使用URL来访问和操作资源,使用HTTP方法来表示不同的操作,使用HTTP状态码来表示请求结果,强调无状态性,使用JSON或XML等格式传输数据。通过遵循Restful风格,我们可以设计出更好的应用程序接口,提供更好的用户体验和系统性能。
Restful风格是一种很简洁的架构风格,它基于HTTP协议和Web标准,将应用程序的功能和数据抽象为一组资源,每个资源都有唯一的标识符(URI)。使用统一的HTTP方法(GET、POST、PUT、DELETE等)对资源进行操作,通过不同的HTTP方法和URI对资源进行增删改查操作。每个请求都包含了足够的信息,服务器不需要维护客户端的状态(无状态)。客户端的状态可以通过请求中的参数、标头或者资源的URI来传递。
Restful风格的好处:Restful风格的设计使得应用程序具有良好的可伸缩性、可重用性和松耦合性。它使得不同的客户端(例如Web浏览器、移动应用程序等)能够与后端服务进行交互,而不需要了解具体的实现细节。同时,Restful风格也符合Web的基本原则和标准,使得应用程序更易于开发、测试和维护。在实际应用中,可以使用Restful风格来设计和构建Web API,提供给客户端进行数据交互。通过合理地设计资源和使用HTTP方法,可以实现简洁、可扩展和易于理解的API接口。
骚戴理解:当我们使用互联网上的应用程序时,我们经常会通过URL访问和操作资源,例如查看新闻、发布博客、购买商品等。而Restful风格就是一种设计这些应用程序的API的方式。
想象一下,当我们浏览网页时,我们可以通过在浏览器中输入网址来访问不同的页面。同样,Restful风格的API也使用URL来访问和操作资源。
首先,我们将不同的资源抽象为一个个的实体,比如一篇文章、一张图片或者一个用户。每个资源都有一个唯一的URL来标识它。例如,一篇文章可以有一个URL是`/articles/123`,其中的123是这篇文章的唯一标识。
接下来,我们使用HTTP协议中的不同方法来表示对资源的不同操作。比如,当我们想要获取一篇文章时,我们可以使用GET方法,发送一个请求到`/articles/123`这个URL。而当我们想要创建一篇新的文章时,我们可以使用POST方法,将文章的内容发送到`/articles`这个URL。
此外,Restful风格还使用HTTP状态码来表示请求的处理结果。比如,当我们成功获取了一篇文章时,服务器会返回状态码200,表示成功。而如果请求的URL不存在,服务器会返回状态码404,表示资源不存在。
Restful风格还强调无状态性,这意味着服务器不会保存客户端的状态。每个请求都应该包含足够的信息来完成请求的处理。这样可以提高系统的可靠性和可扩展性。
最后,Restful风格通常使用JSON或XML等格式来传输数据。这些格式具有良好的可读性和可扩展性,可以方便地在不同的平台和系统之间进行数据交换。
资源:Restful架构将系统中的各种实体(资源)抽象为资源,并为每个资源分配一个唯一的URL,通过URL来访问和操作资源。资源可以是实体对象、集合、服务等。
统一的URL:Restful API中的URL应该是有意义的、可读性强的,并且应该使用名词来表示资源。URL的设计应该遵循一定的规范,例如使用复数形式表示集合资源,使用ID表示单个资源等。
HTTP方法:Restful API使用HTTP协议的不同方法来表示对资源的不同操作。常用的HTTP方法包括GET(获取资源)、POST(创建资源)、PUT(更新资源)、DELETE(删除资源)等。
状态码:Restful API使用HTTP状态码来表示请求的处理结果。常见的状态码包括200(成功)、201(创建成功)、400(请求错误)、404(资源不存在)、500(服务器内部错误)等。
无状态性:Restful架构是无状态的,每个请求都应该包含足够的信息来完成请求的处理,服务器不应该保存客户端的状态。这样可以提高系统的可伸缩性和可靠性。
数据传输格式:Restful API通常使用JSON或XML等格式来传输数据。这些格式具有良好的可读性和可扩展性,可以方便地在不同的平台和系统之间进行数据交换。
事实上,Spring 4.3 之后,为了更好的支持 RESTful 风格,增加了几个注解:@PutMapping、@GetMapping、@DeleteMapping、@PostMapping,从名字也能大概的看出,其实也就是将 method 属性的值与 @RequestMapping 进行了绑定而已
由于浏览器只支持POST和GET方法,因此需要使用_method隐藏字段通知Spring这是一个PUT/DELETE请求。
为此,Spring3.0增加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求,该过滤器是HiddenHttpMethodFilter。
因此,我们需要在web.xml文件中配置此过滤器。
hiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter
hiddenHttpMethodFilter
DispatcherServlet
/**
* 提交方式GET
* 通过学生编号stuNo获得学生信息
*/
@RequestMapping(value="/stuManager/{stuNo}", method=RequestMethod.GET)
public String getStuInfo(@PathVariable("stuNo") String stuNo, Map map){
map.put("stu", us.getStuInfo(stuNo));
//实现Service层方法获得学生信息,并添加进map返回前台
return "queStu";
}
/**
* 提交方式POST
* 添加学生信息
*/
@RequestMapping(value="/stuManager", method=RequestMethod.POST)
public String addStu(Student stu, Map map){
us.addStu(stu);
//实现Service层方法添加学生信息
map.put("msg", "学生信息添加成功");
return "addStu";
}
/**
* 提交方式PUT
* 修改学生信息
*/
@RequestMapping(value="/stuManager", method=RequestMethod.PUT)
public String updateStu(Student stu){
us.updateStu(stu);
//实现Service层方法更新学生信息
return "redirect:/stuList";
}
/**
* 提交方式DELETE
* 通过学生编号stuNo删除学生信息
*/
@RequestMapping(value="/stuManager/{stuNo}", method=RequestMethod.DELETE)
public String delStu(@PathVariable("stuNo") String stuNo){
us.delStu(stuNo);
//实现Service层方法删除学生信息
return "redirect:/stuList";
}
骚戴理解:前端代码其实就是在表单里设置表单提交的方法为post,然后在里面加一个隐藏标签就可,后端代码可以在@RequestMapping中指定对应的方法为put或者delete或者用@PutMapping、@GetMapping、@DeleteMapping、@PostMapping注解
例如@RequestMapping(value="/stuManager", method=RequestMethod.PUT/DELETE)
重定向(Redirect)和请求转发(Forward)是两种不同的页面跳转方式,它们之间有以下区别:
1. 执行位置:
- 重定向:在浏览器端执行,即客户端发起新的请求。
- 请求转发:在服务器端执行,即服务器内部进行页面跳转。
2. 请求对象和响应对象:
- 重定向:生成一个新的请求对象和响应对象,浏览器端会发送两个独立的请求。
- 请求转发:使用同一个请求对象和响应对象,服务器端进行内部的页面跳转。
3. URL变化:
- 重定向:浏览器地址栏会显示新的URL,即地址栏会改变。
- 请求转发:浏览器地址栏不会改变,仍然显示原始的URL。
4. 跳转范围:
- 重定向:可以跳转到不同的服务器、不同的Web应用程序,甚至是外部网站。
- 请求转发:只能在同一个服务器内部进行页面跳转。
5. 数据共享:
- 重定向:不能直接共享数据,可以通过URL参数、Session等方式传递数据。
- 请求转发:可以直接共享数据,因为是在同一个请求对象和响应对象内部进行跳转。
6. 用户感知:
- 重定向:用户会感知到页面的变化,浏览器会显示新的页面。
- 请求转发:用户无法感知到页面的变化,浏览器仍然显示原始的页面。
请求转发是一种在服务器内部的资源跳转方式,简单来说,当客户浏览器发送http请求到web服务器中,web服务器接受请求后调用内部servlet方法完成请求处理和转发资源给同一个web容器下的另一资源做处理,最后将目标资源response给客户
比如图中web容器(Tomcat)有两个资源(A和B),若浏览器请求资源A的时候,资源A处理了一部分,然后跳转到资源B,让资源B接着处理,资源B处理完成后做出响应到客户端。资源A跳转到资源B的这个过程就叫转发。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求转发器对象,调用forward()方法,请求转发
RequestDispatcher requestDispatcher = request.getRequestDispatcher("跳转资源的路径").forward(requset,response);
}
1. 请求转发资源间共享数据
图中资源A处理了一部分数据后把其他数据转交给资源B处理,所以在这过程中资源之间数据是共享的。
void setAttribute(String name,Object o)//存储数据到request域中
Object getAttribute(String name)//根据key,获取值
void removeAttribute(String name)//根据key,删除该键值对
2. 浏览器地址栏路径不发生变化,只能转发到当前服务器的内部资源,浏览器只做了一次请求
在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。
重定向(Redirect)是一种资源跳转的方式,一般用来解决登录进入主页、跨域访问、系统维护等等都使用重定向技术,比如当系统进行维护时,用户若发起请求,系统将会告诉浏览器重定向访问指定的url。
简单来说,当浏览器发起请求给资源A时,资源A发现浏览器发起的请求自身处理不了,但是知道资源B可以处理,这时候资源A就会告诉浏览器说这次请求处理不了,请找资源B处理并且告诉资源B的访问路径,浏览器会自动去请求资源B。
客户浏览器发送http请求后,web服务器中资源A接受请求后无法处理,资源A将会发送302状态码响应及对应新的location(资源B)给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//旧方法
//response.setStatus(302);
//response.setHeader("location","资源B的路径");
//其中资源B的路径需要添加虚拟目录
response.sendRedirect("资源B的路径");
}
1. 浏览器地址栏路径发生变化
2. 可以重定向到任意位置的资源(服务器内部、外部均可)
3. 浏览器发起两次请求,不能在多个资源使用request共享资源
请求转发(Forward)和重定向(Redirect)在不同的场景下有不同的使用场景。
请求转发适用于以下场景:
1. 内部资源跳转:当需要将请求转发给同一个Web容器下的另一个资源进行处理时,可以使用请求转发。例如,将请求从一个Servlet转发给另一个Servlet或JSP进行进一步处理。
2. 共享数据:请求转发可以在同一个请求对象和响应对象的上下文中进行,因此可以方便地共享数据。例如,通过请求转发将用户登录信息传递给下一个资源进行处理。
3. 避免URL变化:由于请求转发是在服务器内部进行的资源跳转,浏览器地址栏不会改变,因此可以避免URL的变化,对用户来说更加友好。
重定向适用于以下场景:
1. 资源跳转到不同的服务器或Web应用程序:当需要将请求跳转到不同的服务器或Web应用程序时,可以使用重定向。例如,将请求从一个Web应用程序重定向到另一个Web应用程序。
2. 外部网站跳转:重定向可以将请求跳转到外部的网站,实现不同域名之间的页面跳转。
3. 防止表单重复提交:在处理表单提交时,可以使用重定向来避免用户刷新页面导致表单的重复提交。
骚戴理解:重定向可以防止表单重复提交的原因是因为重定向会将浏览器的地址栏URL改变,导致浏览器发起一个新的请求。当服务器处理完表单后,将浏览器重定向到另一个URL,浏览器会发起一个新的请求,与之前的请求是完全独立的。这样,用户无法通过刷新页面或回退按钮重新发送相同的请求,从而避免了表单的重复提交。通过重定向,可以将用户从表单提交的页面跳转到一个新的页面,这个新的页面可以是一个成功提交的提示页面或其他需要展示给用户的页面。这样,用户在新页面上进行操作时,再进行刷新或回退等操作,不会再重复提交之前的表单数据。
需要根据具体的需求和场景来选择使用请求转发还是重定向。一般来说,如果需要在服务器内部进行资源的复用和共享数据,或者需要避免URL的变化,可以使用请求转发。如果需要跳转到不同的服务器或Web应用程序,或者需要进行外部网站跳转,或者需要防止表单重复提交,可以使用重定向。