美文网首页
什么是Spring MVC

什么是Spring MVC

作者: 虾米咬小米 | 来源:发表于2021-04-15 17:33 被阅读0次

1. SpringMVC概述

1.1. 什么是Spring MVC

SpringMVC是Spring框架内置的MVC的实现.
SpringMVC就是一个Spring内置的MVC框架.
MVC框架,它解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化、等等),而且使用简单,与Spring无缝集成。 
支持 RESTful风格的 URL 请求 。
采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。

1.2. SpringMVC的作用

MVC模式:(Model-View-Controller):为了解决页面代码和后台代码的分离.

2. SpringMVC底层实现

在没有使用SpringMVC之前我们都是使用的Servlet在做Web开发。
但是使用Servlet开发在接受请求数据参数,数据共享,页面跳转等操作相对比较复杂。

SpringMVC底层就是的Servlet,SpringMVC就是对Servlet进行更深层次的封装

2.1. 回顾MVC模式

回顾什么是mvc模式

   模型model(javabean),  视图view(jsp/img)   控制器Controller(Action/servlet)   C存在的目的.就是为了保证M和V的一致性
   当M发生改变时,C可以把M中的新内容更新到V中.

2.1.1. 原始MVC 模式

MVC模式最早开始是在CS 架构上面 20世纪70+年代

下面为原始的mvc模式.

目前web应用中,99%的项目都会使用mvc模式开发.

image

2.1.2. WEB开发的MVC

WEB开发从20世纪90+年代开始,也是使用MVC模式。在最原始的MVC上有一些改进
优秀的框架改变了这种模式,将model更广泛的使用,这样会比原始的mvc好多了.
像现在一些优秀的mvc的框架,如Struts2,springMVC
在客户端提交也使用了模型来请求参数
spring MVC 也实现的相关的功能
image

3. 入门案例 -xml 配置

3.1. 准备工作

创建动态Web项目

image image image

3.2. 步骤

3.3. 准备jar包

image

3.4. SpringMVC开发相关jar包

spring-web-4.3.3.RELEASE.jar         spring 对web项目的支持。
spring-webmvc-4.3.2RELEASE.jar   spring mvc核心包。
image

3.5. 编写Controller控制器(与以前servlet类似)

public class HelloController implements Controller  {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView mv = new ModelAndView();
        mv.addObject("username", "师姐");
        mv.setViewName("/WEB-INF/hello/hello.jsp");
        return mv;
    }
}

3.6. 在springmvc.xml配置 Controller

    <!--
        name : 给当前控制器取的一个名字,相当于Servlet中的资源名称,以便浏览器访问,必须以斜杠/开头
            建议使用 name属性,不要使用id,因为早期版本 id 不支持特殊字符 如 /斜杠
      -->
    <bean name="/hello" class="cn.zj.springmvc.HelloController"/>

3.7. 配置spring mvc核心(前端)控制器,并且初始化spring容器。 web.xml配置.

<!-- 配置前端控制器 :所有的请求都会经过此控制器,让后通过此控制器分发到各个控制器(总控)
        总控其实就是Servlet,SpringMVC底层就是使用Servlet编写的
     -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 读取SpringMVC的配置文件 -->
        <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>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

3.8. 启动项目

image

3.9. 访问项目

image

4. SpringMVC的全注解开发

4.1. Spring中IOC 注解

image

4.2. SpringMVC使用注解步骤

4.2.1. Spring mvc 采用注解方式(需要导入aop的包)

image

4.2.2. 通过注解方式注册控制器,配置需要扫描的根目录

<context:component-scan base-package="cn.zj.springmvc"/>

4.2.3. 支持所有mvc注解支持。支持json

<mvc:annotation-driven/>

4.2.4. 在核心类上添加@Controller 注解

4.2.5. 在方法上添加@RequestMapping("/hello")注解

4.3. 案例代码

@Controller
public class AnnotationController  {
    //@RequestMapping(value= {"/method1","/method2"})
    @RequestMapping("method1")
    public ModelAndView mehtod1() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("username", "乔峰");
        mv.setViewName("/WEB-INF/anno/index.jsp");
        return mv;
    }
}

5. SpringMVC执行流程和原理

