- 将url映射到Java类或则Java类的方法
- 封装用户提交的数据
- 处理请求— 调用相关的业务处理—封装响应数据
- 将响应数据进行渲染 .jsp / html 等表示层数据
Spring的Web框架围绕DispatcherServlet设计,DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java5或者以上版本的用户可以采用基于注解的声明方式**
客户端请求处理流程
- 客户端向前端控制器发送请求。
- 前端控制器接收客户端请求信息。
- 前端控制器调用代理对象,把请求转发给用户自定义控制器处理。
- 用户自定义控制器处理请求,并把处理结果通过模型对象返回给前端控制器。
- 前端控制器把模型数据发给视图模块进行处理。
- 视图模块把结果返回给前端控制器
- 其那段控制器把最终的视图信息通过流返回给客户端。
DespatcherServlet
前端控制器DespacherServlet 中包含一个IoC容器Servlet WebApplicationContext ,这个IoC容器可能指向它的父容器———-Root WebApplicationContext
DespatcherServlet 继承自HttpServlet, 实现了javax.servlrt.Servlet接口。 所以本质上DespatcherServlet 也是一个Servlet
功能
- 基于JavaBean的配置机制
- 使用后HandlerMapping 的实现类,提前处理对控制器的请求路由。HandlerMapping 作为Bean对象由IoC容器统一管理
- 使用HandlerAdapter 处理请求,HandlerAdapter 也是作为Bean对象由IoC容器统一管理。
- 前端控制器异常由HandlerExceptionResolver 解析。可以映射异常到指定的错误业。
- 视图解析策略由配置的ViewResolver 类来处理。它可以把试图名字解析成视图对象。
- 如果用户没有提供视图对象或视图名字, 使用RequestToViewNameTranslator 配置,可以把请求转换到相应的视图对象。
- 前端控制器使用MultipartResolver 的实现类处理实体文件的上传。
- 国际化LocaleResolver
- 主题策略ThemeResolver
web.xml
- 使用注解开发时, web.xml几乎是固定格式
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--注册Servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--启动顺序, 数字越小,启动越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被SpringMVC拦截-->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-mvc.xml
- 这个配置文件也几乎是固定格式不需要什么修改
- 需要特别注意的是版本问题,否者会报2.4错误
将下面的第8行和第十行,spring-context spring-mvc 版本配置为与上面web.xml中web-app 相同
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!--自动扫描包, 让指定包下面的注解生效,由IoC容器统一管理-->
<context:component-scan base-package="code"/>
<!--过滤,让SpringMVC不处理静态资源(.css .js .html .mp3...)-->
<mvc:default-servlet-handler/>
<!--
支持MVC注解驱动
在Spring中使用@RequestMapping 注解来完成映射关系
想要使@RequestMapping注解生效,必须向上向下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationHandlerMapping 实例, 这两个实例分别在类处理级别和方法处理级别使用
:annotation-driven 自动完成上述两个实例的注入
-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
示例
- 在下面的这段代码中包含了SpringMVC的编码流程
- 首先@Contorller 确定为一个组件,在位置文件的扫描文件夹中
<context:component-scan base-package="code"/>
这里的code 就是要扫面组件的包。 - @RequestMapping(“/h1”) 代表了HTTP请求映射, 接收到 “/h1” 的请求之后会映射到设个方法上面
- Model 是一个视图对象
- 返回结果会被视图解析器处理,如上面配置文件里面的,返回结果会到前缀目录根据返回的String匹配相应的后缀文件,完成响应
@Controller
public class HelloBiz {
@RequestMapping("/h1")
public String sayHello(Model model){
model.addAttribute("name", "Hello");
return "hello";
//返回结果会被视图解析器处理
}
}
Controller控制器
- 控制器负责提供访问应用程序的行为, 通常通过接口定义或注解定义两种方法实现
- 控制器负责解析用户的请求并将其转换为一个模型
- 在SpringMVC中一个控制器类可以包含多个方法
- 在SpringMVC中,对于Controller的配置方式有很多种
Controller接口
Controller 是一个接口,在org.springframework.web.servlet.mvc 包下接口中只有一个方法。
public interface Controller {
@Nullable
ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}
—— 实现该接口的类获得控制器功能
——- 方法作用为:处理请求且返回一个模型与视图对象
public class Controller1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("name", "hello");
mv.setViewName("hello");
return mv;
}
}
<bean name="hello" class="code.Controller1"/>
如上,实现了Controller接口 在新建了ModelAndView 之后也可以返回一个视图
但是这种方法有一个缺点,,,,一个控制器只能写一个方法,如果要多个方法则需要定义多个Controller
@Controller 注解
由于Controller 接口的缺点 ,@Controller 可以很好的弥补这一不足之出
- @Controller 是一个组件同为组件的还有
@Component 组件
@Service service 层
@controller controller 层
@Repository dao 层
- Spring 可以使用扫描机制来找到应用程序中所有基于注解的控制器类, 为了Spring能找到你的控制器,需要在配置文件中声明组件扫描
<context:component-scan base-package="code"/>
- 注解实现
@Controller
//@Controller注解的类会自动添加到Spring的上下文中 这个类会被Spring接管
public class HelloBiz {
//映射访问路径
@RequestMapping("/h1")
public String sayHello(Model model){
//SpringMVC 会自动实例化一个Model对象用于视图中船只
model.addAttribute("name", "Hello");
//返回视图位置
return "hello";
}
}
- 被这个注解的类中的所有方法,如果返回值是String,并且有具体页面可以跳转,那么就会被 视图解析器解析
关于@Controller作用域
- 在没有使用它的属性信息,默认为单例模式,在控制器中注入其他单例对象不受影响
- @controller还包含了以下作用域
@Controller
@Scope("prototype") //原型作用域
@RequestScope //request作用域
@SessionScope //session 作用域
@ApplicationScope //application作用域
(作用域在Spring中有解释)
RestFul 风格
概念:Restful 就是一个资源定位及资源操作的风格,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
操作资源:
传统:`http://127.0.0.1/item?id=1&b=0`
RestFul 操作资源 : `http://127.0.0.1/item/1/0`
可以通过不同的请求方式来实现不同的效果(地址一样但功能不同)
@RequestMapping("/h1/{a}/{b}")
public String sayHello(@PathVariable int a, @PathVariable int b, Model model){
model.addAttribute("name", "Hello");
return "hello";
}
@PathVarible 注释可以让参数的值对应分割请求参数
优点:
1. 使路径变得更加简洁
2. 获得参数更加方便, 框架会自动转换类型
3. 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法。
(@PathVarible 注解, 这个注解适用于RESTFul 风格的Web 站点, 它通过URL中存放的变量传递参数。在使用的时候当变量名与参数名不一致的时候需要特别说明)
@RequestMapping
@RequestMapping 注解映射HTTP 的 URL
SpringMVC 的 @RequestMapping 注解能够处理HTTP 请求的方法, 比如GET , PUT, POST, DELETE, 以及PATCH。
所有地址栏请求默认都是HTTP GET
RequestMapping 有一个produces 属性, 他表示生产媒体的类型
params 属性表示只有HTTP 请求包含指定的参数值, 映射方法才会处理请求
handers 属性相同于params 而它可以携带很多的信息
@RequestMapping的value属性和path属性在Servlet环境下是等效的 代表的是映射URL
model 属性与HTTP方法相对应。可延伸出下面几种注解:
@GetMapping
@PostMappong
@PutMapping
@DeleteMapping
@PatchMapping
@GetMapping 是一个组合注解 其实他就是一个:
//使用method 属性可以指定请求的类型
@RequestMapping(Value="***", method=RequestMethod.GET);
类型不一致的话会报一个405 错误
上面的注解要生效必须在配置文件中增加
<mvc:annotation-driven/>
原因:
支持MVC注解驱动<br />
在Spring中使用@RequestMapping 注解来完成映射关系想要使@RequestMapping 注解生效,必须向上向下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationHandlerMapping 实例, 这两个实例分别在类处理级别和方法处理级别使用 <mvc:annotation-driven/>
自动完成上述两个实例的注入
ViewResolver视图解析器
在Spring MVC控制器中,所有的客户端请求处理方法(Action)必须解析出一个逻辑视图名称,无论是显式的(返回String,View或ModelAndView)还是隐式的(基于约定的,如视图名就是方法名)。视图解析器的作用是将逻辑视图转为物理视图,所有的视图解析器都必须实现ViewResolver接口。
Spring处理视图最重要的两个接口是ViewResolver和View。ViewResolver接口在视图名称和真正的视图之间提供映射关系; 而View接口则处理请求将真正的视图呈现给用户。
ModelAndView使用
- 设置ModelAndView 对象, 根据view的名称,和视图解析器跳转到指定的页面。
- 页面 : {视图解析器前缀} + viewName + {视图解析器后缀}
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
原生的HttpServlet 不通过视图解析器同样可以实现跳转如下
@RequestMapping("/h1")
public String sayHello(HttpServletRequest request, HttpServletResponse response){
request.setAttribute("name","Hello");
return "hello";
}
通过SpringMVC 来实现转发和从定向
- 无需视图解析器
@RequestMapping("/h1")
public String sayHello(Model model){
model.addAttribute("name", "name");
//转发 这里路径需要使用全限命名
return "/hello";
}
@RequestMapping("/h1")
public String sayHello(Model model){
model.addAttribute("name", "name");
//转发
return "forword:/hello";
}
以上两种通过 隐性的 “/” 和 显性的 “forword:” 实现转发
@RequestMapping("/h1")
public String sayHello(Model model){
model.addAttribute("name", "name");
//重定向
return "redirect:/hello";
}
通过redirect
实现重定向
在又视图解析其得情况下
- 在又试图解析情况下直接写路径名默认为转发
@RequestMapping("/h1")
public String sayHello(Model model){
model.addAttribute("name", "name");
return "hello";
}
重定向加上redirect 即可
@RequestMapping("/h1")
public String sayHello(Model model){
model.addAttribute("name", "name");
return "redirect:hello";
}
@RequestParam
@RequestParam 的作用是绑定HTTP 请求参数到控制器的方法参数
当HTTP 中的请求参数与控制器中的映射方法名不一致的时候,必须使用@RequestParam进行转换(下一条数据处理中有体现)
此外@RequestParam还可以设置默认值,示例中HTTP 请求中没有name 参数的时候就会将name 默认设置为“qzw”
//当请求中没有这个请求参数时使用默认值
public String sayHello(@RequestParam(name = "name", defaultValue = "qzw") String name, Model model) {
...
}
SpringMVC : 数据处理
处理提交数据
1. 提交的域名称和处理方法的参数名一致
url: [http://localhost:8080/hello?name=xxx](http://localhost:8080/hello?name=xxx)
处理方法:
@RequestMapping("/h1")
public String sayHello(String name, Model model){
//这里会自动对应到参数名name 直接取值赋值
}
- 提交的域名称和处理方法的参数名不一致
@RequestParam(“username”) 注解
url:http://localhost:8080/hello?username=xxx
@RequestMapping("/h1")
public String sayHello(@RequestParam("username") String name, Model model){
//上传参数为username 也会自动对应道String name 自动取值赋值
}
3. 提交的是一个对象
- 要求提交的表单域和对象的属性名一致,参数使用对象即可
public class User {
private String name;
private int age;
private int id;
}
@RequestMapping("/h1")
public String sayHello(User user, Model model){
}
- 如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null
处理返回的数据
- ModelAndView
- ModelMap
- Model
三种方式使用起来都差不多,主要区别如下:
1. Mdoel 只有寥寥几个方法只适合用于存储数据,简化了新手对于Model对象的操作和理解
2. ModelMap 继承了 LonkedMap, 除了实现了自身的一些方法, 同样继承了 LinkedMap 的方法和特性
3. ModelAndView 可以在存储数据的同时可以设置返回对象的点的逻辑视图, 进行控制和地底层的跳转
控制器方法的返回类型
ModelAndView
- 包含模型和视图两部分数据(还有两个数据类型model view 分别返回模型和视图)
String
- 解析为视图名字或者路径
void
- 空类型,可以使用ServletResponse直接写数据
Object
- 通过配置Object 最后都是返回的Json 格式响应回去
……
乱码过滤器
SpringMVC提供了过滤器, 直接在web.xml 中配置即可
<!--SpringMVC 的乱码过滤器 设置编码 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- **需要注意一下 “/” 和 “/“ 的区别
@RequestBody
@RequestBody 注解表明了方法参数与HTTP 请求体数据绑定
@RequestBody 主要用来接收 前端传递给后端的json字符串中的数据的(请求体中的数据的);GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。
在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
@RequestMapping("/h1")
public String sayHello(@RequestBody String Jstr) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Bean str = mapper.readValue(Jstr,Bean.class);
return "hello";
}
@ResponseBody
- 将返回信息直接写入响应体中
- 使用了该注解的方法不会走视图解析器, 会直接返回一个字符串对象
@RequestMapping("/h1")
@ResponseBody
public String sayHello(@RequestParam("username") String name, Model model){
model.addAttribute("name", "name");
return "hello";
}
会发送一个响应体会到前端, 响应体里面包含了 ”hello“ 字符串
- 在类上面使用@RestController 注解表示该类里面的所有方法都会走视图解析器, 都是返回一个字符串
@RestController
public class HelloBiz {
...
}
@RestController
- RestController 是一种简化了的写法, 他相当于控制器中所有@RequsetMapping 方法都使用了@ResponseBody 注解, 即理解为 @ResController = @RequsetMapping + @ResponseBody
- 在微服务开发中, 所有对外的服务都使用@RestController 注解
@ModelAttribute
更简洁, 可读性更强
- 表明这个方法主要用于添加一个或多个 model 属性 , 用ModelAttribute 注解的方法会在此控制器的所有@requestMapping 方法前执行 ,一个控制器允许多个ModelAttribute 存在
- 使用ModelAttribute 注解参数时,表明这个参数应该从model 中获取。 如果model 中没有该对象就新建一个对象加入到mdoel 当中, 如果找到了对应名称的对象,这个对象的属性值应当从请求参数中按名字匹配查找
@SesionAttributes and @SessionAttribute
- @SessionAttributes 注解用于在会话中存储model 中指定名称的属性, 用在类级别它可以同时存储多个对象。
@SessionAttributes(value = {"user", "shopcar"})
public class HelloBiz { ... }
//从Model 中提取user 属性和 shopcar 对象
- @SessionAttribute 注解用于方法参数, 获取已经存储的会话数据
public String test(@SessionAttribute String name){ ... }
//从会话中查找 name 对象, 若找不到会报错
- 不会自动创建对象
@RequestAttribute
- 使用@RequestAttribute 注解可以提取HttpServletRequest 的属性数据
Jackson
依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.0</version>
</dependency>
乱码
<!--配置 解决json 乱码问题 使用了Jackson 就需要添加此配置-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
对象 ——-> json
ObjectMapper mapper = new ObjectMapper();
Bean b = new Bean("qzw",3,6);
String str = mapper.writeValueAsString(b);
json ———-> 对象
ObjectMapper mapper = new ObjectMapper();
Bean str = mapper.readValue(Jstr,Bean.class);
- fastjson 与这个类似