Spring 初探(十四)(核心类DispacherServlet及Content Negotiation)

来源:互联网 发布:数据恢复实训 编辑:程序博客网 时间:2024/05/16 07:33
开始对于Spring Web MVC框架展开介绍行文结构采用缩进来描述(Python)Spring Web model-view-controller(MVC) 框架围绕DispatcherServlet进行设计这里展开介绍org.springframework.web.servlet.DispatcherServlet
相应简单示例可见本文文末。对于HTTP handlers/controllers 的核心调度(dispatcher) 调度registered handlers 来处理Web Request 提供方便的映射(mapping)及异常处理工具其与基于request的Web MVC框架是有区别的其构建基于JavaBean其可以使用任何HandlerMapping实现——无论是预先设定还是作为一个应用的一部分被提供 来控制处理request操作对象的相关事务。org.springframework.web.servlet.HandlerMapping被对象实现的接口 用于定义requests与handler 对象其常见的两个实现类如下 是DispatcherServlet的默认实现类org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping将URLs 映射为以slash("/") 为名称起始的bean简单的例子及注意事项见:http://stackoverflow.com/questions/3452085/can-i-use-springs-requestmapping-and-beannameurlhandlermapping-in-conjuntion-worg.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping 将要被org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping 取代从@Controller @RequestMapping修饰的方法中生成 RequestMappingInfo实例由于RequestMappingInfo实现的RequestCondition其可以决定与其最相近的HttpServletRequest 以用于servlet service method的处理其相关叙述见:http://blog.csdn.net/u012410733/article/details/51912375由于其将要被取代的原因 其主要应用场景为自定义拦截器,简单示例见:http://blog.csdn.net/liuwenbo0920/article/details/8172791 及文档其可以使用任何HandlerAdaptter接口 Spring默认采用的是 如下两个实现此接口的类 HttpRequestHandlerAdapter SimpleControllerHandlerAdapter, 二者分别对应于HttpRequestHandler及 Controller org.springframework.web.servlet.HandlerAdaptar每一个handler必须实现一个此接口以处理request 此接口可以允许DispatcherServlet被无限扩展, DispatcherServerlet 通过此接口可以接触到所有实现的handlers org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter 对于一般的DispatcherServlet 这是一个使用HttpRequestHandler接口的类其使用方式基本上是通过handle函数完成的 其相关讨论及源码解析见:http://blog.csdn.net/robertleepeak/article/details/5913201其他适配器情况是类似的org.springframework.web.HttpRequestHandler普通的用于操作HTTP requests的组件接口 与Servlet类似 仅仅是声明了ServletException IOException 来允许在任何HttpServlet中使用为派生类提供抽象方法来实现一个合适的HTTP servlet的抽象基类提供以do开头的若干函数接口(doGet doPost doPut doDelete 初始化 析构化等) 对于HttpServlet如何在整个HTTP request到reqponse过程中起作用的叙述及例子见下列:http://www.cnblogs.com/panjun-Donet/archive/2010/02/22/1671290.html其基本等价于上述HttpServlet 仅仅是将核心功能包装成handle方法。org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter 对于一般的DispatcherServlet 这是一个使用一般Controller工作流程接口的类org.springframework.web.servlet.mvc.Controller在先前关于Spring RESTful应用中已经对这部分已经有一个感性的认识其基本上类似于HttpServlet(receives HttpServletRequest and HttpServletResponse)但其还可参与到MVC工作流程中 下面对于此工作流程做概括:在一个DispatcherServlet 收到一个request并完成有关请求信息(URL UR等)的相关解析后 其尝试通过HandlerMapping找到合适的Controller 在找到之后 Controller对应的handleRequest方法被调用。这个方法的作用类似于HttpRequestHandlerAdapter的handle方法与HttpRequestHandler handleRequest方法的结合处理request并返回一个ModelAndView对象用于DispatcherServlet进行渲染(render)从处理逻辑逻辑上来看相当于将HttpRequestHandler handleRequest的具体逻辑放在此函数中。任何一个直接的Controller接口的类仅仅起到处理HttpServletRequests并返回ModelandView对象的作用 任何其他功能应该通过继承AbstractController或者其派生类进行自定义相应的一个简单的仅接受POST请求的AbstractController派生类的例子见下例:http://www.codejava.net/frameworks/spring/14-tips-for-writing-spring-mvc-controller在上面的叙述过程中最后进行渲染(render)之前涉及到一个类org.springframework.eb.servlet.ModelAndView对于web MVC framework其为Model 及View的持有者 这二者具有严格区别该类仅仅是一个可以将二者都作为返回值被Controller return的“容器类”一个简单的应用Model View的例子见:http://jeromejaglale.com/doc/java/spring/mvcorg.springframework.ui.Model被用来设计对于model增加attributes 用于将整体model 可以作为java.util.Map进行访问基本上是储存被渲染内容的“容器类”org.springframework.web.servlet.View用于web 交互的MVC View 其实现负责内容渲染及model应用(调用render方法)View 如同ViewResolver中装备的beans实现这个接口的类可以通过name解析(返回) View (调用 resolveViewName)view的解析阶段可以通过ViewResolver来实现 将象征性的view name 解析为View objectsSpring 默认使用的实现这个接口的类是InternalResourceViewResolverUrlBaesdViewResolver 的方便的派生类 ViewResolver的简单实现 支持对于象征性name到 URLs的解析将解析后的路径作为如 .jsp待渲染文件的对应 其官网上的例子如下:Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" 其有关redirct 及forword url的一些形式设定参看文档。将InternalResourceView(Servlets and JSPs) 及JstlView 作为UrlBaesdViewResolver 指定的View type的指定对应情况构造的类 其设定了使用JSP进行渲染的方式手动进行bean的相关定义的方式见文档或如下链接:http://www.cnblogs.com/crazy-fox/archive/2012/02/18/2357675.html当一个View 或者view name没有被提供的话 配置的RequestToViewNameTranslator会将根据request 翻译成view name 进行后续操作Spring 默认通过DefaultRequestToViewNameTranslator来进行相应翻译操作,其“翻译”方法见文档一个示例应用场景见:http://www.aichengxu.com/view/5359666其余部分不常用,参见文档:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html
从上面的内容可以看到DispatcherServlet承担的基本任务为将requests发送给handlers 并与其连带地配置handler mappings / view resolution / locale / time zone / theme resolution及有关上传文件的支持默认的handler 基于@Controller @RequestMapping 提供了广泛灵活的处理方法 通过@PathVariable及其他特性 可以开发RESTful Web sites及其他应用。Spring view解析十分灵活 Controller负责准备一个model Map组成的 data 并选择一个view name 但是其也可直接对response stream进行写操作并完成request的处理操作 View name的解析可以通过file extension(扩展名)/ Accept header content type negotiation /bean name / property file 甚至一个ViewResolver实现完成。上面提到的content negotiation指有关service得到的返回内容类型的决定过程Spring的处理方式包含下面的形式(另一种形式 Content Negotiation using Views见http://spring.io/blog/2013/06/03/content-negotiation-using-views/ 且不介绍)Content Negotiation using Spring MVC(https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc)有两种方法通过Spring MVC产生output使用@ResponseBody及HTTP message converters返回类似JSON XML的data格式见 Spring 初探(十)使用view resolution view 一般被用来产生HTML的格式可以参见 上文中有关 model 及 view介绍中的链接第三种可能 上面两种都需要 Spring支持简单地实现了对这二者组合的支持无论通过哪种方法 都要求对于相同的由controller返回的数据处理多个表现形式(views) 决定使用哪种data格式作为返回被称为 Content Negotiation需要知道哪种data格式的情况有三种HttpMessageConverters (要决定正确的convrter)对HTTP requests 及responses执行读写的接口Request Mappings (将HTTP request与不同的方法连接并返回不同的形式)View Resolution (选择正确使用的view)对于使用者需要的数据格式的解析通过ContentNegotationStrategy 这个接口的实现完成在通过HTTP 发送一个request时可以通过设定Accept heander属性来设定想要的response格式 (Spring 初探(十二)中简要提及到)但是对于不同的浏览器及其引擎 其Accept内容设定顺序的不同 决定了server在处理是不能统一给出最少交互次数的通信解决方案 特别地IE将一些应用嵌入到Accept中使得这个问题更加复杂 相应讨论见:http://www.newmediacampaigns.com/blog/browser-rest-http-accept-headers其最后结论为 基于Accept Header的 Content-negotiation在实际应用中难以应用 如Twitter的 REST API不使用Accept Header 进行content-negotiation 而是使用扩展的URL(加后缀.josn .xml)等 这也是下面讨论的Spring的处理方式之一。Enabling Content Negotiation in Spring MVCSpring 支持两个便于选择需要数据形式的方式 (后缀 and/or URL参数)后缀:如: http://myserver/myapp/accounts/list.html http://myserver/myapp/accounts/list.xlsUrl参数:如:http://myserver/myapp/accounts/list?format=xls(format 是默认保留参数)最后的 Accept HTTP header 性质会被检查。要想使上面的功能生效 仅需要如下加入配置:(忽略使用xml进行配置的形式)


Ex:
@Configuration@EnableWebMvcpublic class WebConfig extends WebMvcConfigurerAdapter {  /**    * Setup a simple strategy: use all the defaults and return XML by default when not sure.     */  @Override  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {    configurer.defaultContentType(MediaType.APPLICATION_XML);  }}

@EnableWebMvc将这个annotation加入@Configuration修饰的类中 会将Spring MVC configuration从WebMvcConfigurationSupport导入 由MVC Java config提供的主要类 一个更高级的可选方案是直接派生这个类 override相应方法 来进行配置该类对于一些需要的类进行register(如 HandlerMappings HandleerAdapters等)在上例中派生了WebMvcConfigurerAdapeter 一个实现WebMvcConfiguurer的虚基类 相应方法为空 待override在上例中 其目的是为配置WecMvcConfigurationSupport提供接口。configureContentNegotiation(ContentNegotiationConfigurer configurer)其默认配置为favorPathExtension On(后缀)favorParameter Off(参数)ignoreAcceptHeader OndefaultContextType Not setdefaultContentTypeStrategy Not set在使用如上配置的方法中还有很多可具体配置的选项,见下例:

Ex:
@Configuration@EnableWebMvcpublic class WebConfig extends WebMvcConfigurerAdapter {  /**    *  Total customization - see below for explanation.    */  @Override  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {    configurer.favorPathExtension(false).            favorParameter(true).            parameterName("mediaType").            ignoreAcceptHeader(true).            useJaf(false).            defaultContentType(MediaType.APPLICATION_JSON).            mediaType("xml", MediaType.APPLICATION_XML).            mediaType("json", MediaType.APPLICATION_JSON);  }}

上面设定了 禁止扩展名识别 设定参数识别的参数有默认的format改为mediaType 其余具体描述见文档及链接。

给出一个简单的自定义DispatcherServlet的简单示例 
该例来源于 
《Servlet、JSP和Spring MVC初学指南》
可以看到此调度类的大致意思
用到的简单类
package domain;/** * Created by admin on 2017/2/27. */import java.io.Serializable;public class Product implements Serializable {    private static final long serialVersionUID = 748392348L;    private String name;    private String description;    private float price;    public String getName(){return name;}    public void setName(String name){this.name = name;}    public String getDescription(){return description;}    public void setDescription(String description){this.description = description;}    public float getPrice(){return price;}    public void setPrice(float price){this.price = price;}}

package form;/** * Created by admin on 2017/2/27. */public class ProductForm {    private String name;    private String description;    private String price;    public String getName(){return name;}    public void setName(String name){this.name = name;}    public String getDescription(){return description;}    public void setDescription(String description){this.description = description;}    public String getPrice(){return price;}    public void setPrice(String price){this.price = price;}}



Controller 接口
package controller;/** * Created by admin on 2017/2/27. */import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public interface Controller {    String handleRequest(HttpServletRequest request, HttpServletResponse response);}

一个实现
package controller;/** * Created by admin on 2017/2/27. */import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class InputProductController implements Controller {    @Override    public String handleRequest(HttpServletRequest request, HttpServletResponse response){        return "/WEB-INF/jsp/ProductForm.jsp";    }}

对应jsp页面
<%--  Created by IntelliJ IDEA.  User: admin  Date: 2017/2/27  Time: 14:05  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head>    <title>Add Product Form</title>    <style type="text/css">@import url("/css/main.css");</style></head><body><div id = global>    <form action = "product_save.action" method="post">        <fieldset>            <legend>Add a product</legend>            <p>                <label for="name">Product Name:</label>                <input type="text" id = "name" name = "name" tabindex="1">            </p>            <p>                <label for = "description">Description:</label>                <input type="text" id = "description" name = "description" tabindex="2">            </p>            <p>                <label for = "price">Price:</label>                <input type = "text" id = "price" name = "price" tabindex="3">            </p>            <p>                <input id = "reset" type="reset" tabindex="4">                <input id = "submit" type="submit" tabindex="5" value = "Add Product">            </p>        </fieldset>    </form></div></body></html>

另一个实现
package controller;/** * Created by admin on 2017/2/27. */import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import domain.Product;import form.ProductForm;public class SaveProductController implements  Controller {    @Override    public String handleRequest(HttpServletRequest request, HttpServletResponse response){        ProductForm productForm = new ProductForm();        productForm.setName(request.getParameter("name"));        productForm.setDescription(request.getParameter("description"));        productForm.setPrice(request.getParameter("price"));        Product product = new Product();        product.setName(productForm.getName());        product.setDescription(productForm.getDescription());        try{            product.setPrice(Float.parseFloat(productForm.getPrice()));        }catch (NumberFormatException e){        }        request.setAttribute("product", product);        return "/WEB-INF/jsp/ProductDetails.jsp";    }}


对应的jsp页面
<%--  Created by IntelliJ IDEA.  User: admin  Date: 2017/2/27  Time: 14:45  To change this template use File | Settings | File Templates.--%><%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %><html><head>    <title>Save Product</title></head><body><div id = "global">    <h4>The product has been saved.</h4>    <p>    <h5>Details:</h5>    Product Name: ${product.name}<br/>    Description: ${product.description}<br/>    Price: ${product.price}    </p></div></body></html>

调度类
package servlet;/** * Created by admin on 2017/2/27. */import controller.InputProductController;import controller.SaveProductController;import java.io.IOException;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DispatcherServlet extends HttpServlet {    private static final long serialVersionUID = 748495L;    @Override    public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException{        process(request, response);    }    @Override    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{        process(request, response);    }    private void process(HttpServletRequest request, HttpServletResponse response)throws IOException, ServletException{        String uri = request.getRequestURI();        int lastIndex = uri.lastIndexOf("/");        String action = uri.substring(lastIndex + 1);        String dispatcherUrl = null;        if (action.equals("product_input.action")){            InputProductController controller = new InputProductController();            dispatcherUrl = controller.handleRequest(request, response);        }else if(action.equals("product_save.action")){            SaveProductController controller = new SaveProductController();            dispatcherUrl = controller.handleRequest(request, response);        }        if (dispatcherUrl != null){            RequestDispatcher rd = request.getRequestDispatcher(dispatcherUrl);            rd.forward(request, response);        }    }}


配置
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"         version="3.1">    <servlet>        <servlet-name>DispatcherServlet</servlet-name>        <servlet-class>servlet.DispatcherServlet</servlet-class>    </servlet>    <servlet-mapping>        <servlet-name>DispatcherServlet</servlet-name>        <url-pattern>*.action</url-pattern>    </servlet-mapping></web-app>

由于Spring的若干简化工作 上面的代码可以简化如下:
Controller类
package controller;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class InputProductController implements Controller {    private static final Log logger = LogFactory            .getLog(InputProductController.class);    @Override    public ModelAndView handleRequest(HttpServletRequest request,                                      HttpServletResponse response) throws Exception {        logger.info("InputProductController called");        return new ModelAndView("/WEB-INF/jsp/ProductForm.jsp");    }}

package controller;import domain.Product;import form.ProductForm;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class SaveProductController implements Controller {    private static final Log logger = LogFactory            .getLog(SaveProductController.class);    @Override    public ModelAndView handleRequest(HttpServletRequest request,                                      HttpServletResponse response) throws Exception {        logger.info("SaveProductController called");        ProductForm productForm = new ProductForm();        // populate action properties        productForm.setName(request.getParameter("name"));        productForm.setDescription(request.getParameter("description"));        productForm.setPrice(request.getParameter("price"));        // create model        Product product = new Product();        product.setName(productForm.getName());        product.setDescription(productForm.getDescription());        try {            product.setPrice(Float.parseFloat(productForm.getPrice()));        } catch (NumberFormatException e) {        }        // insert code to save Product        return new ModelAndView("/WEB-INF/jsp/ProductDetails.jsp", "product",                product);    }}

web工程配置文件
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"         version="3.1">    <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>/WEB-INF/applicationContext.xml</param-value>    </context-param>    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>    <servlet>        <servlet-name>dispatcher</servlet-name>        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>dispatcher</servlet-name>        <url-pattern>*.action</url-pattern>    </servlet-mapping></web-app>

DispacherServlet配置文件
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean name="/product_input.action" class="controller.InputProductController"/>    <bean name="/product_save.action" class="controller.SaveProductController"/></beans>

当然这里ModelAndView中路径的前缀及后缀是可以通过配置省略的,而且也可以配置 servlet配置文件的 
所在路径及文件名称,见下例。

两个Controller(返回值与上例不同)
package controller;/** * Created by admin on 2017/2/28. */import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;public class InputProductController implements Controller {    private static final Log logger = LogFactory.getLog(InputProductController.class);    @Override    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response){        logger.info("InputProductController called");        return new ModelAndView("ProductForm");    }}

package controller;/** * Created by admin on 2017/2/28. */import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;import domain.Product;import form.ProductForm;public class SaveProductController implements Controller {    private static final Log logger = LogFactory.getLog(SaveProductController.class);    @Override    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response){        logger.info("SaveProductController called");        ProductForm productForm = new ProductForm();        productForm.setName(request.getParameter("name"));        productForm.setDescription(request.getParameter("description"));        productForm.setPrice(request.getParameter("price"));        Product product = new Product();        product.setName(productForm.getName());        product.setDescription(productForm.getDescription());        try{            product.setPrice(Float.parseFloat( productForm.getPrice()));        }catch(NumberFormatException e){        }        return new ModelAndView("ProductDetails", "product", product);    }}

配置文件
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"         version="3.1">    <context-param>        <param-name>contextConfigLocation</param-name>        <param-value>/WEB-INF/applicationContext.xml</param-value>    </context-param>    <listener>        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>    <servlet>        <servlet-name>dispatcher</servlet-name>        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        <load-on-startup>1</load-on-startup>        <init-param>            <param-name>contextConfigLocation</param-name>            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>        </init-param>    </servlet>    <servlet-mapping>        <servlet-name>dispatcher</servlet-name>        <url-pattern>*.form</url-pattern>        <url-pattern>*.action</url-pattern>    </servlet-mapping></web-app>

省略前缀后缀的配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean name = "/product_input.action" class="controller.InputProductController"></bean>    <bean name = "/product_save.action" class="controller.SaveProductController"></bean>    <bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name = "prefix" value = "/WEB-INF/jsp/"/>        <property name = "suffix" value=".jsp"/>    </bean></beans>

上面是对Controller接口进行实现的版本 
还可以使用Spring mvc annotation 进行更简单的Controller实现

package controller;/** * Created by admin on 2017/2/28. */import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import domain.Product;import form.ProductForm;@Controllerpublic class ProductController {    private static final Log logger = LogFactory.getLog(ProductController.class);    @RequestMapping(value = "/product_input")    public String inputProduct(){        logger.info("inputProduct called");        return "ProductForm";    }    @RequestMapping(value = "/product_save")    public String saveProduct(ProductForm productForm, Model model){        logger.info("saveProduct called");        Product product = new Product();        product.setName(productForm.getName());        product.setDescription(productForm.getDescription());        try{            product.setPrice(Float.parseFloat(productForm.getPrice()));        }catch(NumberFormatException e){        }        model.addAttribute("product", product);        return "ProductDetails";    }}

这里简便的过程在于完成了表单对象(ProductForm) 与实际传输表单数据的直接绑定,
使得可以不用再手动对ProductForm对象进行初始化。

使用annotation进行Controller声明  应当如下配置使得 应用上下文对其进行读取
<?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:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/mvc        http://www.springframework.org/schema/mvc/spring-mvc.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd">    <context:component-scan base-package="controller"/>    <mvc:annotation-driven/>    <mvc:resources mapping="/css/**" location="WEB-INF/css/"/>    <mvc:resources mapping="/*.html" location="/"/>    <bean id = "viewResolver" class = "org.springframework.web.servlet.view.InternalResourceViewResolver">        <property name = "prefix" value="/WEB-INF/jsp/"/>        <property name = "suffix" value=".jsp"/>    </bean></beans>

这里还进行了一些resources的mapping配置。

0 0