SpringMVC流程:
01、用户发送出请求到前端控制器DispatcherServlet。
02、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
03、HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
04、DispatcherServlet调用HandlerAdapter(处理器适配器)。
05、HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
06、Controller执行完成返回ModelAndView对象。
07、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
08、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
09、ViewReslover解析后返回具体View(视图)。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
image

涉及组件分析:

1、前端控制器DispatcherServlet(不需要程序员开发),由框架提供,在web.xml中配置。
作用:接收请求,响应结果,相当于转发器,中央处理器。

2、处理器映射器HandlerMapping(不需要程序员开发),由框架提供。
作用:根据请求的url查找Handler(处理器/Controller),可以通过XML和注解方式来映射。

3、处理器适配器HandlerAdapter(不需要程序员开发),由框架提供。
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。

4、处理器Handler(也称之为Controller,需要工程师开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。
作用:接受用户请求信息,调用业务方法处理请求,也称之为后端控制器。

5、视图解析器ViewResolver(不需要程序员开发),由框架提供
作用:进行视图解析,把逻辑视图名解析成真正的物理视图。
SpringMVC框架支持多种View视图技术,包括:jstlView、freemarkerView、pdfView等。

6、视图View(需要工程师开发)
作用:把数据展现给用户的页面
View是一个接口,实现类支持不同的View技术(jsp、freemarker、pdf等)
具体组件的配置相关,请查阅 

spring-webmvc-4.3.2.RELEASE.jar 包
下面 
/org/springframework/web/servlet/DispatcherServlet.properties 的相关配置
HanderMapping 请求映射处理器
    作用:根据不同的请求选择最合适的处理器(自己编写的控制器),请求映射处理器可以配置多个,谁最先匹配就执行谁。
    Spring MVC默认:/org/springframework/web/servlet/DispatcherServlet.properties
   org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
                                                                                                      org.springframework.web.servlet.do.annotation.DefaultAnnotationHandlerMapping
  BeanNameUrlHandlerMapping:处理通过<bean name="/xxx">注册的控制器。控制器需要实现Controller接口。

  DefaultAnnotationHandlerMapping:处理通过注解@Controller(类标签) 及@RequestMapping(方法标签) 注册的控制器。 该请求映射处理器已经在Spring 3.2 版本过时,替换为RequestMappingHandlerMapping。

  spring 中提供的映射处理器:
        org.springframework.web.servlet.handler.SimpleUrlHandlerMapping   简单url请求映射处理器。
        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          <property name="mappings">
            <value>
                /helloworld=helloworldController
                /helloworld002=helloworldController
            </value>
         </property>
     </bean>
        org.springframework.web.servlet.do.method.annotation.RequestMappingHandlerMapping  采用注解方式请求映射处理器。
HandlerAdapter 处理器适配
HandlerAdapter 处理器适配:
   作用: 支持多种类型的处理器,如何来执行"处理器(控制器)“; 
     Spring MVC默认:
    org.springframework.web.servlet.HandlerAdapter=
                                                                                                    org.springframework.web.servlet.do.HttpRequestHandlerAdapter,\
                                                                                                    org.springframework.web.servlet.do.SimpleControllerHandlerAdapter,\
                                                                                                    org.springframework.web.servlet.do.annotation.AnnotationMethodHandlerAdapter

    org.springframework.web.servlet.do.HttpRequestHandlerAdapter 处理实现了HttpRequestHandler对应的控制器。
            核心代码:
          public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

                ((HttpRequestHandler) handler).handleRequest(request, response);
            return null;
    }

   org.springframework.web.servlet.do.SimpleControllerHandlerAdapter 处理实现了Controller对应的控制器。

      public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {

            return ((Controller) handler).handleRequest(request, response);
        }

    org.springframework.web.servlet.do.annotation.AnnotationMethodHandlerAdapter  处理通过注解方式的控制器。 3.2中已过时,替换为org.springframework.web.servlet.do.method.annotation.RequestMappingHandlerAdapter
