SpringMVC基础知识(下篇)

一、处理JSON

JSON知识:

  1. JSON 有两种格式:① Json 对象:{key:value,key:value…},②Json数组:[value1, value2…]

  2. Json 对象解析方式: 对象.key; Json 数组的解析方式:for循环遍历

  3. java对象转Json: ① Bean 和 map —》Json 对象;② List —》 json数组

1、 返回JSON

  1. 加入 jar 包:

    下载地址:https://repo1.maven.org/maven2/com/fasterxml/jackson/core/

    image-20200803112445649

    注意: 请根据自己的Spring版本下载最新的jar,否则有肯能会报错。

    报错异常可以参考我这篇博客:解决方案

    image-20200803112639555

  2. SpringMVC处理json四个条件

​ ① 导入jackson的jar

​ ② 在springMVC的配置文件中开启MVC驱动,<mvc:annotation-driven />

​ ③ 在处理ajax请求的方法上加上注解**@ResponseBody**

​ ④ 将要转换为json且响应到客户端的数据,直接作为该方法的返回值返回

  1. 代码示例

【index.jsp】

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
    <script type="text/javascript" src="${pageContext.servletContext.contextPath}/js/jquery-1.8.2.min.js"></script>
    <script type="text/javascript" >
      $(function () {
        $('#btn').click(function () {
          $.ajax({
            url:"testJson",
            type:"POST",
            dataType:"json",
            success:function (msg) {
              for(var i in msg){
                var emp = msg[i];
        alert("id="+emp.id+",lastName="+emp.lastName+",departmentName="+emp.department.departmentName);
              }
            }
          });
        });
      });
    </script>
  </head>
  <body>
    <a href="testJson">测试JSON</a>
  </body>
</html>

【JsonControllerTest.json】**@ResponseBody : ** SpringMVC 对 JSON 的支持

@Controller
public class JsonControllerTest {

    @Autowired
    private EmployeeDao employeeDao;

    @RequestMapping(value = "/testJson")
    @ResponseBody
    public Collection<Employee> testJson(){

        Collection<Employee> emps = employeeDao.getAll();
        return emps;
    }
}
  1. 测试

image-20200803113451999

2、 使用AJAX

【index.jsp】

<html>
  <head>
    <title>$Title$</title>
    <link rel="stylesheet" href="${pageContext.servletContext.contextPath}/css/index_like.css">
    <script type="text/javascript" src="${pageContext.servletContext.contextPath}/js/jquery-1.8.2.min.js"></script>
    <script type="text/javascript" >
      $(function () {
        $('#btn').click(function () {
          $.ajax({
            url:"testJson",
            type:"POST",
            dataType:"json",
            success:function (msg) {
              /*
                        [
                            {"id":1001,"lastName":"E-AA","email":"aa@163.com","gender":1,"department":{"id":101,"departmentName":"D-AA"}},
                            {"id":1002,"lastName":"E-BB","email":"bb@163.com","gender":1,"department":{"id":102,"departmentName":"D-BB"}},
                            {"id":1003,"lastName":"E-CC","email":"cc@163.com","gender":0,"department":{"id":103,"departmentName":"D-CC"}},
                            {"id":1004,"lastName":"E-DD","email":"dd@163.com","gender":0,"department":{"id":104,"departmentName":"D-DD"}},
                            {"id":1005,"lastName":"E-EE","email":"ee@163.com","gender":1,"department":{"id":105,"departmentName":"D-EE"}}
                        ]
               */
              // 第一种实现方式
              /*var tb = "<table>";
              tb += "<tr><th>id</th><th>lastName</th><th>email</th><th>gender</th><th>departmentName</th></tr>"
              for(var i in msg){
                var emp = msg[i];
                tb += "<tr><td>"+emp.id+"</td><td>"+emp.lastName+"</td><td>"+emp.email+"</td><td>"+emp.gender+"</td><td>"+emp.department.departmentName+"</td></tr>"
              }
              tb += "</table>"
              $('body').append(tb);*/

              //第二种实现方式
              $('body').append("<table></table>");
              $('table').append("<tr><th>id</th><th>lastName</th><th>email</th><th>gender</th><th>departmentName</th></tr>");
              for(var i in msg){
                var emp = msg[i];
                $('table').append("<tr><td>"+emp.id+"</td><td>"+emp.lastName+"</td><td>"+emp.email+"</td><td>"+emp.gender+"</td><td>"+emp.department.departmentName+"</td></tr>");
              }
            }
          });
        });
      });
    </script>
  </head>
  <body>
    <a href="hello">测试</a>
    <br>
    <a href="testJson">测试JSON</a>
    <br>
    <input id="btn" type="button" value="测试ajax">
  </body>
