zoukankan      html  css  js  c++  java
  • day63_SpringMVC学习笔记_01

    1、JAVAEE体系结构

    • JAVAEE体系结构图如下所示:

    2、什么是springmvc?

    • 什么是mvc?
      • Model1
      • Model2
    • SpringMVC是什么?
      • SpringMVC是一个web层mvc框架,类似struts2。
    • SpringMVC和Spring?
      • Springmvc是Spring的组成部分。
    • SpringMVC执行流程(运行原理)
      • 回忆Struts2执行流程:
        • 前端控制器:StrutsPrepareAndExcuteFilter拦截请求(控制层):拦截请求,转发请求
        • 寻找Action执行,处理请求数据
        • ActionMapping去寻找执行类Action --> UserAction
        • 找到ActionProxy:StrutsActionProxy extends DefaultActionProxy
        • 通过代理类ActionProxy根据struts.xml寻找到真正的执行类Action
      • SpringMVC执行流程(运行原理),如下图所示:

    3、springmvc第一个程序案例

    3.1、不使用jsp视图解析器+使用jsp视图解析器

    (1)使用eclipse,创建一个动态的web工程
      其中Dynamic web module version版本选择 2.5,这样兼容性好一些;
      Default output folder设置为 WebRootWEB-INFclasses
      Content directory设置为 WebRoot
      更改JRE System Library[J2SE-1.5]为 JRE System Library[jre1.7.0_80]
      删掉没用的库:EAR Libraries
      增加服务器运行环境库 Server Runtime,不然jsp文件会报错。


      创建完项目后,将整个项目的编码改为UTF-8。
      操作步骤:选中项目右键 --> Properties --> Resource --> Text file encoding --> Other中选择UTF-8。

      对于动态的java web项目,为了工程目录结构的清爽,我们将引入的jar包放到“Web App Libraries”中,可以通过“小三角”选择是否“Show 'Referenced Libraries' Node ”进行调节。
      对于普通的java项目,为了工程目录结构的清爽,我们将引入的jar包放到“Referenced Libraries”中,可以通过“小三角”选择是否“Show 'Referenced Libraries' Node ”进行调节。

    (2)导入springmvc的jar包
      本案例共16个jar,如下图所示:

    (3)在web.xml配置前端控制器:DispatcherServlet(入口)

        <!-- 配置前端控制器:DispatcherServlet -->
        <servlet >
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>

      我们还需要配置springmvc.xml文件的初始化参数,如下图所示:

    (4)配置springmvc.xml
      参考文件位置:spring-framework-3.2.0.RELEASEdocsspring-framework-referencehtmlxsd-config.html

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.2.xsd 
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "
    >

        <!-- 配置处理器映射器,springmvc默认的处理器映射器 -->
        <!-- BeanNameUrlHandlerMapping:根据bean(自定义的Controller)的name属性的url去寻找执行类Handler(Action)即Controller -->
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>

        <!-- 配置处理器适配器,负责执行Controller,也是springmvc默认的处理器适配器 -->
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>

        <!-- 配置自定义的Controller:UserController -->
        <bean name="/hello.do" class="com.itheima.controller.UserController"></bean>

        <!-- 配置jsp视图解析器,InternalResourceViewResolver负责解析出真正的逻辑视图 -->
        <!-- 后台返回逻辑视图:index,jsp视图解析器解析出真正的物理视图:前缀+逻辑视图+后缀 ==>/WEB-INF/jsps/index.jsp -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsps/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    </beans>

    (5)自定义Controller(相当于Struts2里面的Action)

    public class UserController implements Controller {

        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            // 接收请求,接收参数,验证参数,处理请求
            // 封装参数,调用业务方法,返回处理结果数据ModelAndView

            // 演示案例中我们只模拟下而已:向前台返回数据
            ModelAndView mv = new ModelAndView();
            mv.addObject("hello""like xiaoyi");

            // 指定跳转的视图
            // 返回真实的物理视图,省略了8、9步
            // mv.setViewName("/WEB-INF/jsps/index.jsp");
            // 返回逻辑视图
            mv.setViewName("index");

            return mv;
        }
    }

    (6)定义视图页面
      根据视图解析路径:WEB-INF/jsps/index.jsp

    <body>
        <h1>${hello}</h1>
    </body>

    (7)浏览器访问
      访问地址:http://localhost:8080/day63_SpringMVC_01/hello.do

    4、根据程序分析springmvc执行流程(画图)

    • 该图同SpringMVC执行流程图(运行原理)

    5、处理器映射器

    5.1、配置默认处理器映射器(BeanNameUrlHandlerMapping)

    功能:寻找Controller
       根据url请求去匹配bean的name属性url,从而获取Controller

    5.2、配置集中处理器映射器(SimpleHandlerMapping)

    功能:寻找Controller
       根据浏览器url匹配简单url的key,key通过Controller的id找到Controller

    5.3、配置类名处理器映射器(ClassNameHandlerMapping)

    功能:寻找Controller
       直接根据类名(UserController),类名.do来访问,类名首字母小写

    • 3个处理器映射器可以共存。均可以访问成功。

    6、处理器适配器

    6.1、配置默认处理器适配器(SimpleControllerHandlerAdapt)

    功能:执行Controller
       负责执行实现了Controller接口的后端控制器,例如:UserController,调用Controller里面的方法,返回ModelAndView。


    默认处理器适配器源码分析,如下图所示:

    6.2、配置请求处理器适配器(HttpRequestHandlerAdapter)

    功能:执行Controller
       负责执行实现了HttpRequestHandler接口的后端控制器。


    演示过程:
      自定义实现了接口HttpRequestHandler的实现类HttpController,如下图所示:

      在springmvc.xml中配置自定义的bean,即自定义的HttpController,如下图所示:

      上面的这种方式无限接近servlet的开发。
    • 2个处理器适配器可以共存。

    7、命令控制器

    7.1、Controller简介

    1、收集、验证请求参数并绑定到命令对象;
    2、将命令对象交给业务对象,由业务对象处理并返回模型数据;
    3、返回ModelAndView(Model部分是业务对象返回的模型数据,视图部分是逻辑视图名)。

    • 普通控制器(继承接口Controller,继承接口HttpRequestHandler)
    • 命令控制器(继承抽象类AbstractCommandController)
      • 例子:跳转到添加页面,进行页面跳转,参数提交get请求或者post请求
    • 参数控制器(类ParameterizableViewController)

    Springmvc通过命令设计模式接受页面参数。

    7.2、演示:自定义命令控制器

    示例如下:
    (1)自定义命令控制器

    package com.itheima.controller;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.springframework.validation.BindException;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.AbstractCommandController;

    import com.itheima.domain.User;

    // 从页面接收参数,封装到JavaBean中,本例中的JavaBean是User
    @SuppressWarnings("deprecation")
    public class CommandController extends AbstractCommandController {

        // 指定把页面传过来的参数封装到对象,使用命令设计模式
        public CommandController() {
            this.setCommandClass(User.class);
        }

        @Override
        protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command,
                BindException errors)
     throws Exception 
    {
            // 参数被封装进命令对象,这个过程很复杂,我们暂时不用管它,只要知道它使用的是命令设计模式即可

            // 把命令对象强转成User对象
            User user = (User) command;
            // 设置Model的数据,值可以是任意pojo
            ModelAndView mv = new ModelAndView();
            mv.addObject("user", user);
            // 指定返回页面
            mv.setViewName("index");

            return mv;
        }
    }

    (2)定义javaBean

    package com.itheima.domain;

    import java.util.Date;

    public class User {

        private Integer id;
        private String username;
        private String age;
        private Date birthday;
        private String address;

        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        public Date getBirthday() {
            return birthday;
        }
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
    }

    (3)封装参数页面
      文件位置:/day63_SpringMVC_01/WebRoot/WEB-INF/jsps/add.jsp
    add.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <form action="${pageContext.request.contextPath}/command.do" method="post">
            姓名:<input type="text" name="username" id="username"><br>
            年龄:<input type="text" name="age" id="age"><br>
            生日:<input type="text" name="birthday" id="birthday"><br>
            地址:<input type="text" name="address" id="address"><br>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    (4)获取参数页面
      文件位置:/day63_SpringMVC_01/WebRoot/WEB-INF/jsps/index.jsp
    index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <h1>${user.username}---${user.age}---${user.birthday}---${user.address}</h1>
    </body>
    </html>

    (5)跳转到add页面
      由于add页面在WEB-INF下面不能直接访问,需要通过Controller来访问。

    package com.itheima.controller;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;

    public class ToAddController implements Controller {

        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            // 跳转到add页面
            ModelAndView mv = new ModelAndView();
            mv.setViewName("add");

            return mv;
        }
    }

    (6)在springmvc.xml中配置bean

        <!-- 配置自定义的CommandController:CommandController -->
        <bean name="/command.do" class="com.itheima.controller.CommandController"></bean>

        <!-- 配置自定义的ToAddController:ToAddController -->
        <bean name="/toAdd.do" class="com.itheima.controller.ToAddController"></bean>

    7.3、中文乱码解决

    (1)解决get请求乱码
      配置tomcat的编码,如下图所示:


    (2)解决post请求乱码
      在web.xml中,配置spring编码过滤器,如下所示:
        <!-- 配置spring编码过滤器 -->
        <filter>
            <filter-name>characterEcoding</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>characterEcoding</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    7.4、时间类型转换

      在CommandController类中重写initBinder()方法,示例代码如下:

    // 从页面接收参数,封装到JavaBean中,本例中的JavaBean是User
    @SuppressWarnings("deprecation")
    public class CommandController extends AbstractCommandController {

        // 指定把页面传过来的参数封装到对象,使用命令设计模式
        public CommandController() {
            this.setCommandClass(User.class);
        }

        @Override
        protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
            // 参数被封装进命令对象,这个过程很复杂,我们暂时不用管它,只要知道它使用的是命令设计模式即可

            // 把命令对象强转成User对象
            User user = (User) command;
            // 设置Model的数据,值可以是任意pojo
            ModelAndView mv = new ModelAndView();
            mv.addObject("user", user);
            // 指定返回页面
            mv.setViewName("index");

            return mv;
        }

        @Override
        protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
            String str = request.getParameter("birthday");
            if (str.contains("/")) {
                binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy/MM/dd"), true));
            } else {
                binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
            }
        }
    }

    7.5、参数控制器ParameterizableViewController

      在springmvc.xml中配置参数控制器

    • 注意:使用参数控制器:不用自己定义Controller了,可以直接使用toIndex.do进行访问。

    8、注解开发

    8.1、注解开发第一个入门程序

    • 步骤如下:
      • 创建一个动态的web工程,导入jar文件
      • 配置web.xml
      • 配置springmvc.xml文件:配置处理器映射器、配置处理器适配器、配置jsp视图解析器
      • 自定义Controller类,使用注解开发:添加,返回到成功页面进行回显,点击修改回到添加页面,初步理解参数传递。

    (1)创建一个动态的web工程,导入jar文件
      详细过程同3、springmvc第一个程序案例
    (2)配置web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">

        <display-name>day63_SpringMVC_01</display-name>
        <!-- 配置spring编码过滤器 -->
        <filter>
            <filter-name>characterEcoding</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>characterEcoding</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

        <!-- 配置前端控制器:DispatcherServlet -->
        <servlet >
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- 隐式默认加载springmvc.xml文件,该文件需要满足2个规范:
                    命名规范:servlet-name-servlet.xml => springmvc-servlet.xml
                    路径规范:该文件必须放在WEB-INF目录下面
            -->

            <!-- 显示配置加载springmvc.xml文件,即配置springmvc.xml文件的初始化参数 -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>

        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
            <welcome-file>default.html</welcome-file>
            <welcome-file>default.htm</welcome-file>
            <welcome-file>default.jsp</welcome-file>
        </welcome-file-list>
    </web-app>

    (3)配置springmvc.xml文件
      配置扫描,把Controller交给spring管理、配置处理器映射器、配置处理器适配器、配置jsp视图解析器

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.2.xsd 
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "
    >

        <!-- 配置扫描,把Controller交给spring管理 -->
        <context:component-scan base-package="com.itheima"></context:component-scan>

        <!-- 配置注解的处理器映射器,作用:寻找执行类Controller -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>

        <!-- 配置注解的处理器适配器,作用:调用Controller方法,执行Controller -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>

        <!-- 配置jsp视图解析器,InternalResourceViewResolver负责解析出真正的逻辑视图 -->
        <!-- 后台返回逻辑视图:index,jsp视图解析器解析出真正的物理视图:前缀+逻辑视图+后缀 ==>/WEB-INF/jsps/index.jsp -->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsps/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
    </beans>

    (4)自定义Controller类

    @Controller // 相当于<bean id="userController" class="com.itheima.controller.UserController">,即相当于创建了一个UserController对象
    @RequestMapping("/user")
    public class UserController {
        // 请求映射注解
        @RequestMapping("hello") // 相当于访问/hello.do
        public String myHello() {
            // 表示springmvc返回了一个逻辑视图hello.jsp
            return "hello";
        }
    }

    (5)定义hello页面
      根据视图解析,需要在WEB-INF下面定义jsps文件夹,在里面定义一个hello.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <h1>欢迎访问SpringMVC</h1>
    </body>
    </html>

    (6)访问地址:http://localhost:8080/day63_SpringMVC_02/user/hello.do

    8.2、注解开发流程图

    注解开发流程图如下:

    8.3、RequestMapping

    功能:请求映射

    几种写法:
        @RequestMapping("hello") -- 这种方式可以匹配任何的扩展名
        @RequestMapping("/hello.do")
        @RequestMapping(value="/hello.do")
        @RequestMapping(value="/hello.do",method=RequestMethod.GET)
        @RequestMapping(value="/hello.do",method=RequestMethod.POST)
        @RequestMapping(value="/hello.do", method={RequestMethod.GET,RequestMethod.POST})

      浏览器直接访问、a标签都是get请求。
      表单提交(指定post)、ajax指定post提交。
      如果是get请求,写成了post浏览器会报405错误,如下图所示:

    8.4、RequestMapping的根路径

    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("save")
        public String save() {
        }
        @RequestMapping("update")
        public String update() {
        }
        @RequestMapping("find")
        public String find() {
        }
    }
    访问地址:http://localhost:8080/项目名/user/save.do

    @RequestMapping("/items")
    public class  ItemsController {
        @RequestMapping("save")
        public String save() {
        }
        @RequestMapping("update")
        public String update() {
        }
        @RequestMapping("find")
        public String find() {
        }
    访问地址:http://localhost:8080/项目名/items/save.do

    演示:自定义根路径

    @Controller // 相当于<bean id="userController" class="com.itheima.controller.UserController">,即相当于创建了一个UserController对象
    @RequestMapping("/user")
    public class UserController {
        // 请求映射注解
        @RequestMapping("hello") // 相当于访问/hello.do
        // @RequestMapping(value="/hello.do",method=RequestMethod.POST)
        public String myHello() {
            // 表示springmvc返回了一个逻辑视图hello.jsp
            return "hello";
        }
    }

    访问地址:http://localhost:8080/day63_SpringMVC_02/user/hello.do

    8.5、RequestParam

      value:参数名字,即入参的请求参数名字,如value="studentid"表示请求的参数区中的名字为studentid的参数的值将传入。
      required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码。
      defaultValue:默认值,表示如果请求中没有同名参数时的默认值
    示例如下:

    public String userList(@RequestParam(defaultValue="2",value="group",required=true) String groupid) {
    }
        1、形参名称为groupid,但是这里使用value="group"限定参数名为group,所以页面传递参数的名必须为group
        2、这里通过required=true限定groupid参数为必需传递,如果不传递则报400错误,由于使用了defaultvalue="2"默认值,即使不传group参数它的值仍为"2"
        3、所以页面不传递group也不会报错,如果去掉defaultvalue="2"且定义required=true,则如果页面不传递group就会报错。

    示例如下图所示:


      @RequestParam的作用:给传递的参数起别名。

    9、封装参数

    • springmvc没有成员变量,那页面提交过来的参数该如何接收和进行传递呢?
    • 答:把需要传递的参数对象放入方法里面,当你请求这个方法,向这个方法传递参数的时候,这个方法里面的对象会自动被创建,需要的参数会自动被封装到方法的对象里面。

    分析接受参数类型:

    基本类型
        intString等基本类型。
    Pojo类型
    包装类型
    集合类型

    Springmvc默认支持类型:
        HttpSession、HttpRequstServlet、Model等等。

    Struts2参数封装:基于属性驱动封装。
    Springmvc参数封装:基于方法进行封装。

    9.1、封装int类型参数

    • 页面传递的参数都是字符串。

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveInt.do" method="post">
            ID:<input type="text" name="id" id="id"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收int类型参数 
        @RequestMapping("recieveInt")
        public String recieveInt(Integer id) {
            System.out.println(id);
            return "success";
        }
    • 特别注意标签input的name的属性值id要与方法的形式参数名称id相同。

    9.2、封装String类型参数

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveString.do" method="post">
            姓名:<input type="text" name="username" id="username"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收String类型参数 
        @RequestMapping("recieveString")
        public String recieveString(String username) {
            System.out.println(username);
            return "success";
        }

    9.3、封装数组类型参数

    • 分析:封装数组是批量删除时使用,使用checkbox复选框,其value属性必须有值。

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveArray.do" method="post">
            ID:<input type="checkbox" name="ids" value="1" id="ids"><br>
            ID:<input type="checkbox" name="ids" value="2" id="ids"><br>
            ID:<input type="checkbox" name="ids" value="3" id="ids"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收数组类型参数 
        @RequestMapping("recieveArray")
        public String recieveArray(Integer[] ids) {
            System.out.println(ids);
            return "success";
        }

    9.4、封装pojo类型参数

    创建一个pojo类:

    public class User {

        private Integer id;
        private String username;
        private String age;
        private Date birthday;
        private String address;

        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
        public Date getBirthday() {
            return birthday;
        }
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", age=" + age + ", birthday=" + birthday + ", address="
                    + address + "]";
        }
    }

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveUser.do" method="post">
            姓名:<input type="text" name="username" id="username"><br>
            年龄:<input type="text" name="age" id="age"><br>
            生日:<input type="text" name="birthday" id="birthday"><br>
            地址:<input type="text" name="address" id="address"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收pojo类型参数 
        @RequestMapping("recieveUser")
        public String recieveString(User user) {
            System.out.println(user);
            return "success";
        }

    9.4、封装包装类型参数

    创建一个包装类:

    public class UserCustom {

        private User user;

        public User getUser() {
            return user;
        }

        public void setUser(User user) {
            this.user = user;
        }
    }

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveUserCustom.do" method="post">
            姓名:<input type="text" name="user.username" id="username"><br>
            年龄:<input type="text" name="user.age" id="age"><br>
            生日:<input type="text" name="user.birthday" id="birthday"><br>
            地址:<input type="text" name="user.address" id="address"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收包装类型参数 
        @RequestMapping("recieveUserCustom")
        public String recieveUserCustom(UserCustom userCustom) {
            System.out.println(userCustom);
            return "success";
        }

    9.5、封装集合类型参数

    9.5.1、封装List集合类型参数

    • 注意:不能直接传递集合类型,需要把集合类型封装到包装类中。

    我们先把List集合封装到包装类中。即:在包装类中定义List集合。提供getter和setter方法。

        private List<User> userList;

        public List<User> getUserList() {
            return userList;
        }

        public void setUserList(List<User> userList{
            this.userList = userList;
        }

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveList.do" method="post">
            姓名:<input type="text" name="userList[0].username" id="username"><br>
            年龄:<input type="text" name="userList[0].age" id="age"><br>

            姓名:<input type="text" name="userList[1].username" id="username"><br>
            年龄:<input type="text" name="userList[1].age" id="age"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收List结合类型参数 
        @RequestMapping("recieveList")
        public String recieveList(UserCustom userCustom) {
            System.out.println(userCustom);
            return "success";
        }

    9.5.2、封装Map集合类型参数

    我们先把Map集合封装到包装类中。即:在包装类中定义Map集合。提供getter和setter方法。

        private Map<StringObject> maps = new HashMap<StringObject>();

        public Map<StringObject> getMaps() {
            return maps;
        }

        public void setMaps(Map<StringObject> maps) {
            this.maps = maps;
        }

    页面的代码:

        <hr size="12" color="blue">
        <form action="${pageContext.request.contextPath}/user/recieveMap.do" method="post">
            姓名:<input type="text" name="mps['username']" id="username"><br>
            年龄:<input type="text" name="mps['age']" id="age"><br>
            <input type="submit" value="提交">
        </form>

    接受参数的方法:

        // 接收Map结合类型参数 
        @RequestMapping("recieveMap")
        public String recieveMap(UserCustom userCustom) {
            System.out.println(userCustom);
            return "success";
        }

    9.6、思考:有了struts2,为什么还需要sprigmvc呢?

    • 实现机制:
      • struts2 底层是基于`过滤器`实现的。过滤器的底层是servlet。
      • springmvc 底层基于`servlet`实现。servlet比过滤器快。
    • 运行速度:
      • struts2 是`多例`
        • 一个请求来了以后,struts2创建多少个对象?如下:
        • ActionContext、ValueStack、UserAction、ActionSupport、ModelDriven等等。
        • UserAction里面属性:User对象,userList集合对象等。属于成员变量,存活时间长。
      • springmvc 是`单例`,因为是基于servlet的,servlet是单例的。
        • 一个请求来了以后,springmvc 创建多少个对象?如下:
        • Controller等等。
        • 方法的参数属于局部变量,存活时间短。
    • 参数封装来分析:
      • struts 基于`属性驱动`进行封装。
      • springmvc 基于`方法`进行封装,粒度更细。

    10、页面回显

    • springmvc使用Model对象进行页面数据回显,Model对象相当于javaweb时所学的application对象(应用域对象),所以Model对象中的数据可以通过EL表达式进行获取。
    • 有了Model对象,才可以向对象中放值,那么Model对象该如何创建呢?
      • 答:`springmvc中放到方法里面的对象会自动被创建`,那么我们就把Model对象放到方法里面。

    10.1、查询所有

    页面的代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>


    <%--引入jstl标签 --%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <table border="1" style="color: blue">
            <tr>
                <td>姓名</td>
                <td>年龄</td>
                <td>生日</td>
                <td>地址</td>
                <td>操作</td>
            <tr/>
            <c:forEach items="${userList}" var="user">
                <tr>
                    <td>${user.username}</td>
                    <td>${user.age}</td>
                    <td>${user.birthday}</td>
                    <td>${user.address}</td>
                    <td>
                        <a href="${pageContext.request.contextPath}/user/updateById.do?id${user.id}">修改</a>
                    </td>
                <tr/>        
            </c:forEach>
        </table>
    </body>
    </html>

    接受参数的方法:

        // 查询所有
        @RequestMapping("listAll")
        public String listAll(Model model{
            // 由于演示我们没有查询数据库,所以下面我们模拟几条数据
            List<User> userList = new ArrayList<User>();

            User user1 = new User();
            user1.setId(1);
            user1.setUsername("晓艺");
            user1.setAge("26");
            user1.setAddress("物资学院");
            user1.setBirthday(new Date());

            User user2 = new User();
            user2.setId(2);
            user2.setUsername("黑泽");
            user2.setAge("26");
            user2.setAddress("青年路");
            user2.setBirthday(new Date());

            User user3 = new User();
            user3.setId(3);
            user3.setUsername("奇遇");
            user3.setAge("28");
            user3.setAddress("物资学院");
            user3.setBirthday(new Date());

            userList.add(user1);
            userList.add(user2);
            userList.add(user3);

            // Model相当于application域对象
            model.addAttribute("userList", userList);

            return "list";  
        }

    浏览器显示效果:

    11、URL模版映射

    • URL模版映射主要是为了实现请求Restfull软件架构设计模式
    • Restfull软件架构设计模式使得请求更简洁、更安全,方便于搜索引擎收录。

    11.1、普通模式修改

    页面的代码:

        <td>
            <a href="${pageContext.request.contextPath}/user/updateByIdNormal.do?id=${user.id}">修改</a>
        </td>

    接受参数的方法:

        // 普通模式修改
        @RequestMapping("updateByIdNormal")
        public String updateByIdNormal(Integer id) {
            System.out.println(id);
            return "redirect:listAll.do";
        }

    访问的地址为:http://localhost:8080/day63_SpringMVC_02/user/updateByIdNormal.do?id=1

    11.2、Restfull风格设计模式修改

    (1)初始Restfull风格设计模式修改
    页面的代码:

        <td>
            <a href="${pageContext.request.contextPath}/user/updateByIdRestfull/${user.id}.do">修改</a> <!-- 把参数放在了请求的里面了 -->
        </td>

    接受参数的方法:

        // 初始Restfull模式修改
        @RequestMapping("updateByIdRestfull/{id}")
        public String updateByIdRestfull(@PathVariable Integer id) {
            System.out.println(id);
            return "redirect:/user/listAll.do"// 请求重定向
        }

    访问的地址为:http://localhost:8080/day63_SpringMVC_02/user/updateByIdRestfull/1.do

    (2)最终Restfull风格设计模式修改
      约定:在web.xml配置拦截方式:在rest目录下所有请求都被拦截,servlet可以拦截目录。
    web.xml中配置代码如下:

        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>

    页面的代码:

        <td>
            <a href="${pageContext.request.contextPath}/rest/user/updateByIdRestfull/${user.id}">修改</a> 
        </td>

    接受参数的方法:

        // 最终Restfull模式修改
        @RequestMapping("updateByIdRestfull/{id}")
        public String updateByIdRestfull(@PathVariable Integer id) {
            System.out.println(id);
            return "redirect:/user/listAll.do"// 请求重定向
        }

    访问的地址为:http://localhost:8080/day63_SpringMVC_02/rest/user/updateByIdRestfull/1
    其中:
      {id}:表示匹配接受页面url路径中的参数
      @PathVariable:表示{id}里面参数注入后面参数id里面
      url模版映射需要@RequestMapping和@PathVariable结合使用。
    画图理解URL模版映射,如下图所示:

    11.3、在线安装eclipse提示插件--Spring tools suite

    步骤:Help --> Eclipse Marketplace… --> 在Find中输入Spring tools suite,点击安装即可。
    安装成功后的截图如下:

    12、转发和重定向

    12.1、转发

    • 本类中进行转发:本类中方法与方法之间进行forward
      • 关键字:forward
      • 转发方式一:return "forward:listAll.do";
      • 转发方式二:return "/user/forward:listAll.do";
      • 注意:`user根路径前面必须有/。`
    • 跨类进行转发:
      • 转发方式:return "forward:/items/listAll.do";

    测试代码如下:

        // 测试forward
        @RequestMapping("forward")
        public String forward() {
            // return "forward:listAll.do"; // 本类中转发方式一
            // return "/user/forward:listAll.do"; // 本类中转发方式二
            return "forward:/items/listAll.do"// 跨类进行转发
        }

    12.2、重定向

    • 本类中进行重定向:本类中方法与方法之间进行redirect
      • 关键字:redirect
      • 重定向方式一:return "redirect:listAll.do";
      • 重定向方式二:return "redirect:/user/listAll.do";
    • 跨类进行重定向:
      • 重定向方式:return "redirect:/items/listAll.do";

    测试代码如下:

        // 测试redirect
        @RequestMapping("redirect")
        public String redirect() {
            // return "redirect:listAll.do"; // 本类中重定向方式一
            // return "/user/redirect:listAll.do"; // 本类中重定向方式二
            return "redirect:/items/listAll.do"// 跨类进行重定向
        }

    13、标签< mvc:annotation-driven />的使用

    详解如下:

    标签<mvc:annotation-driven /> 表示默认创建处理器映射器RequestMappingHandlerMapping、处理器适配器RequestMappingHandlerAdapter,还表示默认启动json格式数据的支持。

    所以在springmvc.xml中就不要再配置处理器映射器和处理器适配器了。
    只需要配置这一句就可以了。

    14、RequestBody 和 ResponseBody

    • @RequestBody 和 @ResponseBody,这两个注解主要是为了提供对json格式数据的支持。
    • @RequestBody的作用:把前台页面请求的json格式数据直接封装成JavaBean,使用ajax进行数据传递。
    • @ResponseBody的作用:在后台,把JavaBean强制转换成json格式数据返回给前台页面。

    这两个注解不能直接使用,需要依赖两个Jackson的jar包。

    (1)先导入Jackson的jar包


    (2)在springmvc.xml中配置json格式转换
    注意:我们也可以直接使用<mvc:annotation-driven />,因为该标签默认启动json格式数据的支持。
        <!-- 配置注解的处理器适配器,作用:调用Controller方法,执行Controller -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <!-- 配置对json格式数据的支持 -->
            <property name="messageConverters">
                <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
            </property>
        </bean> 

    (3)请求json格式数据,返回json格式数据
    (4)请求pojo格式数据,返回json格式数据
    /day63_SpringMVC_02/WebRoot/WEB-INF/jsps/requestjson.jsp
    前台代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <!-- 引入jquery.js的支持 -->
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.js"></script>
    </head>
    <body>
        <input type="button" value="请求是json格式数据,返回是json格式数据" onclick="requestJson();">
        <br>
        <input type="button" value="请求是pojo格式数据,返回是json格式数据" onclick="requestPojo();">
        <script type="text/javascript">
            function requestJson() {
                // 演示:构造一个json格式数据
                var jsonObj = JSON.stringify({'username':'晓艺','age':'26','address':'物资学院'}); // stringify的作用:把json格式的数据数强转成json对象
                // 发送ajax请求
                $.ajax({
                    type:'post',
                    url:'${pageContext.request.contextPath}/user/requestJson.do',
                    contentType:'application/json;charset=UTF-8', // 默认: "application/x-www-form-urlencoded"
                    data:jsonObj,
                    success:function(data// 回调函数
                        alert(data);
                    }
                });
            }
            function requestPojo() {
                // 演示:构造一个pojo格式数据
                var pojoObj = 'username=黑泽&age=26&address=青年路';
                // 发送ajax请求
                $.ajax({
                    type:'post',
                    url:'${pageContext.request.contextPath}/user/requestPojo.do',
                    data:pojoObj,
                    success:function(data// 回调函数
                        alert(data);
                    }
                });         
            }
        
    </script>
    </body>
    </html>

    后台代码:

        // 跳转方法,跳转到requestjson.jsp页面
        @RequestMapping("toJson")
        public String tiJson() {
            return "requestjson";
        }

        // 接收json格式数据,使用 @RequestBody 把json格式数据封装进JavaBean对象中(本例中是User对象)
        // 返回json对象,使用 @ResponseBody 把User对象转换成json对象
        @RequestMapping("requestJson")
        public @ResponseBody User requestJson(@RequestBody User user) {
            System.out.println(user);

            return user;
        }

        // 接收pojo格式数据
        // 返回json对象,使用@ResponseBody 把User对象转换成json对象
        @RequestMapping("requestPojo")
        public @ResponseBody User requestPojo(User user) {
            System.out.println(user);

            return user;
        }
  • 相关阅读:
    【转】解决在Android设备播放音频与其他应用重音的问题,并监听耳机的控制按钮
    【转】wamp 3.0.6(apache 2.4.23) 403 forbidden 解决办法
    身份证第18位(校验码)的计算方法
    【转】Win10开机密码忘了?教你破解Win10开机密码
    【转】具透 | 你可能不知道,iOS 10 有一个中国「特供」的联网权限功能
    钉钉自定义机器人 发送文本 换行 无效果
    屏蔽右键+f12
    【转】理解WebKit和Chromium: JavaScript引擎简介
    第2章 排序 | 第10节 计数排序练习题 && 基数排序
    图像处理-深入探索插值操作
  • 原文地址:https://www.cnblogs.com/chenmingjun/p/9856070.html
Copyright © 2011-2022 走看看