ViewResolver 视图解析器
   作用:根据不同的视图,响应不同的结果,比如普通的jsp或json.
   Spring mvc默认:
   org.springframework.web.servlet.ViewResolver=
                                                                    org.springframework.web.servlet.view.InternalResourceViewResolver

   InternalResourceViewResolver : 支持默认视图,采用forward,redirect。
   视图名:
          不写前缀默认为"转发" 
          视图名字符串前缀:
            forward:/xxx.jsp 采用转发。
          redirect:/xxx.jsp  采用重定向。

        new ModelAndView("forward:/userList");
        new ModelAndView("redirect:/userList");

   注册视图解析器:
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
     </bean>

6. 对静态资源访问

我们这样的配置有这样一个问题
    在Web根路径添加index.html,然后不能访问,原因是什么呢?为什么此时在配置前端控制器的URL模式(<url-pattern>)写成 / 就不行呢?

原因:
Tomcat中处理静态资源访问的servlet(default)的映射路径为/.
    在启动项目的时候,在Tomcat中的web.xml是先加载的,项目的web.xml是后加载的,如果配置了相同的映射路径,后面的会覆盖前者.
    也就是说,SpringMVC中的DispatcherServlet的映射路径覆盖了Tomcat默认对静态资源的处理的路径。
    如果SpringMVC要配置为/,那么就得设置Dispatcherservlet对静态资源进行支持。

Tomcat 根/confg/web.xml 103行

下面中的 <url-pattern>/</url-pattern>

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
解决方案:需要在SpringMVC的配置文件中添加对静态资源的访问
    <mvc:default-servlet-handler/>
-----------------------------------------------------------------------------------------
<mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet  的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 Tomcat默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet  继续处理
-----------------------------------------------------------------------------------------
 /和/*的区别:
/  会匹配url请求/index等 ,也会匹配静态资源*.js,*.html等, 不会匹配*.jsp文件。
/* 会匹配url请求/index等 ,也会匹配静态资源*.js,*.html等,  会匹配*.jsp文件。
实际开发中一般推荐使用  *.后缀  如  *.do *.action *.do
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

7. Spring请求响应

7.1. @RequestMapping

@RequestMapping注解主要是设置SpringMVC请求的映射路径
所谓的映射路径,就是匹配请求路径和执行方法关系的路径.
请求路径:http://localhost:8080/springmvc/method1.do
映射路径:@RequestMapping(value="/method1")
@RequestMapping 用于贴在控制器的类上或者方法上面
如果是贴在控制器的类上面,那么在访问这个类的方法之前必须先加上类上的对应的名称
类似于 项目下面的 模块名称

如果贴在方法上面,就是访问此方法的资源名称

@Controller
@RequestMapping("/request")  //访问时候必须加上,类似模块名称
public class RequestController {
    @RequestMapping(value="/method1") //资源名称 
    public void method1() {
    }
}

访问地址 : http://localhost:8080/springmvc/request/method1.do

7.2. 两种限制

SpringMVC支持对请求的限制.如果不满足限制的条件,就不让访问执行方法.
这样做,大大提高了执行方法的安全性.
主要的限制有两种:(method)方法限制,参数限制

7.2.1. 方法限制

就是设置请求的method类型.如果发送过来的请求与方法设置的method不一样,就不能访问执行方法.

前端 请求method : GET , POST

  <form action="${pageContext.request.contextPath }/login.do" method="get">
    <input type="submit" value="登录">
  </form>

后台:

    /**
     * 接收的请求,必须是POST
     * @return
     */
    @RequestMapping(value="login",method=RequestMethod.POST)
    public String login(){
        System.out.println("-登录-");
        return "/login.jsp";
    }

前台发送的是GET请求,而方法限制是POST请求,所以请求无法执行方法

image

方法限制可以配置多个参数

    @RequestMapping(value="login",method={RequestMethod.GET,RequestMethod.POST})
    public String login(){
        System.out.println("-登录-");
        return "/login.jsp";
    }

7.2.2. 参数限制

1.就是请求里面必须包括哪些参数,或不包括哪些哪些.
2.参数包括哪些值,不包括哪些值

限制参数格式:

1.参数必须包括:params={"username","password"}
2.参数不能包括:params={"!userid"}
3参数值必须是指定的值:params={"username=zhangsan"})
4.参数值必须不是指定的值:params={"userid!=123"})

请求:没有后台方法指定的参数

