SpringMVC快速入门

Web环境下Spring获取应用上下文

  1. 底层实现原理

    在Web项目中,可以使用ServletContextListener监听Web应用的启动,我们可以在Web应用启动时,就加载Spring的配置文件,创建应用上下文对象ApplicationContext,再将其存储到最大的域servletContext域中,这样就可以在任意位置从域中获得应用上下文ApplicationContext对象了。

    <!-- web.xml -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>applicationContext.xml</param-value>
    </context-param>
    
    @WebListener
    public class ContextLoaderListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            ServletContext servletContext = servletContextEvent.getServletContext();
            //读取web.xml中的全局参数
            String springContextLocation = servletContext.getInitParameter("contextConfigLocation");
            ApplicationContext app = new ClassPathXmlApplicationContext(springContextLocation);
            //将上下文对象存储到ServletContext域中
            servletContext.setAttribute("app",app);
            System.out.println("Spring容器创建完毕...");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {}
    }
    
    public class WebApplicationContextUtils {
        public static ApplicationContext getWebApplicationContext(ServletContext servletContext){
            return (ApplicationContext) servletContext.getAttribute("app");
        }
    }
    
    ServletContext servletContext = this.getServletContext();
    ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
    
  2. 使用Spring API获取应用上下文

    • 上面的不需要手动实现,Spring提供了一个监听器ContextLoaderListener就是对上述功能的封装,该监听器内部加载Spring配置文件,创建应用上下文对象,并存储到ServletContext域中,提供了一个客户端工具WebApplicationContextUtils供使用者获取应用上下文对象。

    • 如何获取?

      • 导入spring-web坐标

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        
      • 在web.xml中配置ContextLoaderListener监听器与Spring核心配置文件路径

        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </context-param>
        
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        
      • 使用WebApplicationContextUtils获取应用上下文对象ApplicationContext

        ServletContext servletContext = this.getServletContext();
        WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        //WebApplicationContext是ApplicationContext的子类
        

SpringMVC简介

SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品,已经融合在Spring Web Flow中。

SpringMVC已经成为目前最主流的MVC框架之一,并且随着Spring3.0的发布,全面超越Struts2,成为最优秀的MVC框架。它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful编程风格的请求。

SpringMVC快速入门

  1. 需求:客户端发起请求,服务器接收请求,执行逻辑并进行视图跳转

  2. 开发步骤

    • 导入SpringMVC相关坐标

    • 配置SpringMVC核心控制器DispathcerServlet(在web.xml中)

      <!-- spring-webmvc -->
      <!-- 前端控制器 -->
      <servlet>
          <servlet-name>DispatcherServlet</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
              <!-- spring-mvc上下文 -->
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:spring-mvc.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
          <servlet-name>DispatcherServlet</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
      
    • 创建Controller类和视图页面

      @Controller
      public class UserController {
      
      }
      
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
          <head>
              <title>success.jsp</title>
          </head>
      
          <body>
              <h1>Success!</h1>
          </body>
      </html>
      
    • 使用注解配置Controller类中业务方法的映射地址

      @Controller
      public class UserController {
      
          @RequestMapping("/userSave")    //请求映射,访问对应url时会调用该方法
          public String save(){
              System.out.println("Controller save running...");
              return "/jsp/success.jsp";   //转发到另一个资源,一般是视图层
              //return "redirect:/jsp/success.jsp";	//重定向
          }
      
      }
      
    • 配置SpringMVC核心文件spring-mvc.xml

      <context:component-scan base-package="pers.zero.controller"/>
      
    • 客户端发起请求测试

  3. SpringMVC执行流程(宏观)

    image-20210210154010210

