• 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 {
            
                }
            }
  • 相关阅读:
    U8g2库I2C总线再次突破性调试成功
    要学的东西太多了,还想学习opencv
    中断知识
    别人做的扫地机器人,有机会我也想搞一台!
    团队冲刺第五天
    第八周学习进度
    团队冲刺第四天
    构建之法1
    团队冲刺第三天
    团队冲刺第二天
  • 原文地址:https://www.cnblogs.com/fatRabbit-/p/10547797.html
Copyright © 2020-2023  润新知