</html>

测试:

image-20200803163539333

二、HttpMessageConverter 原理

1、HttpMessageConverter<T>

HttpMessageConverter<T> 是 Spring3.0 新添加的一个接口, 负责将请求信息转换为一个对象(类型为 T), 将对象(类型为 T)输出为响应信息

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

image-20200803113843706

  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。
package org.springframework.http;
import java.io.IOException;
import java.io.InputStream;
public interface HttpInputMessage extends HttpMessage {
	InputStream getBody() throws IOException;
}
package org.springframework.http;
import java.io.IOException;
import java.io.OutputStream;
public interface HttpOutputMessage extends HttpMessage {
	OutputStream getBody() throws IOException;
}

image-20200803114336375

3、HttpMessageConverter

使用 HttpMessageConverter 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息, Spring 提供了两种途径:

  1. 使用 @RequestBody / @ResponseBody 对处理方法进行标注
  2. 使用 HttpEntity<T> / ResponseEntity<T> 作为处理方法的入参或返回值

三、文件上传下载

1、文件下载

  1. 代码示例

**方式一:**图片名字由服务进行绑定

​ 【index.jsp】

<body>
    <a href="down">下载图片</a>
</body>

​ 【TestUploadAndDownController.java】

    @RequestMapping(value = "/down")
    public ResponseEntity<byte[]> down(HttpSession session) throws Exception {

        // 获取下载文件的路径
        String realPath = session.getServletContext().getRealPath("img");
        String finalPath = realPath + File.separator + "2.jpg";
        InputStream is = new FileInputStream(finalPath);
        // available():获取输入流所读取的文件的最大字节数
        byte[] bt = new byte[is.available()];
        is.read(bt);

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition","attachment;filename=zzz.jpg");
        // 设置响应状态
        HttpStatus status = HttpStatus.OK;
        ResponseEntity<byte[]> entity = new ResponseEntity<>(bt, headers, status);
        return entity;
    }

测试:

image-20200803161906909

方式二: 图片有请求方式来获取

​ 【index.jsp】

<body>
    <a href="down/1">下载图片</a>
</body>

​ 【TestUploadAndDownController.java】

@RequestMapping(value = "/down/{username}")
 public ResponseEntity<byte[]> down(@PathVariable("username") String username, HttpSession session) throws Exception {

        // 获取下载文件的路径
        String realPath = session.getServletContext().getRealPath("img");
        String finalPath = realPath + File.separator + username+".jpg";
        InputStream is = new FileInputStream(finalPath);
        byte[] bt = new byte[is.available()];
        is.read(bt);

        // 获取请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition","attachment;filename="+username+".jpg");

        // 设置响应状态
        HttpStatus status = HttpStatus.OK;
        ResponseEntity<byte[]> entity = new ResponseEntity<>(bt, headers, status);
        return entity;
}

测试:

image-20200803162239131

2、文件上传

  1. 导入需要的Jar包

image-20200803161320628

  1. 代码示例

    【index.jsp】

<form action="up" method="post" enctype="multipart/form-data">
        头像:<input type="file" name="uploadFile"/>
        描述:<input type="text" name="desc"/>
        <input type="submit" value="上传"/>
</form>

​ 【配置spingmvc.xml】不配置上传则会报错

	<!-- 
		处理文件,将客户端上传的File文件,处理为MultipartFile
		注意:文件解析器的bean中id必须设置为multipartResolver
	 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置文件解析的编码,注意:一定要和页面的pageEncoding保持一致 -->
		<property name="defaultEncoding" value="UTF-8"></property>
		<!-- 设置最大上传文件大小 -->
		<property name="maxUploadSize" value="88888888"></property>
	</bean>

【TestUploadAndDownController.java】

方式一:

	@RequestMapping(value = "/up" ,method = RequestMethod.POST)
    public String up (String desc, MultipartFile uploadFile, HttpSession session) throws IOException {
        // 获取上传文件的名称
        String filename = uploadFile.getOriginalFilename();
        String path = session.getServletContext().getRealPath("phone") + File.separator + filename;
        // 获取输入流
        InputStream is = uploadFile.getInputStream();
        // 获取输出流
        File file = new File(path);
        OutputStream fos = new FileOutputStream(file);
        byte[] bt = new byte[1024];
        int len;
        while((len = is.read(bt)) != -1){
            fos.write(bt, 0, len);
        }
        is.close();
        fos.close();
        return "success";
    }