<h4>登录页面</h4>
<form action="${pageContext.request.contextPath}/request/method1.do" method="post">
    账号:<input name="username"><br>
    密码:<input type="password" name="pwd"><br>
    <button type="submit">登录</button>
</form>

后台代码

    /**
     * 需求:登录时必须包括用户名,密码
     * @return
     */
    @RequestMapping(value="login2",params={"username","password"})
    public String login2(){
        System.out.println("-登录-");
        return "/login.jsp";
    }

如果前台请求没有指定后台要求的参数,会报错.

7.3. Spring方法参数可以注入的类型

SpringMVC的方法默认可以注入 JavaWeb开发常用的数据共享对象

HttpServletRequest 
HttpServletResponse
HttpSession

获取这些共享对象以后,就可以向之前的Servlet一样,做任何数据共享以及页面跳转操作

/*
 * Spring的方法默认可以注入 JavaWeb开发常用的数据共享对象 
HttpServletRequest
HttpServletResponse
 * HttpSession 以后开发 按需注入
 */
@RequestMapping(value = "/method0")
public void method0(HttpServletRequest req, 
                    HttpServletResponse resp,
                    HttpSession session) {
    //TODO
}

8. 数据绑定

8.1. 数据绑定是什么

SpringMVC里面,所谓的数据绑定就是将请求带过来的表单数据绑定到执行方法的参数变量.
实际开发中,SpringMVC作为表现层框架,肯定会接受前台页面传递过来的参数,SpringMVC提供了丰富的接受参数的方法

8.2. 原始方式request.getParameter() 了解

SpringMVC可以注入HttpServletRequest对象,直接使用getParameter参数接受

前台:

<!--  原始方式request.getParameter() -->
<fieldset>
    <legend> 原始方式request.getParameter()</legend>
    <form action="${pageContext.request.contextPath}/request/method1.do" method="get">
        账号: <input name="username"><br>
        年龄: <input name="age"><br>
        <button type="submit">提交</button>
    </form>
</fieldset>

后台:

@RequestMapping(value="/method1",method=RequestMethod.POST) //资源名称 
public void method1(HttpServletRequest req,HttpServletResponse resp,HttpSession session) {
         //原始方式request.getParameter()
    String username = req.getParameter("username");
    String age = req.getParameter("age");
    System.out.println(username);
    System.out.println(age);
}

8.3. 方法形参与前台参数同名

在请求方法形参上,声明和表单字段名相同的参数名(可以自动同名匹配,然后进行封装)

<fieldset>
    <legend>方法形参与前台参数同名</legend>
    <form action="${pageContext.request.contextPath}/request/method2.do" method="post">
        账号: <input name="username"><br>
        年龄: <input name="age"><br>
        <button type="submit">提交</button>
    </form>
</fieldset>
//方法形参与前台参数同名
@RequestMapping(value="/method2",method=RequestMethod.POST) 
public ModelAndView method2(String username,String age) {
    System.out.println(username);
    System.out.println(age);
    return null;
}

8.4. 方法形参与前台参数不同名

<fieldset>
    <legend>方法形参与前台参数不同名</legend>
    <form action="${pageContext.request.contextPath}/request/method3.do" method="post">
        账号: <input name="name"><br>
        年龄: <input name="age"><br>
        <button type="submit">提交</button>
    </form>
</fieldset>
// 方法形参与前台参数不同同名
// 解决方案使用 : @RequestParam("前台表单对应的名")
@RequestMapping(value = "/method3", method = RequestMethod.POST)
public ModelAndView method3(@RequestParam("name") String username, String age) {
    System.out.println(username);
    System.out.println(age);
    return null;
}

8.5. 接受数组

<fieldset>
    <legend>接收数组或集合</legend>
    <form action="${pageContext.request.contextPath}/request/method4.do" method="post">
        账号: <input name="name"><br>
        年龄: <input name="age"><br>
        爱好: <input type="checkbox" name="hobbys" value="java">java
        <input type="checkbox" name="hobbys" value="html">html<br>
        <button type="submit">提交</button>
    </form>
</fieldset>
// 接受数组
    @RequestMapping(value = "/method4", method = RequestMethod.POST)
    public ModelAndView method4(String[] hobbys) {
        System.out.println(Arrays.toString(hobbys));
        return null;
    }

8.6. 对象传参

