SpringMVC入门总结

SpringMVC

Spring MVC是目前主流的实现MVC设计模式的企业级开发框架,Spring框架的一个子模块,无需整合,开发更加便捷。

复习总结: 首次编辑2020.7.2(后续继续完善)

什么是MVC设计模式

应用程序分为:ControllerViewModel三层。controller接收客户端请求,调用model生成业务数据,传递给view.SpringMVC就是对这套流程的封装,屏蔽了许多底层代码。

SpringMVC 的核心组件
  • DispatherServlet:前置控制器,核心,控制其他组件执行,进行统一调度,降低组件之间耦合性。
  • Handler:处理器,完成具体业务逻辑,相当于Servlet或者action
  • HandlerMapping:接受来自DispatherServlet的请求,映射请求到不同的Handler
  • HandlerIntercrptor:handler拦截器,是一个接口,需要拦截业务,则实现该接口
  • HandlerExecutionChain:处理器执行链,包括HandlerHandlerIntercrptor(系统会有一个默认的HandlerIntercrptor
  • HandlerAdaptor:处理器适配器,处理器适配器,Handler 执⾏业务⽅法之前,需要进⾏⼀系列的操作,包括表单数据的验证、数据类型的转换、将表单数据封装到 JavaBean 等,这些操作都是由HandlerApater 来完成,开发者只需将注意⼒集中业务逻辑的处理上,DispatcherServlet 通过HandlerAdapter 执⾏不同的 Handler。
  • ModelAndView:包含视图和模型数据,作为handler的处理结果返回给dispatherServlet
  • ViewReslover:视图解析器,将逻辑视图转化为物理视图,渲染结果响应给客户端
SpringMVC的工作流程
  • 客户端请求被DispatherServlet接受
  • 根据HandlerMapping映射到handler
  • 生成handlerhandlerInterceptor
  • HandlerhandlerIntercepthandlerExecutionChain的形式返回给DispatherServlet
  • DispatherServlet通过handlerAdaptor调用handler的方法完成业务逻辑
  • handler返回一个modelandviewDispatherServlet
  • DispatherServlet将返回的modelandview对象传给viewResolver视图解析器,将逻辑视图变成物理视图view
  • viewResolver返回一个view给DispatherServlet
  • dispaServlet根据view进行视图渲染,响应给客户端

SpringMVC流程复杂,实际开发中很简单,因为大部分的组件不需要开发者创建、管理,只需要通过配置文件的方式完成配置即可。真正需要开发者进行处理的只有handler、view。

SpringMVC的特点
  • 清晰的角色划分
  • 灵活的配置功能
  • 提供了大量的控制器接口和实现类
  • 分离view层的实现
  • 国际化支持
  • 面向接口编程
如何搭建springmvc项目
  • 创建maven工程

    • 配置archetypeCAtalog==internal加快项目的构建

    • 最初结构

    • main下新建两个文件夹javaresources,右键Mark Directory as

    • pom.xml中添加依赖

    <!--springMVC依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.11.RELEASE</version>
    </dependency>
    
  • web.xml中配置DispatherServlet配置

    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      
      <servlet>
        <servlet-name>dispatherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      		<!--读取spring.xml配置文件-->  
          <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:springmvc.xml</param-value>
        </init-param>
      </servlet>
      <!--根目录下所有都交由DispatherServlet处理-->
      <servlet-mapping>
        <servlet-name>dispatherServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>
    
  • springmvc.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.kingwan"></context:component-scan>
        
        <!--配置视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    </beans>
    
  • 创建Handler

    package com.kingwan.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class MyHandler {
        @RequestMapping("/index")
        public String index(){
            System.out.println("执行了index...");
            return "index";
        }
    }
    
    
  • 流程说明:

    客户端输入http://localhost:8888/index其中indexDispatcherServlet捕获,交给对应的HandlerMapping处理(Handler已经通过ioc实例化,通过@RequestMapping注解映射),返回一个逻辑视图(return "index")交给DispatcherServletDispatcherServlet再交给视图解析器ViewResolver解析,根据定义的解析规则(配置视图解析器的那个bean),拼凑之后(/index.jsp)就去target根目录里找对应jsp文件。

SpringMVC注解
  • @RequestMapping

将URL请求与业务方法进行映射,在Handler的类定义处以及方法定义处都可以添加@RequestMapping,在类定义处添加,相当于多了一层访问路径,在方法处添加,即与方法绑定。

  • @Controller

在类定义处添加,将该类交给IOC容器管理(结合springmvc.xml的自动扫描),同时使其成为一个控制器,可以接受客户端请求。

package com.kingwan.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyHandler {
    @RequestMapping("/index")
    public String index(){
        System.out.println("执行了index...");
        return "index";
    }
}
  • @RequestMapping的相关参数
  1. value:指定URL请求的实际地址,是@RequestMapping的默认值

    @RequestMapping("/index")
    public String index(){
        System.out.println("执行了index...");
        return "index";
    }
    /*这两个效果相当*/
    @RequestMapping(value = "/index")
    public String index(){
        System.out.println("执行了index...");
        return "index";
    }
    
  2. method:指定请求的method类型,GET、POST、PUT、DELET

    //只允许接受get请求
    @RequestMapping(value = "/index",method = RequestMethod.GET)
    public String index(){
        System.out.println("执行了index...");
        return "index";
    }
    
    
  3. params:指定请求必须包含某些参数,否则无法调用该方法。

    @RequestMapping(value = "/index",method = RequestMethod.GET,params = {"name","id=10"})
    public String index(){
        System.out.println("执行了index...");
    
        return "index";
    }
    

    上述代码表示只能接受get请求,请求中必须包含两个参数name和id,其中id的值必须为10。

    关于参数绑定,在形参列表中,通过添加@RequestParm注解完成HTTP请求参数与业务方法形参映射.

    @RequestMapping(value = "/index",method = RequestMethod.GET,params = {"name","id=10"})
    public String index(String name,@RequestParam("id") int id){
        System.out.println("执行了index...");
        System.out.println(name);
        System.out.println(id);
        return "index";
    }
    

    上述代码表示请求的参数name和id分别赋给了形参name和id,同时完成了数据类型的转化,这些工作是由HandlerAdapter来完成的

  • 支持Restful风格

    @Controller
    @RequestMapping("/rest")
    public class RestfulHandler {
        @RequestMapping("/restful/{id}/{name}")
        public ModelAndView restful(@PathVariable("id") Integer id, @PathVariable("name") String name){
            ModelAndView mv = new ModelAndView();
            mv.addObject("id",id);
            mv.addObject("name",name);
            mv.setViewName("/view/hello");
            return mv;
        }
    }
    
    <a href="/rest/restful/1/张三">RESTful风格</a>
    

    使用@PathVariable注解完成请求参数和形参的映射

SpringMVC数据绑定
  • 传递请求参数

    <h4>地址栏参数绑定</h4>
    <a href="/paramTest01?name=张三&id=12">参数绑定1</a>
    <a href="/paramTest02?name=张三&id=12">参数绑定2</a>
    <a href="/paramTest03?name=张三&id=12">参数绑定3</a>
    <a href="/paramTest04?name=张三&id=12">参数绑定4</a>
    <h4>表单参数绑定</h4>
    <form method="post" action="/paramTest05">
        编号<input type="text" name="id">
        姓名<input type="text" name="name">
        <input type="submit" value="提交">
    </form>
    <h4>表单参数绑定(支持级联)</h4>
    <form method="post" action="/paramTest06">
        学生姓名<input type="text" name="name">
        学生编号<input type="text" name="user.id">
        <input type="submit" value="提交">
    </form>
    
    /**
         * 通过传统request.getParameter获取参数
         * @param request
         * @return
         */
    @RequestMapping("/paramTest01")
    public ModelAndView getParam(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        String name = request.getParameter("name");
        String id = request.getParameter("id");
        mv.addObject("name",name);
        mv.addObject("id",id);
        System.out.println(name+id);
        mv.setViewName("/view/hello");
        return  mv;
    }
    
    /**
         * 通过形参列表,形参名需要对应,顺序可以不一致
         * @param id
         * @param name
         * @return
         */
    @RequestMapping("/paramTest02")
    public ModelAndView getParam02(String id,String name){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",name);
        mv.addObject("id",id);
        System.out.println(name+id);
        mv.setViewName("/view/hello");
        return  mv;
    }
    
    /**
         * 使用@RequestParam注解方式
         * @param myid
         * @param myname
         * @return
         */
    @RequestMapping("/paramTest03")
    public ModelAndView getParam03(@RequestParam("id") String myid, @RequestParam("name") String myname){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",myname);
        mv.addObject("id",myid);
        System.out.println(myname+myid);
        mv.setViewName("/view/hello");
        return  mv;
    }
    
    /**
         * 传入一个封装对象
         * @param user
         * @return
         */
    @RequestMapping("/paramTest04")
    public ModelAndView getParam03(User user){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",user.getName());
        mv.addObject("id",user.getId());
        mv.setViewName("/view/hello");
        return  mv;
    }
    
    /**
         * 表单提交方式
         * @param user
         * @return
         */
    @RequestMapping("/paramTest05")
    public ModelAndView getParam05(User user){
        ModelAndView mv = new ModelAndView();
        mv.addObject("name",user.getName());
        mv.addObject("id",user.getId());
        mv.setViewName("/view/hello");
        return  mv;
    }
    
    /**
         * 表单提交方式(支持级联)
         * @param student
         * @return
         */
    @RequestMapping("/paramTest06")
    public ModelAndView getParam06(Student student){
        ModelAndView mv = new ModelAndView();
        System.out.println(student);
        mv.addObject("name",student.getName());
        mv.addObject("id",student.getUser().getId());
        mv.setViewName("/view/hello");
        return  mv;
    }
    
  • 基本数据类型绑定

    <a href="/data/basetype?id=10">直接返回数据(不返回视图)</a>
    
    /**
         * 绑定基本数据类型
         * @param id
         * @return
         */
    @RequestMapping("/basetype")
    @ResponseBody
    public String baseType(String id){
        return id;
    }
    

    @ResponseBody 表示 Spring MVC 会直接将业务⽅法的返回值响应给客户端,如果不加@ResponseBody注解,Spring MVC 会将业务⽅法的放回值传递给 DispatcherServlet,再由DisptacherServlet调⽤ ViewResolver对返回值进⾏解析,映射到⼀个 JSP 资源。

  • List类型

    Spring MVC 不⽀持 List 类型的直接转换,需要对 List 集合进⾏包装

    form action="/data/list" method="post">
        编号1<input type="text" name="userList[0].id">
        姓名1<input type="text" name="userList[0].name"><br>
        编号2<input type="text" name="userList[1].id">
        姓名2<input type="text" name="userList[1].name"><br>
        编号3<input type="text" name="userList[2].id">
        姓名3<input type="text" name="userList[2].name">
        <input type="submit" value="提交">
    </form>
    
    /**
         * list类型
         * @param userList
         * @return
         */
    @RequestMapping("/list")
    @ResponseBody
    public String userList(UserList userList){
        StringBuffer buffer = new StringBuffer();
        for (User user : userList.getUserList()) {
            buffer.append(user);
        }
        String string = buffer.toString();
        return string;
    }
    

    处理@ResponseBody中文乱码,springmvc.xml中配置消息转换器

    <!--配置编码-->
    <mvc:annotation-driven>
        <!--消息转化器-->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"></property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
  • JSON数据

    <script type="text/javascript">
        $(function () {
            var obj = JSON.stringify({'id':'123','name':'张三'});
            //后台使用对象的形式接受
            $.ajax({
                url: "/data/jsonAfter",
                type: "post",
                data: obj,
                contentType: 'application/json;charset=utf-8',
                dataType:"json",
                success:function (msg) {
                    alert(msg.id+"=="+msg.name)
                }
            })
        })
    </script>
    
    /**
         * 跳转到json.jsp页面
         * @return
         */
    @RequestMapping(value = "/jsonBefore")
    public String jsonBefore(){
        return "/view/json";
    }
    
    /**
         * 接受json数据,修改后返回
         * @param user
         * @return
         */
    @RequestMapping(value = "/jsonAfter",method = RequestMethod.POST)
    @ResponseBody
    public User jsonAfter(@RequestBody(required=false) User user){
        System.out.println(user);
        user.setName("李四");
        return user;
    }
    
    • 静态js资源无法访问:web.xml设置不拦截静态资源

      <!--不拦截静态资源-->
        <servlet-mapping>
          <servlet-name>default</servlet-name>
          <url-pattern>*.js</url-pattern>
        </servlet-mapping>
      
    • fastjson解析

      <!--json数据解析-->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.32</version>
      </dependency>
      
      <!--配置编码-->
      <mvc:annotation-driven>
          <!--消息转化器-->
          <mvc:message-converters>
              <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                  <property name="supportedMediaTypes" value="text/html;charset=utf-8"></property>
              </bean>
              <!--配置fastjson-->
              <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4"></bean>
          </mvc:message-converters>
      </mvc:annotation-driven>
      
SpringMVC自定义数据转换器

数据转换器是指将客户端 HTTP 请求中的参数转换为业务⽅法中定义的形参,⾃定义表示开发者可以⾃主设计转换的⽅式,HandlerApdter 已经提供了通⽤的转换,String 转 int,String 转 double,表单数据的封装等,但是在特殊的业务场景下,HandlerAdapter ⽆法进⾏转换,就需要开发者⾃定义转换器。

1.日期转换器
  • 创建DateConverter实现Converter接口

    package com.kingwan.converter;
    
    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * Created by kingwan on 2020/6/29.
     * 说明:日期转换器String-->日期类型
     */
    public class DateConverter implements Converter<String,Date> {
        private String pattern;
    
        public DateConverter(String pattern) {
            this.pattern = pattern;
        }
    
        @Override
        public Date convert(String s) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.pattern);
            Date date = null;
            try {
                date = simpleDateFormat.parse(s);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    }
    
    
  • springMVC.xml配置日期转换器

    <!--配置自定义转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <bean class="com.kingwan.converter.DateConverter">
                <constructor-arg type="java.lang.String" value="yyyy-MM-dd">
                </constructor-arg>
            </bean>
        </property>
    </bean>
    
  • 加入驱动

    <mvc:annotation-driven conversion-service="conversionService">
        <!--消息转化器-->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"></property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    
  • 前端及业务代码

    h4>日期类型转换器</h4>
    <form action="/converter/date" method="post">
        日期<input type="date" name="date">
        <input type="submit" value="提交">
    </form>
    
    package com.kingwan.handler;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.Date;
    
    /**
     * Created by kingwan on 2020/6/29.
     * 说明:
     */
    @Controller
    @RequestMapping("/converter")
    public class ConverterHandler {
        @RequestMapping("/date")
        @ResponseBody
        public String data(Date date){
            return date.toString();
        }
    }
    
    
SpringMVC自定义异常
  • 编写自定义异常类

    package com.kingwan.exception;
    
    /**
     * Created by kingwan on 2020/7/1.
     * 说明:自定义异常类
     */
    public class MyException extends Exception{
        public MyException() {
        }
        public MyException(String message) {
            super(message);
        }
        public MyException(String message, Throwable cause) {
            super(message, cause);
        }
        public MyException(Throwable cause) {
            super(cause);
        }
        public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
    
    
  • 编写MyExceptionResolver类实现HandlerExceptionResolver接口

    package com.kingwan.exception;
    
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Created by kingwan on 2020/7/1.
     * 说明:
     */
    public class MyExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            ModelAndView mv = new ModelAndView();
            if(e instanceof MyException){
                System.out.println("属于自定义异常");
                mv.addObject("error_message",e.getMessage());
                mv.setViewName("/404");
            }else {
                System.out.println("错误日志信息");
                mv.addObject("error_message",e.getMessage());
                mv.setViewName("/test.jsp");
            }
            return mv;
        }
    }
    
    
  • 测试手动抛出异常

    /**
         * 测试抛异常
         * @param request
         * @return
         * @throws Exception
         */
    @RequestMapping("/throw")
    public ModelAndView throwException(HttpServletRequest request) throws Exception{
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/view/hello");
        if(true){
            throw new MyException("手动抛Myexception异常");
        }
        return  mv;
    }
    
SpringMVC拦截器
SpringMVC文件上传及下载
1.单文件上传
2.多文件上传
3.文件下载
4.配置Tomcat虚拟路径
复习总结
  • 导入pom.xml中mvc依赖
  • 配置dispatcherServlet
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值