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在使用如上配置的方法中还有很多可具体配置的选项,见下例:
@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 其余具体描述见文档及链接。
该例来源于
《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"; }}
<%-- 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
- Spring 初探(十四)(核心类DispacherServlet及Content Negotiation)
- Spring MVC Content Negotiation
- 内容协商 (Content Negotiation)
- Django-restframework27 Content negotiation(内容协议)
- RESTful之Content negotiation
- 逆向工程核心原理学习笔记(二十四):abex'crackme #2 初探
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring中DispacherServlet、WebApplicationContext、ServletContext的关系
- Spring核心及实现
- Negotiation
- Windows核心编程(二十四)终止处理程序及异常处理程序
- Windows Phone架构下CONTENT及开发初探
- python核心编程(十四)—邮件
- UML 类图
- spring和springmvc父子容器问题
- PHP开发小技巧⑩—实现中文字符串截取无乱码的方法
- Echarts导出为pdf
- 字符串输出后面有乱码
- Spring 初探(十四)(核心类DispacherServlet及Content Negotiation)
- 支付宝芝麻信用界面_(二)UI适配以及特效
- 用C语言解决狐狸找兔子的问题
- SSH说明(1)
- Java注解
- Sqlite存储日期
- jQuery实现QQ空间图片展示效果
- tomcat各目录(文件)作用
- nodejs设置允许跨域