SpringMVC的数据响应

  1. 数据响应方式

    • 页面跳转(转发请求,可能会在request域中添加一些数据)
      • 直接返回字符串
      • 通过ModelAndView对象返回
    • 回写数据(直接将数据返回给请求者)
      • 直接返回字符串(一般用于返回json字符串或简单视图)
      • 返回对象或集合(在配置后可返回json格式数据)
  2. 页面跳转

    • 直接返回字符串

      • 默认为转发,也可加forward:前缀,转发会经过视图解析器,因此会受到视图解析器设置的前后缀影响

      • 重定向需要使用redirect:前缀,但要注意重定向不会经过视图解析器,因此设置的前后缀对其无影响,应该使用完全路径

      • 传递参数

        //使用Model
        public String test(Model model){
            model.addAttribute("username","test1_2");
            return "success";
        }
        
        //使用原生request,不推荐
        public String test(HttpServletRequest request){
            request.setAttribute("username","test1_3");
            return "success";
        }
        
    • 通过ModelAndView对象返回【Model:模型,用于封装数据(通过模型向视图传递参数)】【View:视图,用于显示数据】

      • 第一种方式:手动创建ModelAndView对象

        public ModelAndView test(){
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("username","tom");//数据会被放入request域
            modelAndView.setViewName("success");//只要是转发就会受到视图解析器的前后缀影响
            return modelAndView;
        }
        
      • 第二种方式:使用SpringMVC自动创建的ModelAndView

        public ModelAndView test(ModelAndView modelAndView){	//SpringMVC会传递参数
            modelAndView.addObject("username","tom");
            modelAndView.setViewName("success");
            return modelAndView;
        }
        
  3. 回写数据

    • 直接返回字符串

      • 第一种方式:使用@ResponseBody注解+return字符串方式

        @ResponseBody   //表明返回字符串而不是跳转
        public String test() throws IOException {
            User user = new User();
            user.setUsername("test");
            user.setAge(18);
            //使用jackson将对象转换为json格式字符串
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(user);
            return json;	//{"username":"test3_3","age":18}
        }
        
      • 第二种方式:原生response.getWriter().print()方式,不推荐

        public void test(HttpServletResponse response) throws IOException{
            response.getWriter().print("hello world");
        }
        
    • 返回对象或集合

      • 第一种方式:在spring-mvc.xml中配置处理器适配器后直接返回对象,处理器适配器会将对象转为json字符串

        <!-- 配置处理器适配器 -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <property name="messageConverters">
                <list>
                    <!-- 配置:返回对象/数组会自动转换成json字串 -->
                    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
                </list>
            </property>
        </bean>
        
        @ResponseBody
        public User test(){
            User user = new User();
            user.setUsername("test");
            user.setAge(18);
            return user;
        }
        
      • 第二种方式:在spring-mvc.xml中配置mvc注解驱动,便可实现上述效果

        <mvc:annotation-driven/>
        

