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("完成方法");
    }
}

  

    

 

  

 

posted @ 2018-01-07 13:29  张小铁  阅读(167)  评论(0编辑  收藏  举报