后台并不能直接接受集合参数,需要将集合设置到对应的JavaBean中,通过JavaBean接受集合参数

Pojo对象

public class User {
    private String username;
    private String password;
    private String email;
    private String phone;
    private String[] hobby;
}
<fieldset>
    <legend>接受对象,表单参数名必须和后台pojo对象对应的属性名相同</legend>
    <form action="${pageContext.request.contextPath}/request/method5.do" method="get">
        账号: <input name="username"><br>
        密码: <input type="password" name="password"><br>
        邮箱: <input name="email"><br>
        电话: <input name="phone"><br>
        爱好:<input type="checkbox" name="hobby" value="java">java
        <input type="checkbox" name="hobby" value="C">C
        <input type="checkbox" name="hobby" value="C++">C++<br/>
        <button type="submit">提交</button>
    </form>
</fieldset>
// 对象传参->对象中有集合
    @RequestMapping(value = "/method5", method = RequestMethod.POST)
    public ModelAndView method4(User user) {
        System.out.println(user);
        return null;
    }

8.7. 接受参数封装成Map集合

<fieldset>
    <legend>接受参数封装成Map集合</legend>
    <form action="${pageContext.request.contextPath}/request/method6.do" method="post">
        账号: <input name="username"><br>
        密码: <input name="password"><br>
        邮箱: <input name="email"><br>
        电话: <input name="phone"><br>
    </form>
</fieldset>
// 接受参数封装成Map集合
    @RequestMapping(value = "/method6", method = RequestMethod.POST)
    public ModelAndView method6(@RequestParam Map<String,Object> map) {
        System.out.println("map:"+map);
        return null;
    }

8.8. RESTful风格支持

8.8.1. RESTFUL 风格介绍

REST(英文:Representational State Transfer,简称REST)
描述了一个架构样式的网络系统,比如 web 应用程序。
它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。
在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,
简单对象访问协议)以及XML-RPC更加简单明了,REST都倾向于用更加简单轻量的方法设计和实现。
值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。
RESTful一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。
它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,
更易于实现缓存等机制。

8.8.2. 参数传递方法 GET

例如:根据商品id查询对应的商品信息(京东网站)

如果按照我们web开发应该是将商品id通过get方法跟在地址后面
普通方式 京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物! 京东不支持
但是京东不是使用的此种方式,使用的 RESTFUL风格 
RESTful风格 : 【AppleiPhone XS Max】Apple iPhone XS Max (A2104) 256GB 金色 移动联通电信4G手机 双卡双待【行情 报价 价格 评测】-京东

8.8.3. 案例代码

// RESTful风格
@RequestMapping(value = "/method7/{product_id}")
public ModelAndView method7(@PathVariable("product_id") Integer product_id) {
    System.out.println(product_id);//1231323123
    return null;
}

8.8.4. 浏览器访问地址

localhost:8080/springmvc/request/method7/1231323123.html

8.8.5. 使用RESTful优势

1.可以让页面伪静态
页面访问感觉像在访问静态html页面,实际上访问时动态页面(伪静态)
2,方便搜索引擎的SEO优化

8.9. 请求中文乱码问题

SpringMVC默认接受的参数是ISO-8859-1编码参数,单字节,不支持中文,Spring提供了一个过滤器可以让开发者自定义请求参数的字符编码

注意:此种方式只对post提交方式有效

    <!-- 统一配置SpringMVC接受请求参数的编码 -->
    <filter>
        <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
如果提交中文参数的提价是get方式
配置 tomcat/conf/server.xml 添加 URIEncoding="UTF-8"
 <Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

建议:以后表单一般使用post,get方式请求尽量不要使用中文作为参数

9. 响应传值方式

9.1. 返回void类型和共享数据 : 需要共享数据,页面跳转

//返回void类型和共享数据 : 需要共享数据,页面跳转
    //必须注入请求响应对象(共享数据,页面跳转)
    @RequestMapping("/method1")
    public void method1(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
        //共享数据
        req.setAttribute("username", "小龙女");
        //跳转到jsp页面要显示数据,就必须使用请求转发
        req.getRequestDispatcher("/WEB-INF/response/response.jsp").forward(req, resp);
    }
