zoukankan      html  css  js  c++  java
  • MVC模式到传统风格的Spring MVC

    现在我们要做个简单的基于servlet的MVC的模型,我们要有一个Product要从表单处获取。

    MVC中的M是模型,V是视图,C是控制器。视图负责应用的展示,模型封装了数据和业务逻辑,控制器负责接收用户输入,改变模型以及调整视图是显示。

    在现代框架中,servlet和filter都可以作为controller,也就是控制器。

    MVC中的业务逻辑一般叫做action,每个HTTP请求发给控制器,请求中的URL标识出对应的action。action标识了一个操作。在数据库中添加一个product需要两个action:

    1.显示一个添加产品的表单

    2.保存表单信息到数据库

    然后我们要通过url来告诉控制器执行相应的action    http://domain/appName/product_input   http://domain/appName/product_save

    控制器回解析url并调用相应的action,然后将模型对象放在视图可以访问到的区域,最后利用RequestDispatcher来跳转视图。

    先来看用servlet实现的mvc:

    Product类

    public class Product implements Serializable {
        //实现了序列化接口,然后就可以安全地将数据保存在HttpSession中
    
        private static final long serialVersionUID = 544546444654L;
        private String name;
        private String description;
        private float price;
    
        public String getName() {
            return name;
        }
    
        public String getDescription() {
            return descriptioin;
        }
    
        public String getPrice() {
            return price;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setPrice(float price) {
            this.price = price;
        }
    
        public void setDescription(String description){
            this.description = description;
        }
    }

    ProductForm类(这里主要是考虑到校验等问题)

    public class ProductForm {
    
        private String name;
        private String description;
        private float price;
    
        public String getName() {
            return name;
        }
    
        public String getDescription() {
            return descriptioin;
        }
    
        public String getPrice() {
            return price;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setPrice(float price) {
            this.price = price;
        }
    
        public void setDescription(String description){
            this.description = description;
        }
    }

    两个视图:ProductForm.jsp对应于输入表单操作,ProductDetials.jsp对应于保存表单操作。

    自己写的Controller接口:

    public interface Controller {
        String handleRequest(HttpRequest req, HttpServletResponse resp);
    }

    InputProductController类

    public class InputProductController implements Controller {
        public  String handleRequest(HttpRequest req, HttpServletResponse resp) {
            return "WEB-INF/jsp/ProductForm.jsp";
        }
    }

    SaveProductController类

    public class InputProductController implements Controller {
        public  String handleRequest(HttpRequest req, HttpServletResponse resp) {
        ProductFrom productFrom = new ProductFrom();
        productFrom.setName(req.getParameter("name"));
        productFrom.setPrice(req.getParameter("price"));
        productFrom.setDescription(req.getParameter("description"));
    
        //create model
        Product product = new Product();
        product.setName(productFrom.getName());
        product.setPrice(productFrom.getPrice());
        product.setDescription(productFrom.getDescription());
    
        requset.setAttribute("product",product);    
            return "WEB-INF/jsp/ProductDetails.jsp";
        }
    }

    DispatcherServlet 分发器servlet:

    public class DispatcherServlet extends HttpServlet {
        private static final long serialVersionUID = 4654654L;
        public void doGet(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            process(req,resp);
        }
    
        public void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            process(req,resp);
        }
    
        public void process(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            String url = request.getRequestURl();
            int lastIndex = url.lastIndexOf("/");//就是找出最后一个/的所在位置
            String action = url.subString.substring(lastIndex+1);
    
            String dispatcherUrl = null;
            if(action.equals("product_input.action")) {
                InputProductController controller = new InputProductController();
                dispatchUrl = controller.handleRequest(req,resp);
            } else if(action.equals("product_save.action") {
                SaveProductController controller = new SaveProductController();
                dispatchUrl = controller.handleRequest(req,resp);
            }//解析url,根据不同的action实例化不同的controller
    
            //跳转视图
            if(dispatcherUrl != null) {
                RequestDispatcher rd = request.getRequestDispather(dispatchUrl);
                rd.forward(req,resp);
            }
        } 
    
    
    }

    然后这里顺便提提校验器,就是在后台校验表单内容,一般框架都支持声明式验证和编程式验证两种,前者需要提供包含校验规则的xml文档或者属性文件,后者则需要通过编码进行用户输入校验。

    这就是一个简单的MVC模型的应用。

    SpringMVC:

    现在我们来开始介绍Spring MVC,这里我们讲的是“传统开发风格的”SpringMVC,另一种方式将是基于注解的。

    首先,用Spring MVC有什么好处呢?首先一点就是,我们可以不用去写Disapatcher servlet,SpringMVC框架已经带有了这个,不用额外开发。也就是说,SpringMVC里面自带了一个DisapatcherServlet,它可以:

      1.根据url调用相应的action

      2.实例化正确的控制器类

      3.根据请求参数来构造表单bean

      4.调用控制器对象的相应方法

      5.转发到一个视图

    也就是说,只要我们把该配置的配置好,SpringMVC自带的这个servlet就会帮我们去完成这些工作。

    另外SpringMVC还有几个特点,像    可以自动绑定用户输入,并正确地转换数据类型;可以校验用户输入,若校验不通过,则重定向回输入表单,输入校验是可选的,支持编程以及声明方式……

    SpringMVC的DispatcherServlet:

      要用这个自带的分发器,我们要在部署描述符也就是web.xml中配置好它。

      

    <servlet>
           <description>This is the description of my J2EE component</description>
           <display-name>This is the display name of my J2EE component</display-name>
           <servlet-name>springmvc</servlet-name>
           <servlet-class>org.springframework.web.servlet.DisaptcherServlet</servlet-class>
           <load-on-startup>1<load-on-startup/>
            <!-- 这个是可选的,如果存在,则在应用程序启动的时候就会装载这个servlet并调用它的init方法,如果不存在这个方法,则在这个servlet的第一个请求的时候加载 -->
    
      </servlet>
    
      <servlet-mapping>
           <servlet-name>springmvc</servlet-name>
           <url-pattern>/*</url-pattern>
      </servlet-mapping>

     好了,完成了这一步之后,现在Tomcat就知道我在用这个servlet,但这个servlet是来自SpringMVC的,所以显然它要读取到Spring的配置信息。所以这个servlet在初始化的时候,会在WEB-INF下找一个配置文件,该文件的命名规则如下:

      servletName-servlet.xml

    这个servletName就是部署描述符中的那个DisaptcherServlet的名称,比如现在我们上面这个的文件名就应该为:

      springmvc-servlet.xml

    当然,如果你不想这个配置文件放在着这,也不想用这个名字,那么你可以在部署描述符中使用servlet定义的init-param元素,以便servlet可以加载到这个元素,元素里面有一个值为<param-name>contextConfigLocation<param-name/>的param-name的元素,它的值param-value元素则包含配置文件的路径。

    <servlet>
           <description>This is the description of my J2EE component</description>
           <display-name>This is the display name of my J2EE component</display-name>
           <servlet-name>springmvc</servlet-name>
           <servlet-class>org.springframework.web.servlet.DisaptcherServlet</servlet-class>
           <load-on-startup>1<load-on-startup/>
            <!-- 这个是可选的,如果存在,则在应用程序启动的时候就会装载这个servlet并调用它的init方法,如果不存在这个方法,则在这个servlet的第一个请求的时候加载 -->
            
            <init-param>
                <param-name>contextConfigLocation<param-name/>
                <param-value>xxx/xxx/xxx/yourName.xml<param-name/>
            <init-param/>
      </servlet>
    
      <servlet-mapping>
           <servlet-name>springmvc</servlet-name>
           <url-pattern>/*</url-pattern>
      </servlet-mapping>

     

    Controller:

    传统的开发方法就是去实现org.springframework.web.servlet.mvc.Controller

    这个接口开放了一个handleRequest方法

      ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse);

    这个ModelAndView可以包含视图路径或则同时包含视图路径和数据模型

    Controller接口的实现类只能处理一个单一的动作Action,而一个基于注解的控制器可以同时支持多个请求处理动作,并且无须实现任何接口。

    先来看spring配置文件,这里我们直接放在规定的位置和规定的命名——springmvc-servlet.xml

    <?xml version="1.0" encoding="UTF-8" ?>   
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
         xmlns="http://www.springframework.org/schema/beans"  
         xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">   
        <bean name="/product_input.action" class="xxx.xxx.InputProductController"/>
        <bean name="/product_save.action" class="xxx.xxx.SaveProductController"/>
    </beans> 

     两个controller:

    public class InputProductController implements Controller {
        //这个controller就是spring框架那个要实现的controller
        private static final Log logger = LogFactory.getLog(InputProductController.class);
    
        public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            logger.info("InputProductController caller");
            return new ModelAndView("/WEB-INF/jsp/ProductForm.jsp");
        }
    }
    public class SaveProductController implements Controller {
        //这个controller就是spring框架那个要实现的controller
        private static final Log logger = LogFactory.getLog(SaveProductController.class);
    
        public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            logger.info("SaveProductController caller");
            
            ProductFrom productFrom = new ProductFrom();
                productFrom.setName(req.getParameter("name"));
                productFrom.setPrice(req.getParameter("price"));
                productFrom.setDescription(req.getParameter("description"));
    
                //create model
                Product product = new Product();
                product.setName(productFrom.getName());
                product.setPrice(productFrom.getPrice());
                product.setDescription(productFrom.getDescription());
    
            
            return new ModelAndView("/WEB-INF/jsp/ProductDetails.jsp","product",product);
        }  
    }

     InputProductController的handelRequest只是返回一个包含视图的ModelAndView,

    SaveProductController的handelRequest方法返回的ModelAndView包括了视图的路径、模型的名称及模型,该模型将提供给目标视图,用于展示。

    ProductFrom.jsp中的form的action:

      action="product_save.action"

    ProductDetials.jsp中

      Product Name: ${product.name} <br>

      Description: ${product.description}<br>

      Price: ${product.price}

      可以直接用EL表达式来访问传过来的product模型

    SpringMVC的View Resolver:

    SpringMVC的视图解析器负责解析视图,可以通过在Spring的配置文件来设置:

    <bean id="viewResolver" class="org.springframewordk.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    上图的视图解析器设置了前缀和后缀两个属性,现在你只需要在ModelAndView里面返回"mainPage"就相当于

    /WEB-INF/jsp/mainPage.jsp
  • 相关阅读:
    前端资源分享
    Java的wait(), notify()和notifyAll()使用心得(转)
    Java 理论与实践: 处理 InterruptedException(转)
    关于线程中断的总结
    Python入门(good)
    看着自己有什么样的资源,利用好这些资源就好了。不要看着别人的资源流口水(转)
    android手机SD卡中的android_secure目录
    Android中ExpandableListView控件基本使用
    华为的面试经历
    Flex强制类型转换错误
  • 原文地址:https://www.cnblogs.com/wangshen31/p/8457781.html
Copyright © 2011-2022 走看看