SpringMVC


SpringMVC

SpringMVC

SpringMVC一种开发模式,它是模型视图控制器的简称.所有的web应用都是基于MVC开发.

M:模型层,包含实体类bean,业务逻辑层service,数据访问层mapper V:视图层,html,javaScript,vue等都是视图层,用来显现数据 C:控制器,它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件

1
1

运行流程图

2
2

为配置

3
3

SpringMVC 常用主要组件

1.ispatcherServlet:前端控制器

2.Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理

3.HandlerMapping :请求映射到处理器,找谁来处理,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器对象)

4.View Resolver : 视图解析器,找谁来处理返回的页面。把逻辑视图解析为具体的View,进行这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为JSP视图

  1. LocalResolver:本地化、国际化

  2. MultipartResolver:文件上传解析器

  3. HandlerExceptionResolver:异常处理器

永远的HelloWorld

1.新建Web工程,加入 jar 包

spring-aop-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
commons-logging-1.1.3.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
  1. 在 web.xml 中配置 DispatcherServlet

    !-- 配置SpringMVC核心控制器: -->
    <servlet>
    <servlet-name>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置DispatcherServlet的初始化參數:设置文件的路径和文件名称 -->
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    解释配置文件的名称定义规则:实际上也可以不通过 contextConfigLocation 来配置 SpringMVC 的配置文件, 而使用默认的.默认的配置文件为: /WEB-INF/<servlet-name>-servlet.xml
    

    加入 Spring MVC 的配置文件:springmvc.xml

    增加名称空间

    4
    4

    增加配置

    <!-- 设置扫描组件的包: -->`
    <context:component-scan base-package="com.atguigu.springmvc"/>
        
    <!-- 配置映射解析器:如何将控制器返回的结果字符串,转换为一个物理的视图文件-->
    <bean id="internalResourceViewResolver" 
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
    </bean>
    

4.需要创建一个入口页面,index.jsp

<a href="${pageContext.request.contextPath }/helloworld">Hello World</a>
  1. 编写处理请求的处理器,并标识为处理器

    package com.atg.springmvc.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    @Controller  //声明Bean对象,为一个控制器组件
    public class HelloWorldController { 
    /**
     * 映射请求的名称:用于客户端请求;类似Struts2中action映射配置的action名称
     * 1. 使用 @RequestMapping 注解来映射请求的 URL
     * 2. 返回值会通过视图解析器解析为实际的物理视图, 对于InternalResourceViewResolver视图解析器, 
     * 会做如下的解析:
     * 通过 prefix + returnVal + suffix 这样的方式得到实际的物理视图, 然后做转发操作.
     * /WEB-INF/views/success.jsp
     */
    @RequestMapping(value="/helloworld",method=RequestMethod.GET)
    public String helloworld(){
         System.out.println("hello,world");
         return "success"; //结果如何跳转呢?需要配置映射解析器
    }    }   
    

6.1编写视图/WEB-INF/views/success.jsp

<h4>Sucess Page</h4>

HelloWorld请求流程图解

5
5

一般请求的映射路径名称和处理请求的方法名称最好一致(实质上方法名称任意)

RequestMapping(value="/helloworld",method=RequestMethod.GET)
public String helloworld(){
//public String abc123(){
System.out.println("hello,world");
return "success";
}

处理请求方式

public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}

@RequestMapping应用

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {}

流程

6
6

基本步骤:

① 客户端请求提交到DispatcherServlet

② 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller

③ DispatcherServlet将请求提交到Controller(也称为Handler)

④ Controller调用业务逻辑处理后,返回ModelAndView

⑤ DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图

⑥ 视图负责将结果显示到客户端

RequestMapping_请求参数&请求头

//可以使用 params 和 headers 来更加精确的映射请求. params 和 headers 支持简单的表达式.
@RequestMapping(value="/testParamsAndHeaders",
params= {"username","age!=10"}, headers = { "Accept-Language=en-US,zh;q=0.8" })
public String testParamsAndHeaders(){
System.out.println("testParamsAndHeaders...");
return "success";
}

RequestMapping支持Ant 路径风格

/user/*/createUser
匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL
/user/**/createUser
匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL
/user/createUser??
匹配 /user/createUseraa、/user/createUserbb 等 URL

@PathVariable

//@PathVariable 注解可以将请求URL路径中的请求参数,传递到处理请求方法的入参中
浏览器的请求:  testPathVariable/1001
@RequestMapping(value="/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id){
System.out.println("testPathVariable...id="+id);
return "success";
}

HiddenHttpMethodFilter过滤器

7
7
8
8

配置HiddenHttpMethodFilter过滤器

<!-- 支持REST风格的过滤器:可以将POST请求转换为PUT或DELETE请求 -->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

实例put

@RequestMapping(value="/testRESTPut/{id}",method=RequestMethod.PUT)
public String testRESTPut(@PathVariable("id") Integer id){
System.out.println("testRESTPut id="+id);
return "success";
}

增加控制器方法

/**
 * @RequestParam 注解用于映射请求参数
 *         value 用于映射请求参数名称
 *         required 用于设置请求参数是否必须的
 *         defaultValue 设置默认值,当没有传递参数时使用该值
 */
@RequestMapping(value="/testRequestParam")
public String testRequestParam(
@RequestParam(value="username") String username,
@RequestParam(value="age",required=false,defaultValue="0") int age){
System.out.println("testRequestParam - username="+username +",age="+age);
return "success";
}
@RequestMapping(value="/testRequestHeader")
public String testRequestHeader(@RequestHeader(value="Accept-Language") String al){
System.out.println("testRequestHeader - Accept-Language:"+al);
return "success
@CookieValue: 映射一个 Cookie. 属性同 @RequestParam
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId) {
System.out.println("testCookieValue: sessionId: " + sessionId);
return "success";
}
 * Spring MVC 会按请求参数名和 POJO 属性名进行自动匹配, 自动为该对象填充属性值。
 * 支持级联属性
 *                 如:dept.deptId、dept.address.tel 等
 */
@RequestMapping("/testPOJO")
public String testPojo(User user) {
System.out.println("testPojo: " + user);
return "success";
<!-- 测试 POJO 对象传参,支持级联属性 -->
<form action=" testPOJO" method="POST">
username: <input type="text" name="username"/><br>
password: <input type="password" name="password"/><br>
email: <input type="text" name="email"/><br>
age: <input type="text" name="age"/><br>
city: <input type="text" name="address.city"/><br>
province: <input type="text" name="address.province"/>
<input type="submit" value="Submit"/>
</form>
public class Address {
 
private String province;
private String city; 
//get/set
  
}

public class User {
private Integer id ;
private String username;
private String password; 
private String email;
private int age; 
private Address address; 
//get/set 
}
	<!-- 配置字符集 -->
	<filter>
		<filter-name>encodingFilter</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>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

SpringMVC 输出模型数据

1.** ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据

2.Map 或 Model: 入参为 org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中

ModelAndView

1.两个重要的成员变量:private Object view视图信息, private ModelMap model 模型数据

2.添加模型数据:

MoelAndView addObject(String attributeName, Object attributeValue) 设置模型数据

ModelAndView addAllObject(Map<String, ?> modelMap)

3.设置视图:

void setView(View view) 设置视图对象

void setViewName(String viewName) 设置视图名字

4.获取模型数据

​ protected Map<String, Object> getModelInternal() 获取模型数据

​ public ModelMap getModelMap()

​ public Map<String, Object> getModel()

Map

1.Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存储模型数据具体使用步骤

2.Spring MVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。

如果方法的入参为 Map 或 Model 类型**,Spring MVC 会将隐含模型的引用传递给这些入参。

4.在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据

//目标方法的返回类型也可以是一个Map类型参数(也可以是Model,或ModelMap类型)
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){ 
System.out.println(map.getClass().getName());
//org.springframework.validation.support.BindingAwareModelMap
map.put("names", Arrays.asList("Tom","Jerry","Kite"));
return "success";
}
//目标方法的返回类型也可以是一个Map类型参数(也可以是Model,或ModelMap类型)
@RequestMapping("/testMap2")
public String testMap2(Map<String,Object> map,Model model,ModelMap modelMap){
System.out.println(map.getClass().getName());
map.put("names", Arrays.asList("Tom","Jerry","Kite"));
model.addAttribute("model", "org.springframework.ui.Model");
modelMap.put("modelMap", "org.springframework.ui.ModelMap");
 
System.out.println(map == model);
System.out.println(map == modelMap);
System.out.println(model == modelMap);
 
System.out.println(map.getClass().getName());
System.out.println(model.getClass().getName());
System.out.println(modelMap.getClass().getName());
 
/*
true
true
true
org.springframework.validation.support.BindingAwareModelMap
org.springframework.validation.support.BindingAwareModelMap
org.springframework.validation.support.BindingAwareModelMap
    */ 
return "success";
}

Map, 便于框架移植。

9
9

视图和视图解析器

1.请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了逻辑名和模型对象的视图

2.Spring MVC 借助视图解析器ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图

3.对于最终究竟采取何种视图对象对模型数据进行渲染,处理器并不关心,处理器工作重点聚焦在生产模型数据的工作上,从而实现 MVC 的充分解耦

视图

1.视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。

2.为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口:

10
10

3.视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题

常用的视图实现类

11
11

常用的视图解析器

12
12

mvc:view-controller标签

<!-- 直接配置响应的页面:无需经过控制器来执行结果 -->
<mvc:view-controller path="/success" view-name="success"/>

重定向

@RequestMapping("/testRedirect")
public String testRedirect(){
System.out.println("testRedirect");
return "redirect:/index.jsp";
//return "forward:/index.jsp";
}
HttpMessageConverter<T>

1.HttpMessageConverter<T>,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息**

2.HttpMessageConverter<T>接口定义的方法:

1. Boolean canRead(Class<?> clazz,MediaType mediaType): 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json等)
2. Boolean canWrite(Class<?> clazz,MediaType mediaType):指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。
3. List<MediaType> getSupportMediaTypes():该转换器支持的媒体类型。
4. T read(Class<? extends T> clazz,**HttpInputMessage** inputMessage):将请求信息流转换为 T 类型的对象。

5.void write(T t,MediaType contnetType,**HttpOutputMessgae** outputMessage):将T类型的对象写到响应流         中,同时指定相应的媒体类型为 contentType。