SpringMVC处理请求数据

  1. SpringMVC可以接收的参数类型

    • 基本类型参数
    • POJO类型参数(简单的Java对象,就是普通的JavaBeans)
    • 数组类型参数
    • 集合类型参数
  2. 获得基本类型参数

    Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配

    ......?username=test&age=10
    
    @ResponseBody   //不能省,否则会跳转到/user/test
    public void test(String username,int age){
        System.out.println(username);
        System.out.println(age);
    }
    
  3. 获得POJO类型参数

    Controller中的业务方法的POJO参数的属性名与请求参数的name一致,参数值会自动映射匹配

    ......?username=test&age=1
    
    public class User {
        private String username;
        private int age;
    
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    @ResponseBody
    public void test6(User user){
        System.out.println(user);
    }
    
  4. 获得数组类型参数

    Controller中的业务方法数组参数与请求参数的name一致,参数值会自动映射匹配

    ......?strs=ab&strs=cd&strs=ef
    
    @ResponseBody
    public void test7(String[] strs){
        System.out.println(Arrays.asList(strs));
    }
    
  5. 获得集合类型参数

    • 获得通过Ajax提交的json形式集合类型参数时,可以指定contentType为json形式,那么再方法参数位置使用注解**@RequestBody**可以直接接收集合数据而无需使用POJO进行包装

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>ajax.jsp</title>
          <script src="${pageContext.request.contextPath}/js/jquery-1.12.4.min.js"></script>
          <script>
              var userList = new Array();
              userList.push({username:"张三",age:18});
              userList.push({username:"李四",age:20});
              $.ajax({
                  type:"POST",
                  url:"${pageContext.request.contextPath}/user/test",
                  data:JSON.stringify(userList),
                  contentType:"application/json;charset=utf-8"
              });
          </script>
      </head>
      <body>
      
      </body>
      </html>
      
      @ResponseBody
      public void test(@RequestBody List<User> userList){
          System.out.println(userList);
      }
      
    • 获得通过表单提交的集合类型参数时,需要把集合参数包装到一个POJO中才可以

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>form.jsp</title>
      </head>
      <body>
          <p>"${pageContext.request.contextPath}"</p>
          <form action="${pageContext.request.contextPath}/user/test" method="post">
              <%-- 表明是第一个User对象的username age --%>
              <input type="text" name="userList[0].username"><br/>
              <input type="text" name="userList[0].age"><br/>
              <input type="text" name="userList[1].username"><br/>
              <input type="text" name="userList[1].age"><br/>
              <input type="submit" value="提交">
          </form>
      </body>
      </html>
      
      public class VO {
          private List<User> userList;
      
          public List<User> getUserList() {
              return userList;
          }
      
          public void setUserList(List<User> userList) {
              this.userList = userList;
          }
      
          @Override
          public String toString() {
              return "VO{" +
                      "userList=" + userList +
                      '}';
          }
      }
      
      @ResponseBody
      public void test(VO vo){
          System.out.println(vo);
      }
      
  6. @RequestParam

    • 作用:将请求参数映射到方法参数上,支持请求体与url?后的参数
    • 位置:方法参数位置
    • 属性:
      • value:请求参数名
      • required:指定请求参数是否必须包括,默认为true,提交时若没有此参数会报错
      • defaultValue:当没有指定参数时,则使用指定的默认值赋值,注意该设置可以抵消客户端未指定参数而服务器设置了required=true产生的错误
  7. 获得Restful风格的参数

    • 什么是Restful风格?

      Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁、更有层次、更易于实现缓存机制等

    • Restful风格的请求是使用“url+请求方式”表示一次请求目的的,HTTP协议里面四个表示操作方式的动词如下:

      • GET:获取资源
      • POST:新建资源
      • PUT:更新资源
      • DELETE:删除资源
    • 例如

      image-20210212122853469

    • 使用@PathVariable获取url携带的参数

      @RequestMapping("/test/{name}")
      @ResponseBody
      public void test(@PathVariable(value = "name",required = true) String username){
          System.out.println(username);
      }
      
  8. 自定义类型转换器

    • SpringMVC默认提供了一些常用的类型转换器,例如客户端提交的字符串转换成int类型。但并不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据

    • 自定义类型转换器的开发步骤:

      • 定义转换器类并实现Converter接口

        //将字符串转为Date对象
        public class DateConverter implements Converter<String, Date> {
            @Override
            public Date convert(String dateStr) {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                Date date = null;
                try {
                    date = format.parse(dateStr);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return date;
            }
        }
        
      • 在spring-mvc.xml配置文件中声明转换器

        <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <list>
                    <bean class="pers.zero.converter.DateConverter"/>
                </list>
            </property>
        </bean>
        
      • 在<annotation-driven>中引用转换器

  9. 获得原生request、response、session

    public void test(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);
    }
    
  10. 获得请求头信息

    通过 @RequestHeader注解

    public void test(@RequestHeader(value = "User-Agent",required = false) String useragent){
        System.out.println(useragent);
    }
    

    特殊:通过@CookieValue获得指定cookie

    public void test(@CookieValue(value = "JESSIONID",required = false) String jessionId){
    	System.out.println(jessionId);
    }
    
  11. 文件上传

    • 客户端文件上传三要素

      • 表单项type=“file”
      • 表单的提交方式是post
      • 表单的enctype属性是多部分表单形式,及enctype=“multipart/form-data”
    • 文件上传原理

      • 当form表单修改为多部分表单时,request.getParameter()将失效

      • enctype默认值是"application/x-www-form-urlencoded",此时表单提交时请求体以键值对形式存储数据,key=value&key=value

      • 当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就变成多部分形式:

        image-20210212162502020

    • 文件上传步骤

      • 导入fileupload和io坐标

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
        </dependency>
        
      • 在spring-mvc.xml中配置文件上传解析器

        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- 上传总文件的最大大小 -->
            <property name="maxUploadSize" value="5242800"/>
            <!-- 上传单个文件的最大大小 -->
            <property name="maxUploadSizePerFile" value="5242800"/>
            <property name="defaultEncoding" value="UTF-8"/>
        </bean>
        
      • 编写文件上传代码

        <!-- 客户端表单 -->
        <form action="${pageContext.request.contextPath}/user/test14" method="post" enctype="multipart/form-data">
            名称:<input type="text" name="username"><br/>
            文件1:<input type="file" name="uploadFiles"><br/>
            文件2:<input type="file" name="uploadFiles"><br/>
            <input type="submit" value="提交">
        </form>
        
        //服务器转存文件代码
        @ResponseBody
        public void test(String username, MultipartFile[] uploadFiles) throws IOException {  //注意要与input元素名字一致
            System.out.println(username);
            for(MultipartFile file:uploadFiles){
                //获得上传文件名称
                String originalFilename = file.getOriginalFilename();
                //将文件转存到磁盘
                file.transferTo(new File("E:\\program\\Java\\05_ssm\\spring_web_mvc\\upload\\"+originalFilename));
            }
        }
        

SpringMVC拦截器

  1. 拦截器(interceptor)的作用

    SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理后处理

    将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(interceptor chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

  2. 拦截器和过滤器的区别

    比较项目过滤器拦截器
    使用范围是servlet规范中的一部分,任何Java Web工厂都可以使用是SpringMVC自己的,只有使用了SpringMVC框架的工程才能用
    拦截范围在url-pattern中配置/*之后,可以对所有要访问的资源进行拦截只会拦截访问的控制器方法,如果访问的是jsp、html、css等是不会进行拦截的
  3. 开发流程

    • 创建拦截器类并实现HandlerInterceptor接口

      public class MyInterceptor1 implements HandlerInterceptor {
          //在目标方法执行之前执行
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              System.out.println("preHandle...");
              String param = request.getParameter("param");
              if("yes".equals(param)){    //注意将"yes"写在前面,否则如果没有带param参数的话会空指针异常
                  return true;
              }else {
       		request.getRequestDispatcher("/jsp/error.jsp").forward(request,response);
                  return false;   //若返回false,不会继续执行目标方法
              }
          }
          //在目标方法执行之后、视图返回之前执行
          @Override
          public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
              //常用于修改响应参数
              modelAndView.addObject("name","拦截器");
              System.out.println("postHandle...");
          }
          //在整个流程都执行完毕之后执行
          @Override
          public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
              System.out.println("afterCompletion...");
          }
      }
      
      public class MyInterceptor2 implements HandlerInterceptor {
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              System.out.println("preHandle2...");
              return true;
          }
      
          @Override
          public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
              System.out.println("postHandle2...");
          }
      
          @Override
          public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
              System.out.println("afterCompletion2...");
          }
      }
      
    • 在spring-mvc.xml中配置拦截器

      <mvc:interceptors>
      <!-- 注意:先配置的拦截器先执行preHandle,后执行postHandle与afterCompletion,栈出入 -->
          <mvc:interceptor>
              <!-- 对哪些资源执行拦截操作,相当于切点 -->
              <mvc:mapping path="/**"/>
              <!-- 对登录操作不进行拦截 -->
              <mvc:exclude-mapping path="/user/login"/>
              <bean class="pers.zero.interceptor.MyInterceptor1"/>
          </mvc:interceptor>
          <mvc:interceptor>
              <mvc:mapping path="/**"/>
              <bean class="pers.zero.interceptor.MyInterceptor2"/>
          </mvc:interceptor>
      </mvc:interceptors>
      
    • 测试拦截器的拦截效果

      preHandle…
      preHandle2…
      目标资源正在执行
      postHandle2…
      postHandle…
      afterCompletion2…
      afterCompletion…

  4. 拦截方法总结

    image-20210212202258281

  5. 拦截器路径

    • /**的意思是所有文件夹及里面的子文件夹
    • /*是所有文件夹,不含子文件夹
    • /是web项目的根目录
  6. 拦截器作用范围

    • 拦截器只拦截@Controller注解的类和方法,对于jsp没有拦截
    • 另外需要注意的是,拦截器是会拦截静态资源的 比如html js css image这类

SpringMVC异常处理

  1. SpringMVC异常处理机制

    系统的Dao、Service、Controller出现的异常都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理,如下图:

    image-20210215110313039

  2. 异常处理的两种方式

    • 使用SpringMVC提供的简单异常处理器SimpleMappingExceptionResolver
    • 使用Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器
  3. 简单异常处理器SimpleMappingExceptionResolver(只需要进行页面跳转时推荐使用这种)

    <!-- 配置异常处理器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 设置异常跳转视图,受前后缀影响 -->
        <!-- 默认异常跳转视图,异常无法与其余配置匹配时跳转到该视图 -->
        <property name="defaultErrorView" value="error"/>
        <!-- 特定异常跳转视图 -->
        <property name="exceptionMappings">
            <map>
                <entry key="java.lang.ClassCastException" value="castError"/>
                <entry key="pers.zero.exception.MyException" value="myError"/>
            </map>
        </property>
    </bean>
    
  4. 自定义异常处理(这种操作更加灵活)

    • 创建异常处理器并实现HandlerExceptionResolver

      public class MyExceptionResolver implements HandlerExceptionResolver {
          @Override
          public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
              ModelAndView modelAndView = new ModelAndView();
              if(e instanceof MyException){
                  modelAndView.addObject("info","自定义异常");
              }else if(e instanceof ClassCastException){
                  modelAndView.addObject("info","类型转换异常");
              }else {
                  modelAndView.addObject("info","其余异常");
              }
              modelAndView.setViewName("error1");
              return modelAndView;
          }
      }
      
    • 配置异常处理器

      <!-- 自定义异常处理器 -->
      <bean class="pers.zero.resolver.MyExceptionResolver"/>
      
    • 编写异常页面

    • 测试异常跳转

总结与扩展

  1. 前置控制器的url-pattern

    • /:表示匹配所有请求(其中包含除.jsp和.jspx外的所有后缀,至于为什么不会匹配到.jsp和.jspx,是因为Tomcat在web.xml中设置了*.jsp与*.jspx的servlet映射,其精度比/高,会覆盖掉/对应的映射),/的意义在于符合restful风格,restful风格的请求不能有后缀,需要像 /user/name这种,需要配置静态资源:mvc:resources或mvc:default-servlet-handler/或Tomcat的web.xml中配置DefaultServlet。
    • /*:表示匹配所有请求(包含所有后缀),这里*.jsp比"/*"的匹配度低,所以配置后会使.jsp也进入DispatcherServlet,而*.jsp既不是控制器路径也不是静态资源,所以就算配了静态资源还是访问不到,所以这个/*的配置不适用于DispatcherServlet,一般用于过滤器来拦截所有资源
    • *.do:表示匹配所有以.do结尾的请求,只匹配.do结尾的请求,不会匹配到静态资源,静态资源可以被直接访问,省去了配置静态资源的麻烦,但不适用于restful风格
  2. SpringMVC执行流程(微观)

    image-20210210161820702

    image-20210210162224403

  3. SpringMVC三大组件:处理器映射器、处理器适配器、视图解析器,其中处理器映射器与处理器适配器可以使用注解方式配置,只需在spring-mvc.xml中使用<mvc:annotation-driven>,并且该配置默认底层就会集成jackson进行对象或集合的json格式字符串的转换

  4. 源码分析

    • 前端控制器配置文件路径:\org\springframework\web\servlet\DispatcherServlet.properties
  5. 注解

    • @RestController

      • 作用:相当于@ResponseBody+@Controller,方法会直接以方法指定的格式(一般通过XxxMapping的produces指定)将数据封装到响应后返回,一般用于前后端分离
      • 位置:类上
      • 注意:这样做无法再实现使用return进行转发与重定向
    • @RequestMapping

      • 作用:用于建立请求URL和处理请求方法之间的对应关系
      • 位置:
        • 类上:请求URL的第一级访问目录。此处不写的话,就相当于应用的根目录
        • 方法上:请求URL的第二级访问目录,与类上的一级目录一起组成访问虚拟路径
      • 属性:
        • value:用于指定请求的URL,与path作用相同
        • method:用于指定请求的方法。值是枚举类型RequestMethod.xxx
        • params:用于指定限制请求参数的条件。它支持简单的表达式,要求请求参数的key和value必须和配置的一模一样,例如
          • params = {“accountName”},表示请求参数必须有accountName
          • params = {“money!100”},表示请求参数中money不能是100
        • produces:指定响应数据类型,例如application/json;charset=UTF-8
        • consumes:指定处理请求的提交内容类型(Content-Type),例如application/json;表示该controller只能处理请求体为json格式数据的请求
    • @PostMapping、@GetMapping、@DeleteMapping等:相当于指定了method的@RequestMapping

    • @ResponseBody

      • 作用:表明直接返回数据而不是跳转
      • 位置:方法上
    • @RequestBody

      • 作用:将客户端返回的json格式数据直接封装到参数中

      • 位置:方法参数位置

      • 注意:

        • @RequestBody注解的形参只能有一个

        • @RequestBody只有在注释POJO时才会自动将数据封装到POJO属性(只推荐在这种情况下前端传递json数据)

        • @RequestBody在注释String类型参数时,会将整个json字符串原封不动的赋值,

          例如:客户端传递{“num”:“123456”},服务端@RequestBody String num,那么打印num会得到{“num”:“123456”}

        • @RequestBody在注释int等类型参数时,若传递标准json字符串,将会报错

          例如:客户端传递{“num”:“123456”},服务端@RequestBody int num,那么将产生400响应

        • 对于String、int等类型使用@RequestBody,有个奇怪的方法可以自动注解:不使用{}与key,直接传值,例如:客户端传递123456,服务端@RequestBody int num,那么num=123456

    • @RequestParam

      • 作用:将请求参数映射到方法参数上,支持请求体与url?后的参数
      • 位置:方法参数位置
      • 属性:
        • value:请求参数名
        • required:指定请求参数是否必须包括,默认为true,提交时若没有此参数会报错
        • defaultValue:当没有指定参数时,则使用指定的默认值赋值,注意该设置可以抵消客户端未指定参数而服务器设置了required=true产生的错误
    • @ModelAttribute

      • 位置与作用
        • 方法上:在该controller的@requestMapping方法前调用,用于处理model
        • 方法参数:将model的指定属性注入到参数
    • @PathVariable

      • 作用:将url携带的参数映射到方法参数上,支持url/param格式

      • 位置:方法参数位置

      • 属性:

        • value:请求参数名
        • required:指定请求参数是否必须包括,注意:设置为false的功能是在path不携带时将参数设置为null,因此不要使用int等基本类型,而要改用其包装类
      • 示例

        @RequestMapping("/test/{name}")
        @ResponseBody
        public void test(@PathVariable(value = "name",required = true) String username){
            System.out.println(username);
        }
        
    • @RequestHeader

      • 作用:将请求头的参数映射到方法参数上
      • 位置:方法参数位置
      • 属性:
        • value:请求头参数名
        • required:指定请求参数是否必须包括
    • @CookieValue

      • 作用:将指定的Cookie值映射到方法参数上
      • 位置:方法参数位置
      • 属性:
        • value:指定Cookie名
        • 是否必须携带此Cookie
  6. spring-mvc.xml配置

    • spring-mvc.xml与applicationContext.xml的区别:

      • spring-mvc.xml是SpringMVC使用的,主要记载了MVC相关组件的配置(包括controller的扫描)
      • applicationContext.xml是我们自己使用的,主要记载了Model相关配置(如dao层、service层的bean、切面等等)
    • 配置组件扫描(用于扫描@Controller)

      <context:component-scan base-package="pers.zero.controller"/>
      
    • 配置mvc注解驱动

      <
      mvc:annotation-driven
      conversion-service="conversionService"	<!-- 转换器服务(工厂方法) -->
      />
      
    • 开放资源的访问权限(一般为静态资源,使浏览器可以通过url访问到资源)

      <!-- 第一种方式,若springmvc无法找到对应资源,交由Tomcat等容器来处理 -->
      <mvc:default-servlet-handler/>
      
      <!-- 第二种方式 -->
      <mvc:resources mapping="/js/**" location="/js/"/>
      <mvc:resources mapping="img/**" location="/img/"/>
      
    • 配置配置视图解析器

      <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
          <!-- 这样配置后跳转到jsp文件只需写jsp文件名 -->
          <!-- 注意重定向不会经过视图解析器,故使用重定向时需要手动添加前缀后缀 -->
          <property name="prefix" value="/jsp/"/>	<!-- 视图名称前缀 -->
          <property name="suffix" value=".jsp"/>	<!-- 视图名称后缀 -->
      </bean>
      
    • 配置拦截器

      <mvc:interceptors>
      <!-- 注意:先配置的拦截器先执行preHandle,后执行postHandle与afterCompletion,栈出入 -->
          <mvc:interceptor>
              <!-- 对哪些资源执行拦截操作,相当于切点 -->
              <mvc:mapping path="/**"/>
              <bean class="pers.zero.interceptor.MyInterceptor1"/>
          </mvc:interceptor>
          <mvc:interceptor>
              <mvc:mapping path="/**"/>
              <bean class="pers.zero.interceptor.MyInterceptor2"/>
          </mvc:interceptor>
      </mvc:interceptors>
      
    • 配置简单异常处理器(也可使用自定义异常处理器)

      <!-- 配置简单异常处理器 -->
      <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
          <!-- 设置异常跳转视图,受前后缀影响 -->
          <!-- 默认异常跳转视图,异常无法与其余配置匹配时跳转到该视图 -->
          <property name="defaultErrorView" value="error"/>
          <!-- 特定异常跳转视图 -->
          <property name="exceptionMappings">
              <map>
                  <entry key="java.lang.ClassCastException" value="castError"/>
                  <entry key="pers.zero.exception.MyException" value="myError"/>
              </map>
          </property>
      </bean>
      
    • 配置文件上传解析器

      <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
          <!-- 上传总文件的最大大小 -->
          <property name="maxUploadSize" value="5242800"/>
          <!-- 上传单个文件的最大大小 -->
          <property name="maxUploadSizePerFile" value="5242800"/>
          <property name="defaultEncoding" value="UTF-8"/>
      </bean>
      
    • 配置处理器适配器

      <!-- 配置处理器适配器 -->
      
      <!-- 使用这一句话就可使得@ResponseBody注解的方法返回对象/数组时自动转换成json字符串 -->
      <mvc:annotation-driven/>
      
      <!--
      <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
          <property name="messageConverters">
              <list>
      			配置:返回对象/数组会自动转换成json字符串
                  <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
              </list>
          </property>
      </bean>
      -->
      
    • 声明转换器(一般用于将请求的字符串参数转为对应对象)

      <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
          <property name="converters">
              <list>
                  <bean class="pers.zero.converter.DateConverter"/>
              </list>
          </property>
      </bean>
      
  7. web.xml配置

    • 配置spring-web(用于获取applicationContext)

      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:applicationContext.xml</param-value>
      </context-param>
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      
    • 前端控制器

      <servlet>
          <servlet-name>DispatcherServlet</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <init-param>
              <!-- mvc相关上下文 -->
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:spring-mvc.xml</param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
          <servlet-name>DispatcherServlet</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
      
    • 编码过滤器(不配置的话POST会中文乱码,GET不会)

      <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>
      

参考:2020年IDEA版黑马Java就业班-进阶篇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值