**注意:**上传出现异常

类型 异常报告

消息 E:\IDEA\SpringMVC\SpringMVC_demo3\out\artifacts\SpringMVC_demo3_war_exploded\phone\1.jpg (系统找不到指定的路径。)

java.io.FileNotFoundException: E:\IDEA\SpringMVC\SpringMVC_demo3\out\artifacts\SpringMVC_demo3_war_exploded\phone\1.jpg (系统找不到指定的路径。)

解决方法:(以为自己的为例子)E:\IDEA\SpringMVC\SpringMVC_demo3\out\artifacts\SpringMVC_demo3_war_exploded这个目录下创建一个phone文件就可解决问题

可以在代码中写入System.out.prinln(path); 方便查看图片上传的位置

方式二:

    @RequestMapping(value = "/up",method = RequestMethod.POST)
    public String up (MultipartFile uploadFile, HttpSession session) throws IOException {
        // 获取上传文件的名称
        String filename = uploadFile.getOriginalFilename();
        String finalFileName = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
        String path = session.getServletContext().getRealPath("phone") + File.separator + finalFileName;
        File file = new File(path);
        uploadFile.transferTo(file);
        return "success";
    }

3、多个文件上传

【index.jsp】

<form action="up" method="post" enctype="multipart/form-data">
        头像:<input type="file" name="uploadFile"/>
        头像1:<input type="file" name="uploadFile"/>
        头像2:<input type="file" name="uploadFile"/>
        <input type="submit" value="上传"/>
</form>

【TestUploadAndDownController.java】

    @RequestMapping(value = "/up",method = RequestMethod.POST)
    public String ups(MultipartFile[] uploadFile, HttpSession session) throws IOException {
        for(MultipartFile uploadFiles : uploadFile){
           //  判断文件是否为空
            if(! uploadFiles.isEmpty()){
               String filename = uploadFiles.getOriginalFilename();
               String finalFileName = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
               String path = session.getServletContext().getRealPath("phone") + File.separator + finalFileName;
               File file = new File(path);
               uploadFiles.transferTo(file);
           }
        }
        return "success";
    }

四、拦截器

1、 自定义拦截器

​ Spring MVC 也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的 功 能 , 自 定 义 的 拦 截 器 可 以 实 现 HandlerInterceptor 接 口 , 也 可 以 继 承 HandlerInterceptorAdapter 适配器类 。

  1. preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回 true;如果程序员决定不需要再调用其他的组件去处理请求,则返回 false。
  2. postHandle(): 这个方法在业务处理器处理完请求后,但是 DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求 request 进行处理。
  3. **afterCompletion():**这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。

代码示例:

【spingmvc.xml】中配置拦截器(3中方式)

(推荐使用):

    <mvc:interceptors>
        <!--默认拦截所有的请求-->
        <bean class="com.oy.online.springmvc.interceptor.FirstInterceptor"></bean>
    </mvc:interceptors>

    <mvc:interceptors>
        <!--此方式要求拦截器类上必须加注解@Component -->
        <ref bean="firstInterceptor"></ref>
    </mvc:interceptors>

    <mvc:interceptors>
        <!-- 设置自定义拦截方式 -->
        <mvc:interceptor>
            <bean class="com.oy.online.springmvc.interceptor.FirstInterceptor"/>
            <!-- 拦截所有的请求,这个必须写在前面,也就是写在【不拦截】的上面 -->
            <mvc:mapping path="/**" />
            <!-- 但是排除下面这些,也就是不拦截请求 -->
            <mvc:exclude-mapping path="/login.html" />
        </mvc:interceptor> 
    </mvc:interceptors>

【index.jsp】

<body>
    <a href="testInterceptor">测试拦截器</a>
</body>

【FirstInterceptor.java】

​ preHandle(): 中的 return 值true 表示不拦截放行,反之 false 拦截

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("First:preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("First:postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("First:afterCompletion");
    }
}

【TestInterceptorController.java】

@Controller
public class TestInterceptorController {

    @RequestMapping(value = "/testInterceptor")
    public String testInterceptor(){
        return "success";
    }
}

测试:

image-20200804115048604

2、拦截器方法执行顺序

image-20200804115212883

3、多个拦截器的执行顺序

图解:

image-20200804115427251

