zoukankan      html  css  js  c++  java
  • SpringMVC

    SpringMVC

     SpringMVC的几大组件

      1、前端总控制器:用于接受、处理请求,对其他各个组件进行调度。

      2、处理器映射器(Handler Mapping):根据请求url找到具体的处理器,生成处理器对象以及处理器拦截器(如果有则生成)一并返回给DispatherServlet(HandlerExecutionChain执行链)

      3、处理器适配器(Handler Adapter):DispatherServlet通过HandlerAdapter处理器适配器调用处理器,找到对应的处理器。然后将ModelAndView(Model  数据和view 名)给前端总控制器

      4、视图解析器(ViewResolver):将逻辑视图转化为真正的视图,然后在前端控制器处将数据和页面结合返回给请求的用户(返回静态页面)

       

    SpringMvc所需jar包

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.16</version>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>${jackson.version}</version>
            </dependency>
            <!--jsp相关-->
            <dependency>
                <groupId>jstl</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl.version}</version>
            </dependency>
    
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <scope>provided</scope>
            </dependency>
    <!--provided有服务器提供,tomcat而且部署的时候同样不会打包-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jsp-api</artifactId>
                <scope>provided</scope>
            </dependency>

       

      DispatcherServlet是一个servlt。servlet在第一次被访问的时候创建的,后面就不会再创建了。

      

    <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--服务器启动的时候,初始化springmvc中的DispatherServlet-->
    <load-on-startup>1</load-on-startup>
    </servlet>

     

    上图为handlerMapping拿到执行链,

     interceptorList=ArrayList<E>(id=1067)  :拦截器的集合

    在xml文件中可以不添加映射器和适配器因为在webmvc的代码中,DispatcherServlet.properties配置文件中含有

      

    org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

    org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

      BeanNameUrlHandlerMapping和SimpleControllerHandlerAdapter为处理器映射器和处理器适配器。

    但是这两个类被淘汰了,可以使用

    <mvc:annotation-driven />这行代码可以自动加载替代上面两个类的新类,以及JSON转换器


    2、注解开发

    由于springmvc注解开发更加简洁而且如果不适用注解,每个类都需要实现Controller接口,但是这样的话注册到spring容器中时,该类只能绑定一个路径,springmvc是方法级别的,
    一个方法对应一个请求,这样极大的降低了开发效率。
      而使用注解开发只需要在类上添加
    @Controller
    @RequestMapping(value = "hello")
    

     即可标识,已将该类添加到了spring容器,而且可以指定一个路径到该类,而再在类中的各个方法前添加

    @RequestMapping(value = "/i18n")即可标识hello/i18n.html的请求会到含有in18n的方法上。
    是否添加/无所谓

    ANT风格开发,即通配符。

    通配符

    说明

    ?

    匹配任何单字符

    *

    匹配0或者任意数量的字符

    **

    匹配0或者更多的目录


    其中

    @RequestMapping("/test/*/show") 

    *代表可以填写任意字符,但是不可以写/test/show.html

    **则既可以使用**代表任意字符,也可以使用/test/show.html

    <context:component-scan base-package="com.back.controller"/>    //开启注解扫描,以扫描那些类开启了注解
    视图配置
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"/> <!-- 视图前缀 -->
    <property name="suffix" value=".jsp" /> <!-- 视图后缀 -->
    </bean>
    可以不用每个路径都添加前缀和后缀
    限定请求方式和请求参数
      限定只能使用GET方式请求:
     @RequestMapping(value = "/show",method = RequestMethod.GET)
    

      即可使用GET也可以使用POST

    @RequestMapping(value = "/show",method = {RequestMethod.GET,RequestMethod.POST})
    

      限定请求参数

    @RequestMapping(value = "/show",params = "userId")
    

      请求参数必须含有userId

    params=“userId”;请求参数必须含有userId

    params=“!userId”;请求参数不能含有userId

    params=“userId!=1”;请求参数必须包含userId,但是其值不能为1

    params={"userId","userName"} 请求参数必须包含userId和userName参数


    3、处理方法好参数绑定
    3.1  绑定servlet内置对象
        
        @RequestMapping(value = "/hello.do")
        public ModelAndView welcome(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
            ModelAndView mv = new ModelAndView("welcome");
            mv.addObject("msg","sdfasfsaf");
            mv.getModel().put("name","张小娴");
            return mv;
        }
    

      一般常用的有request、response和session

    3.2  获取请求连接中的值 @PathVariable(获取路径中的占位符的值)

        @RequestMapping(value = "test/{id}/show")
        public ModelAndView test4(@PathVariable("id")String id){
            ModelAndView mv=new ModelAndView("welcome");
            mv.addObject("msg","占位符id"+id);
            System.out.println(id);
            return  mv;
        }
    

      将请求路径中的{id}传入到id参数。其中@PathVariable("id")的id不可省去,不添加的时候它是由IDE工具自动添加到类中,但是发布的时候并不能保证可以传入class中。

      {id}  这里表示可以输入任何字符都可以被@PathVariable("id")获取到

    3.3    @RequestParam

        @RequestMapping(value = "test/{uri}/show")
        public ModelAndView test4(@RequestParam(value = "username",required = false,defaultValue = "012")String username){
            ModelAndView mv=new ModelAndView("welcome");
            System.out.println(username);
            mv.addObject("username",username);
            return  mv;
        }
    

      

    @RequestParam有三个参数1、value:参数名    2、required:是否必须(当有defaultValue时,该参数无效,以defaultValue为准 3、defaultValue默认参数值)
    3.4POJO对象绑定参数
      即将User user当成参数传入进来,然后在地址栏输入属性例:userName=zhangsan; 会自动匹配到user.userName
    3.5Java基本数据类型绑定
      Spring对Java的基本数据类型支持非常多,基本满足开发需要。
      
        @RequestMapping(value = "/show")
        @ResponseStatus(value = HttpStatus.OK)
        public ModelAndView test4(@RequestParam("name")String name,@RequestParam(value = "age")Integer age){
            ModelAndView mv=new ModelAndView("welcome");
            mv.addObject("username","李大庄");
            System.out.println(age);
            return  mv;
        }
    

      

    <form action="/demos/demo1.action" method="post">
    	<div>姓名:</div>
    	<div><input name="name" value="张三"/></div>
    	<div class="clear"></div>
    

      @RequestParam可以添加页面上的name属性的值给name

    @ResponseStatus(value = HttpStatus.OK)直接返回一个结果表示200OK。
    3.6 session对象的创建时机

    第一次获取session对象,或者访问一个jsp页面,内置对象有session也会创建session。
    3.7 集合List绑定
      List无法直接作为参数去接受数据,如下代码
        @RequestMapping(value = "/show")
        @ResponseStatus(value = HttpStatus.OK)
        public ModelAndView test4(List<User> user){
            ModelAndView mv=new ModelAndView("welcome");
            mv.addObject("username",user);
            return  mv;
        }
    

      数组如果是POJO类型的数据也是不可以直接接收参数的

    一定要将List<User>当做一个包装类的属性才行

    public class UserForm {
        private List<User> users;
    
        public List<User> getUsers() {
            return users;
        }
    
        public void setUsers(List<User> users) {
            this.users = users;
        }
    }
    

      例如:

        @RequestMapping(value = "/show")
        @ResponseStatus(value = HttpStatus.OK)
        public ModelAndView test4(UserForm userForm){
            ModelAndView mv=new ModelAndView("welcome");
            mv.addObject("username",123);
            if (userForm.getUsers()!=null){
                for (User user:userForm.getUsers()) {
                    System.out.println(user);
                }
            }
            return  mv;
        }
    

      像以上这种方式即可接收参数。

    前端页面代码:

        <form action="/show.do">
            用户1:<input type="text" name="users[0].username"><br>
            用户2:<input type="text" name="users[1].username"><br>
            用户3:<input type="text" name="users[2].username"><br>
            <button type="submit">提交</button>
        </form>
    

     

    包括如果不是List<User> user,而是User[]user数组;也需要弄到包装类里。

    public class UserForm {
        private User[] users;
    
        public User[] getUsers() {
            return users;
        }
    
        public void setUsers(User[] users) {
            this.users = users;
        }
    }
    

    Controller代码不变

    4、SpringMVC和Struts的区别

      4.1、SpringMVC核心是servlet,Struts是Filter

      4.2、接收参数模式不一样 springmvc接收参数是在方法上,Struts2是定义成员变量。

      4.3、Struts2返回值类型只能是string,springmvc可以返回多种类型

      4.4、Struts2是多例的,springmvc是单例的。如果一个类是单例的,那么类中的属性,是所有人都共享的。

    springmvc把所有的参数都绑定到方法上,运行的时候会为每一个方法开辟一个新的方法区,变量是自己的。没调用一次方法就会生成一个方法区,都会有一个新的方法区。没有

    冲突的地方。

        springmvc性能更高,单例的。节省内存空间,单例的。不会开辟多余的内存空间。多个方法之间不能共享。

    5、JSP和JSTL视图解析器

      JSTL需要导入一个jar包   jstl-version.jar

    在jsp页面头上添加:

    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    

      用foreach循环

                  <c:forEach items="${users}" var="user">
                    <tr>
                            <td>${user.id}</td>
                            <td>${user.username}</td>
                    </tr>
                  </c:forEach>
    

      Controller类

        @RequestMapping(value = "/show")
        @ResponseStatus(value = HttpStatus.OK)
        public ModelAndView test4(){
            ModelAndView mv=new ModelAndView("welcome");
            User user=new User();
            user.setId(12);
            user.setUsername("张三");
            User user1=new User();
            user1.setId(32);
            user1.setUsername("李四");
            List<User> users=new ArrayList<User>();
            users.add(user);
            users.add(user1);
            mv.addObject("users",users);
            return  mv;
        }
    

      

    6、使用ResponseBody输出JSON

     在实际开发过程中返回JSON是最为常见的一种方式,所以SpringMVC提供了一种更为简便的方式输出数据。就是使用@ResponseBody注解。

     依赖包:jackson-annotation、jackson-core、jackson-databind

        @RequestMapping(value = "/show")
        @ResponseBody
        public List<User> test4(){
            ModelAndView mv=new ModelAndView("welcome");
            User user=new User();
            user.setId(12);
            user.setUsername("张三");
            User user1=new User();
            user1.setId(32);
            user1.setUsername("李四");
            List<User> users=new ArrayList<User>();
            users.add(user);
            users.add(user1);
            mv.addObject("users",users);
            return  users;
        }
    

      添加了@ResponseBody就会将返回的结果当成响应体进行输出。springmvc会调用一个messageConvertor去把returnvalue进行数据输出,默认会去调用json去处理数据。

      1、springmvc要处理json,需要依赖jackson工具类

      2、messageConvertor:消息转换器,把请求中的内容转换成java的数据格式,把java的数据格式转换成响应的内容

      3、当方法上面标识了@ResponseBody之后,springmvc使用的消息转换器,默认使用jackson的消息转换器。

      4、springmvc有很多的转换器,在注解驱动的类里面,如果它发现了jackson的工具类才会把jackson的massegeConvertor添加到springmvc中。

    7、RequestBody请求体,处理接收的json格式的数据

      依赖springmvc.xml中的

    mvc:annotation-driven />
    public ModelAndView test4(@RequestBody User user)
    

      将json格式转换成user对象

        @RequestMapping(value = "/show")
        public ModelAndView test4(@RequestBody List<User> users){
            ModelAndView mv=new ModelAndView("welcome");
            if(users!=null){
                for (User user:users){
                    System.out.println(user);
                }
            }
            return  mv;
        }
    

    8、转发和重定向

      如果Controller的返回值是String,那么它返回的是视图名称。

      如果是

    ModelAndView mv = new ModelAndView("redirect:/welcome");表示转发到这个路径下
    ModelAndView mv = new ModelAndView("forward:/hello/welcome.do");  //重定向该路径

     9、拦截器

      MappingHandler被调用返回给DispatcherServlet一个HandlerExecutionChain,这其中包含了Handler对象和Intercptor(拦截器)对象。

        <!--对拦截器进行配置-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--定义所有请求都进入拦截器-->
                <mvc:mapping path="/**"/>
                <bean class="com.back.interceptor.MyHandlerInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>
    

      拦截器类实现HandlerInterceptor接口。

       

    public class MyHandlerInterceptor implements HandlerInterceptor {
    
        /**
         *前置方法:从前向后执行
         * 在执行Handler前执行
         *返回值:true:继续向下执行
         *      false:终止执行
         */
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            System.out.println("前置方法");
            return true;
        }
    
    
        /**
         * 后置方法,执行完handler之后执行,从后向前执行
         * 如果前置方法返回false:整个拦截器中的所有的后置方法都不再执行
         *
         * */
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            System.out.println("后置方法");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            System.out.println("完成方法");
        }
    }
    

      

        

      

     

    坚持就是胜利
  • 相关阅读:
    MISP版本嵌入式QT编译时出现mips-linux-gcc command not found
    数据传输对象(DTO)介绍及各类型实体比较
    signalR例子
    WebAPI GET和POST请求的几种方式
    github教程
    Asp.net MVC + EF + Spring.Net 项目实践3
    SpringMVC
    SignalR
    SignalR的实时高频通讯
    开发视频教程
  • 原文地址:https://www.cnblogs.com/xiaotieblog/p/8227866.html
Copyright © 2011-2022 走看看