访问地址: http://localhost:8080/springmvc/response/method1.do

9.2. 返回ModelAndView类型和共享数据

/*
 *  返回ModelAndView类型和共享数据
 *  ModelAndView 模型和视图
 *  Spring提供此对象可以集中管理共享数据操作和设置跳转视图操作
 *  ModelAndView 只能使用请求转发
 */
@RequestMapping("/method2")
public ModelAndView method2() {
    ModelAndView mv = new ModelAndView();
    //共享数据,等价于 request对象共享数据的级别
    //mv.addObject(attributeName, attributeValue)
    mv.addObject("username", "杨过");
    //页面跳转,等价于request对象的请求转发
    //mv.setViewName(viewName);
    mv.setViewName("/WEB-INF/response/response.jsp");
    return mv;
}

访问地址: http://localhost:8080/springmvc/response/method2.do

9.3. 配置视图解析器

9.3.1. 代码分析图

image

9.3.2. 视图解析器的配置

<!-- 配置SpringMVC的视图解析器: 配置前缀和后缀 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置视图跳转的前缀 -->
        <property name="prefix" value="/WEB-INF/response/"/>
        <!-- 配置视图跳转的后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>

9.3.3. 配置视图解析器后的代码

Controller方法返回字符串表示逻辑视图名,通过视图解析器解析为物理视图地址。
此时默认的物理视图地址为:视图前缀+返回值+视图后缀
    @RequestMapping("/method2")
    public ModelAndView method2() {
        ModelAndView mv = new ModelAndView();
        //共享数据,等价于 request对象共享数据的级别
        //mv.addObject(attributeName, attributeValue)
        mv.addObject("username", "杨过");
        //页面跳转,等价于request对象的请求转发
        //mv.setViewName(viewName);
        //没有配置视图解析器之前的写法
        //mv.setViewName("/WEB-INF/response/response.jsp");
        //配置视图解析器之后的写法
        mv.setViewName("response");
        return mv;
    }

注意: 配置完视图解析器以后,必须保证,前缀目录下面必须有对应逻辑视图名称所在的 页面 ,否则可能会报404错误

9.4. 通过Model方式-设置共享数据

/*
 * Model方式 :  直接将需要共享的数据封装到Model对象中即可
 *  方法返回String字符传直接,返回需要跳转的地址即可
 *   默认使用请求转发
 */
@RequestMapping("/method3")
public String method3(Model m) {
    //m.addAttribute(attributeName, attributeValue)
    m.addAttribute("username", "小敬哥123");
    //没有配置视图解析器之前的写法
    //return "/WEB-INF/response/response.jsp";
    //配置视图解析器之后的写法
    return "model"; //返回逻辑视图名称
}

9.5. 自定义请求转发和重定向跳转的页面

 * 如果直接使用视图解析器的配置开发,那么必须保证视图解析器前缀目录下面有对应的页面文件才能跳转,否则报错
 * 默认页面跳转也只能使用请求转发跳转,不能使用重定向 需要解决问题: 除了使用视图解析器对应规则的开发,用户还得自定义跳转方式,和自定义跳转页面 方案:
 * 使用视图解析器的 请求转发和重定向配置,可以打破默认的规则
 * public static final String REDIRECT_URL_PREFIX = "redirect:"; 
 * public static final String FORWARD_URL_PREFIX = "forward:";

9.5.1. 案例代码

// 自定义请求转发页面跳转的地址 : forward: 跳转的地址
@RequestMapping("/method4")
public String method4(Model m) {
    // m.addAttribute(attributeName, attributeValue)
    m.addAttribute("username", "东方姑娘");
    return "forward:/WEB-INF/views/index.jsp";
}
// 自定义重定向页面跳转的地址 redirect: 跳转的地址
@RequestMapping("/method5")
public String method5() {
    return "redirect:京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!";
}

9.6. 返回对象类型和共享数据

方法不返回ModelAndView也不返回String类型对应的逻辑视图名称直接返回一个Pojo对象
如果直接返回Pojo对象,项目又配置了视图解析器规则
如果方法中没有返回ModelAndView对象,此时SpringMVC不知道视图在哪里.
此时需要配置视图解析器org.springframework.web.servlet.view.InternalResourceViewResolver.
物理视图路径为:前缀+请求路径(上下文路径+资源名称)+后缀
必须保证视图解析器路径下面必须有 请求路径对应的页面