总结:

  • 当有多个拦截器时:

    • preHandle: 按照拦截器数组的正向顺序执行
    • postHandle: 按照拦截器数组得反向顺序执行
    • afterCompletion: 按照拦截器的数组反向顺序执行
  • 当多个拦截器的PreHandle有不同的值时

    • 第一个返回false,第二个返回false: 只有第一个preHandle会执行

      image-20200804121203337

    • 第一个返回true, 第二个返回false;两个(全部)拦截器的preHandle都会执行,但是(全部)postHandle都不会执行,而afterCompletion 只有第一个(返回false的拦截器之前的拦截器之前的所有afterCompletion)会执行

      image-20200804121300338

    • 第一个返回fasle,第二个返回true; 只有第一个的preHandle会执行

      image-20200804121426359

五、异常处理

1、异常处理的概述

  1. SpringMVC 通过 ExceptionResolver 处理程序的异常,包括Handler 映射、数据绑定以及目标方法执行发生的异常。
  2. SpringMVC 提供 HandlerExceptionResolver 的实现类

image-20200804232936099

2、HandlerExceptionResolver

  1. DispatcherServlet 默认装配的 HandlerExceptionResolver
  2. 没有使用 <mvc:annotation-driven/> 配置

image-20200804233240631

image-20200804233254472

  1. 使用了 <mvc:annotation-driven/> 配置:

image-20200804233402126

image-20200804233412600

3、异常处理_DefaultHandlerExceptionResolver

对一些特殊的异常进行处理,比如:

  • NoSuchRequestHandlingMethodException
  • HttpRequestMethodNotSupportedException
  • HttpMediaTypeNotSupportedException
  • HttpMediaTypeNotAcceptableException

代码示例

【index.jsp】

<body>
   <a href="testException">异常测试</a>
</body>

【ExceptionControllerTest.java】

	
@RequestMapping(value = "/testException",method = RequestMethod.POST) // 不能是POST请求
    public String testException(){
        System.out.println("testDefaultHandlerExceptionResolver...");
        return "success";
    }

测试:

image-20200805111942998

4、异常处理_SimpleMappingExceptionResolver

  1. 在springmmvc.xml 中配置
    <!--异常处理-->
    <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
            </props>
        </property>
    </bean>

【ExceptionControllerTest.java】

    @RequestMapping(value = "/testSimpleMappingException")
    public String testSimpleMappingException(){
        System.out.println("testSimpleMappingException....");
        String[] s = new String[10];
        // s[i] 下标大于数组的长度
        System.out.println(s[12]);
        return "success";
    }

测试:

image-20200805115112892

【eeor.jsp】

<body>
    <a href="#">操作异常,请稍后重试</a>
    <br>
    ${requestScope.exception }
</body>

image-20200805115300115

六、运行流程

1、 流程图

image-20200805115731886

工作流程描述:

  1. 用户向服务器发起请求,请求被SpringMVC 前端控制器 DispatcherServlet 捕获:

  2. DispatcherServlet对请求解析,得到请求资源的标识符(URL):

    判断请求 URL 对应的映射

    ① 不存在:

    • 再判断是否配置了 mvc:default-servlet-handler:
    • 如果没配置,则控制台报映射查找不到,客户端展示404 错误

    ② 存在:

    • 执行下面的流程
  3. 根据URL,调用HandlerMapping 获取该 Handler配置的所有相关的对象(包括 Handler 对象以及Handler 对象对应的拦截器),最后HandlerExecutionChain 对象的形式返回:

  4. DispatcherServlet 根据获得的 Handler, 选择一个合适的 HandlerAdapter。

  5. 如果成功获得 HandlerAdapter 后,此时将开始拦截器的 preHandler(…) 方法【正向】

  6. 提取Request 中的模型数据,填充Handler 入参,开始执行 Handler (Controller)方法,处理请求。在填充Handler的入参过程中,根据配置,SpringMVC 将帮助做一些额外的工作:

    ① HttpMessageConverter: 将请求的信息(如 json、xml 的数据)转换成一个对象,将对象转换成指定的响应信息

    ② 数据转换:对请求的消息进行数据转换。如String 转换Integer、Double等。

    ③ 数据格式化:对请求的消息进行数据格式化。如将字符串转换成数字或格式化日期等。

    ④ 数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 EEOR 中。

  7. Handler 执行完成后,向DispatcherServlet 返回一个ModelAndView 对象

  8. 此时开始执行拦截器的 postHasndle(…)方法【逆向】

  9. 根据返回的 ModelAndView (此时会判断是否存在异常:如果存在异常,则执行HandelExceptionResolver 进行异常处理)选择一个适合的DispacherServlet(必须是已经注册到Spring容器中 的 ViewResolver )返回给DispatcherServlet,根据Model 和 View, 来渲染试图

  10. 在返回给客户端需要执行拦截器的AfterCompletion 方法【逆向】

  11. 将渲染的结果返回给客户端

