SpringMvc框架

  • 什么是SpringMvc
    • 是spring框架的一个模块,springmvc和spring之间不需要中间整合层进行整合
    • 是一个基于mvc的web框架
      • mvc是一个设计模式
      • mvc在b/s系统下的应用
        • M:模型,包括pojo、action、service、dao
        • V:视图
        • C:控制器,接收用户的请求、响应
    • 前端控制器(DispatcherServlet)
      • 作用:接收请求,响应结果,  相当于转发器
    • 处理器映射器(HandlerMapping)
      • 作用:根据请求的url查找Handler
    • 处理器适配器(HandlerAdapter)
      • 作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
      • 注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才能正确执行Handler
    • 视图解析器(View resolver)
      • 作用:进行时图解析,根据逻辑视图名解析成真正的视图(View)
    • 视图(View)
      • View是一个接口,实现类支持不同的View类型
  • 入门
    • 导入spring-webmvc-4.3.5.RELEASE.jar
    • 若报错ClassNotFoundException: org.springframework.web.context.WebApplicationContext,导入spring-web-4.3.5.RELEASE.jar
    • Handler编写和调试
      <?xml version="1.0" encoding="UTF-8" ?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/mvc
              http://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
          <!-- 配置Handler -->
          <bean class="cn.muriel.auto.controller.UserController" name="/userController.action"/>
          <!-- 配置处理器映射器 -->
          <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
          <!-- 配置处理器适配器 -->
          <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
          <!--
              配置视图解析器
              解析jsp解析,默认使用jstl标签
          -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
      </beans>
      
      
      
      public class UserController implements Controller {
      
      
          @Override
          public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
      
              ApplicationContext applicationContext = new ClassPathXmlApplicationContext("service/service.xml");
              UserService userService = (UserService) applicationContext.getBean("userService");
              userService.selectAllUser();
      
              ModelAndView modelAndView = new ModelAndView();
              //如果不设置ViewName的话,就会404加参数
              //如果url错误就报404
              modelAndView.setViewName("WEB-INF/jsp/userList.jsp");
              return modelAndView;
          }
      }
    • 非注解的处理器映射器
        <!-- 配置Handler -->
          <bean class="cn.muriel.auto.controller.UserController" name="/userController.action" id="userController"/>
          <!-- 配置处理器映射器 -->
          <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        <!--
              多个映射器可以并存,前端控制器判断url能让那些映射器映射,就让正确的映射器处理
              所有的映射器都实现HandlerMapping接口
          -->
      <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
              <property name="mappings">
                  <props>
                      <prop key="/userController.action">userController</prop>
                  </props>
              </property>
          </bean>
    • 非注解的处理器适配器
       <!-- 配置处理器适配器,实现Controller接口 -->
          <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
      
      public class UserController implements Controller {
      
      
          @Override
          public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
      
            
          }
      }
    • 注解处理器映射器和处理器适配器
      • 使用注解的映射器不用在xml中配置url和handler的映射关系。注解的处理器映射器和处理器适配器必须成对使用
        <!-- 配置Handler,配置单个handler -->
        <bean class="cn.muriel.auto.controller.FoodController" />
        <!-- 注解开发中建议使用组建扫名描,进行handler扫描配置 -->
            <context:component-scan base-package="cn.muriel.auto.controller"/>
        
        <!--
                注解映射器
                在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器
                在spring3.1之后使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器
             -->
            <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
            <!-- 注解适配器 -->
            <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
        
            <!--
                mvc:annotation-driven代替上边注解映射器和注解适配器配置,
                它默认加载很多的参数绑定方法
             -->
            <mvc:annotation-driven></mvc:annotation-driven>
        
        
        //使用Controller标识它是一个控制器
        @Controller
        public class FoodController  {
        
            //一般建议将url和方法写成一样,控制器映射器
            @RequestMapping("/selectAllFood")
            public ModelAndView selectAllFood(){
        
                ModelAndView modelAndView = new ModelAndView();
                modelAndView.setViewName("WEB-INF/jsp/foodList.jsp");
                return modelAndView;
            }
        
        
        
        }
    • 视图解析器
       <!--
              配置视图解析器
              解析jsp解析,默认使用jstl标签
          -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!-- 配置Jstl,若与mvc:annotation-driven不需要配置,
              <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> -->
              <!-- 配置前缀 -->
              <property name="prefix" value="WEB-INF/jsp/"/>
              <!-- 配置后缀  -->
              <property name="suffix" value=".jsp"/>
          </bean>
      
      
      //使用Controller标识它是一个控制器
      @Controller
      public class FoodController  {
      
          //一般建议将url和方法写成一样,控制器映射器
          @RequestMapping("/selectAllFood")
          public ModelAndView selectAllFood(){
      
              ModelAndView modelAndView = new ModelAndView();
              //因为在springmvc.xml中配置了前缀和后缀,所以原格式WEB-INF/jsp/foodList.jsp可以改为foodList
              modelAndView.setViewName("foodList");
              return modelAndView;
          }
      
      
      
      }
    • 服务端校验
      • 控制层(controller):校验页面请求的参数的合法性。在服务端控制层controller校验,不区分客户端类型(浏览器、手机客户端、远程调用)
      • 业务层(service):主要校验关键业务参数,仅限于service接口中使用的参数
      • 持久层(dao):一般不校验
      • springmvc一般使用的是hibernate的validation的校验框架
        • 导入hibernate-validator-6.0.16.Final.jar、hibernate-validator-annotation-processor-6.0.16.Final.jar、jboss-logging-3.3.2.Final.jar、validation-api-2.0.1.Final.jar
    • 异常处理
      • springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理
      • 全局异常处理器
        • 思路
          • 系统遇到异常,在程序中手动抛出,dao抛出service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器
          • 解析出异常类型
          • 如果该异常类型是系统自定义的异常,直接取出异常信息,在错误页面展示
          • 如果该异常类型不是系统自定义异常,构造一个自定义的异常类型(信息为“未知错误”)
      • 如果与业务功能相关的异常,建议在service中抛出异常;如果与业务功能无关的异常,建议在controller中抛出异常
        /**
         * 系统自定义异常类,针对预期的异常,需要在程序抛出此类的异常
         */
        public class CustomException extends Exception {
        
            //异常信息
            private String message;
        
            /**
             * Constructs a new exception with {@code null} as its detail message.
             * The cause is not initialized, and may subsequently be initialized by a
             * call to {@link #initCause}.
             */
            public CustomException(String message) {
                this.message = message;
            }
        
            @Override
            public String getMessage() {
                return message;
            }
        
            public void setMessage(String message) {
                this.message = message;
            }
        }
        
        
        /**
         * 全局异常处理器
         */
        public class CustomExceptionResolve implements HandlerExceptionResolver {
            @Override
            public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        
                //创建一个自定义异常对象
                CustomException customExcetion = null;
                //判断异常类型是否是系统自定义异常
                if (e instanceof CustomException)
                    customExcetion = (CustomException) e;
                else
                    customExcetion = new CustomException("未知异常");
        
                //获取错误信息
                String errorMessage = customExcetion.getMessage();
        
                //创建一个ModelandView对象
                ModelAndView modelAndView = new ModelAndView();
                //将错误信息传递到页面
                modelAndView.addObject(errorMessage);
                //设置页面
                modelAndView.setViewName("error");
                return modelAndView;
            }
        }
        
        <!-- 在springmvc中进行注册 -->
         <!-- 配置全局异常处理器 -->
                <bean class="cn.muriel.ssm.exception.CustomExceptionResolve"></bean>

         

    • 上传图片
      • 在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行分析
      • 在springmvc.xml中配置multipart类型解析器,若不配置参数绑定会失败,无法传递参数
      • 导入commons-fileupload-1.4.jar、commons-io-2.6.jar
    • requestBody和responseBody实现与json交互
      • 请求json、输出json
        /**
         * @ResponseBody:
         * @RequestBody:将请求的商品信息json串转成指定对象
         * @param userCustom
         * @return
         */
        @RequestMapping(value = "/insertUser",method = RequestMethod.POST)
        public @ResponseBody UserCustom insertUser(@RequestBody UserCustom userCustom){
        
            JSONObject jsonObject = JSONObject.fromObject(userCustom);
            System.out.println(jsonObject);
            return userCustom;
        }

         

      • 请求key/value、输出json
      • 若报错HttpMediaTypeNotSupportedException,则导入jackson-databind-2.9.8.jar
      • 若报错java.lang.NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonView,则导入jackson-annotations-2.9.8.jar
      • 配置json转换器,导入jackson-core-2.9.8.jar、jackson-mapper-asl-1.9.13.jar、jackson-databind-2.9.8.jar、jackson-annotations-2.9.8.jar
           <!-- json转换器配置,若使用<mvc:annotation-driven/>则无需进行配置 -->
                <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
                    <property name="messageConverters">
                        <list>
                            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        
                            </bean>
                        </list>
                    </property>
        
                </bean>

         

    • spring对RESTful支持
      • RESTful架构,就是一种互联网软件框架,它结构清晰、符合标准、易于理解、扩展方便。
      • RESTfule(Representational State Transfer)其实就是一个开发理念,是对http的很好诠释。
      • Http四种请求方法
        • GET:获取资源
        • POST:新建资源,即更新资源
        • PUT:更新资源
        • DELETE:删除资源
      • 思路:
        • 不管是删除、添加、更新使用的url是一致的,区别在于http的方法设置为delete、post、get、put
        • 后台需要判断http的方法,再执行相应操作
          在web.xml进行RESTful控制器配置
            <!-- 配置Restful控制器 -->
              <servlet>
                  <servlet-name>springmvc_rest</servlet-name>
                  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                  <init-param>
                      <param-name>contextConfigLocation</param-name>
                      <param-value>classpath:spring/springmvc.xml</param-value>
                  </init-param>
              </servlet>
              <servlet-mapping>
                  <servlet-name>springmvc_rest</servlet-name>
                  <!--
          
                   -->
                  <url-pattern>/</url-pattern>
              </servlet-mapping>
          
          
           
           /**
               * /deleteUserById/{id}里面的{id}表示将这个位置的参数传到@PathVariable指定名称中
               *
               * @param id
               * @PathVariable:用于将请求URL中的模版变量映射到功能处理方法的参数上 通过在方法中使用@pathVariable获取{xxx}中的xxx变量
               */
              @RequestMapping("/deleteUserById/{id}")
              public @ResponseBody UserCustom deleteUserById(@PathVariable("id") Integer id) {
          
                  UserCustom userCustom = new UserCustom();
                  userCustom.setId(id);
          
                  System.out.println("id=" + id);
                  return userCustom;
          
              }

           

      • 注意:若使用Restful的方法返回值不要为void,不然可能会去寻找jsp资源,报404
      • 通过RESTful访问静态资源,要在springmvc.xml配置静态资源解析,否则会报404
        <!-- 静态资源解析,包括JS、css、img等等 -->
                <mvc:resources mapping="/images/**" location="WEB-INF/images/"/>

         

    • springmvc拦截器
      • 例如:统一日志处理器,需要该拦截器preHandle必须放行,且将它防砸拦截器链接中第一个位置
      • 例如:登录认证拦截器,放在拦截器链接中第一个位置
      • 例如:权限校验拦截器,放在登录认证拦截器之后,因为只有登录通过才能验证
      • 针对Mapping配置拦截器
        • springmvc拦截器针对HandlerMapping进行拦截设置。
        • 如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的handler最终使用该拦截器
      • 类似全局配置拦截器
        • springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中
           <!-- 拦截器 -->
                  <mvc:interceptors>
                      <!-- 多个拦截器,顺序执行 -->
                      <mvc:interceptor>
                          <!-- /**表示所有url包括子url路径 -->
                          <mvc:mapping path="/**"/>
                          <bean class="cn.muriel.ssm.interceptor.TestInterceptor"/>
                      </mvc:interceptor>
                  </mvc:interceptors>
          
          
          
          /**
           * 
           */
          public class TestInterceptor implements HandlerInterceptor {
              /**
               * 进入Handler方法之前执行
               * @param httpServletRequest
               * @param httpServletResponse
               * @param o
               * @return
               * @throws Exception
               */
              @Override
              public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
                  //return false表示拦截,不向下执行
                  //return true表示放行
                  return false;
              }
          
              /**
               * 进入Handler方法之后,返回ModelAndView之前执行
               * 应用场景:将共用的数据(例如菜单导航)在这里传到视图,也可以在这里统一指定视图
               * @param httpServletRequest
               * @param httpServletResponse
               * @param o
               * @param modelAndView
               * @throws Exception
               */
              @Override
              public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
          
              }
          
              /**
               * 执行Handler完成执行此方法
               * 应用场景:统一异常处理、统一日至处理
               * @param httpServletRequest
               * @param httpServletResponse
               * @param o
               * @param e
               * @throws Exception
               */
              @Override
              public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
          
              }
          }

           

posted @ 2019-03-28 11:36  好胖的兔子  阅读(287)  评论(0编辑  收藏  举报