@ModelAttribute作用如下:

1、设置请求参数绑定到Model对象中并传到视图页面的key名.
2、将方法返回值或请求参数绑定到Model对象中并传到视图页面
image
@ModelAttribute("userKey")//跳转页面使用el表达式获取的对应的属性名称
    @RequestMapping("/method6")
    public User method6() {
        User user = new User();
        user.setUsername("东方姑娘");
        user.setPassword("dfgn");
        user.setEmail("dfgn@qq.com");
        user.setPhone("234234234324");
        return user;
    }

9.7. 转换JSON数据

在web开发中,前台页面经常会发送ajax请求从后台请求数据,ajax请求给前台的数据一般都是json 数据。
SpringMVC支持自动将对象转换JSON格式的数据响应给客户端
SpringMVC默认使用的是 jackson 作为对象转json的工具

Fast-json Alibaba
Gson google
Json-lib Apache

9.7.1. 步骤

导入jackson的jar包

image

案例代码

@Controller
public class JsonController {
    @RequestMapping("/getUserJson")
    @ResponseBody //把响应的内容设为普通字符串
    public User getUserJson() {
        User user = new User();
        user.setUsername("东方姑娘");
        user.setPassword("dfgn");
        user.setEmail("dfgn@qq.com");
        user.setPhone("234234234324");
        return user;
    }

    @RequestMapping("/getUserJsonList")
    @ResponseBody
    public List<User> getUserJsonList() {
        User user = new User();
        user.setUsername("东方姑娘");
        user.setPassword("dfgn");
        user.setEmail("dfgn@qq.com");
        user.setPhone("234234234324");

        List<User> list = new ArrayList<>();
        list.add(user);
        list.add(user);
        list.add(user);
        list.add(user);
        return list;
    }
}

10. 小结

1,SpringMVC介绍

(1) SpringMVC是一个Spring框架下面一个基于MVC模式的 表现层/Web 框架
(2) SpringMVC 底层就是Servlet,就是对Servlet的封装
(3) SpringMVC 接受参数灵活,页面跳转,共享数据方便

2,开发步骤

(1) 引入相关依赖jar包
(2) 在web.xml中配置SpringMVC的前端控制器
①   DispatcherServlet
(3) 在springmvc.xml配置文件配置包扫描,开启Springmvc的注解驱动
①   <context:component-sacn basePackage=’cn.zj.springmvc’>
②   <mvc:annotation-driven>
(4) 新建一个普通类型
①   在类上面贴上 @Controller注解,就是SpringMVC的控制器了
(5) 在类中新建一个方法,并且在方法上面贴上一个注解
①   @RequestMapping(“url地址访问路径”)
(6) 在浏览器输入地址即可访问

3,SpringMVC的请求

(1) 请求方法的限定  GET/POST 
(2) 请求参数的限定 ,必须有什么参数,必须没有什么参数,参数值必须是什么,参数值必须不是什么
(3) 数据绑定(接受请求参数)
①   表单提交参数名和方法参数名相同 -最常见
②   表单提交参数名和方法参数名不相同
1)  在方法参数前面写上@RequestParam("和表单参数名相同")
③   数组类型(多值)
④   接受多个参数封装成 pojo对象
1)  必须保证表单参数名称和pojo对象属性名称相同
⑤   将接受参数封装成map集合
(4) 支持 RestFul风格
①   @PathVariables()
(5) SpringMVC中文参数乱码的问题
①   Post方式 设置过滤器
②   Get方式 修改tomcat 配置

4,SpringMVC的相应

(1) ModelAndView 共享模型数据并且设置视图地址
(2) 方法直接返回 String 使用 Model 模型对象共享
(3) 自定义页面跳转
①   redirect: 重定向
②   forward:请求转发
(4) 配置视图解析器(配置视图的前缀和后缀)
(5) 返回对象类型
(6) 返回json数据
①   Jackson+@ResponseBody

参考:
SpringMVC-基础篇(一)

相关文章

网友评论

      本文标题:什么是Spring MVC

      本文链接:https://www.haomeiwen.com/subject/jnodlltx.html