七、Spring 整合 SpringMVC

1、Spring 与 SpringMVC 的整合问题

  1. 需要进行 Spring 整合 SpringMVC 吗?
  2. 还是需要加入Spring 的 IOC 容器?
  3. 是否需要在web.xml 文件中配置启动 SpringMVC 容器的ContextLoaderListener?

需要:通常情况下,类似于数据源,事务,整合其他框架都是放在 Spring 的配置文件中(而不是放在SpringMVC 的配置文件中),实际上方入 Spring 配置文件对应的 IOC 容器中还有 Servlet 和 Dao。

不需要:都放在 SpringMVC 的配置文件中,也可以分多个 Spring 的配置文件,然后使用 import 节点导入其他的配置文件

2、Spring 整合 SpringMVC解决方案配置监听器

  1. 监听器配置【web.xml】

image-20200805155620646

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:bean.xml</param-value>
    </context-param>
  1. 创建Spring 的 【bean.xml】配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--设置扫描组件的包-->
    <context:component-scan base-package="com.oy.online.springmvc">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--<bean id="teacher" class="com.oy.online.springmvc.bean.Teacher"></bean>-->
</beans>
  1. SpringMVC 配置文件:【Springmvc.xml】
<!-- 设置扫描组件的包 -->
<context:component-scan base-package="com.oy.online.springmvc.Controller"/>
<!-- 配置视图解析器 -->
<bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/views/"/>
	<property name="suffix" value=".jsp"/>
</bean>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>

**注意:**在Teanch 类中增加构造方法,启动服务器,查看构造器执行情况。若Spring 的IOC 容器 和 SpringMVC 的 IOC 容器扫描的包有重合的部分,就会导致有的 bean 会被创建 2 次。

**解决:**使 Spring 的 IOC 容器扫描的包和 SpringMVC 的 IOC 容器扫描的包没有重合的部分.使用 exclude-filter 和 include-filter 子节点来规定只能扫描的注解 。

【bean.xml】: <!-- 不扫描@Controller注解 -->

image-20200805160544504

【Springmvc.xml】:<!-- 扫描@Controller注解 -->

image-20200805160709752

  1. 【index.jsp】
  <body>
    <a href="testListener">监听器测试</a>
  </body>
  1. 【SpringListener.java】

image-20200805161008189

public class SpringListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
       ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        ServletContext servletContext = servletContextEvent.getServletContext();
        servletContext.setAttribute("context", context);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

【ExceptionControllerTest.java】

@Controller
public class ExceptionControllerTest {

    @RequestMapping()
    public void testListener(HttpSession session){
        // 获取spring所管理的teacher对象
        ServletContext servletContext = session.getServletContext();
        ApplicationContext context = (ApplicationContext) servletContext.getAttribute("context");
        Teacher teacher = context.getBean("Teacher", Teacher.class);
        System.out.println(teacher);
    }
}

测试:

image-20200805161242267

3、SpringIOC 容器和 SpringMVC IOC 容器的关系

  1. SpringMVC 的 IOC 容器中的 bean 可以来引用 Spring IOC 容器中的 bean,之则不行. Spring IOC 容器中的 bean 却不能来引用 SpringMVC IOC 容器中的 bean 。
  2. 在 Spring MVC 配置文件中引用业务层的 Bean
  3. 多个 Spring IOC 容器之间可以设置为父子关系,以实现良好的解耦。
  4. Spring MVC WEB 层容器可作为 “业务层” Spring 容器的子容器:即 WEB 层容器可以引用业务层容器的 Bean,而业务层容器却访问不到 WEB 层容器的 Bean 。

image-20200805161453395

4、SpringMVC 对比 Struts2

  1. Spring MVC 的入口是 Servlet, 而 Struts2 是 FilterSpring MVC 会稍微比 Struts2 快些.
  2. Spring MVC 是基于方法设计, 而 Sturts2 是基于类,每次发一次请求都会实例一个 Action.
  3. Spring MVC 使用更加简洁, 开发效率 Spring MVC 确实比 struts2 高: 支持 JSR303, 处理 ajax 的请求。
  4. Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值