- 浏览: 481577 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
mrluo735:
明显不对,INOUT参数也可以有多个!
MyBatis 3 中使用存储过程 -
qitianhuoshen:
问一下 如果 配合 datatables的 searchval ...
MyBatis 3 中使用存储过程 -
zhanggang807:
”这就是累积,不会被清理“ 这个例子解决了我疑惑很久的问题
NIO - 使用选择器 -
lIO01:
你能不能别用自己照片当头像?
Spring MVC 中的基于注解的 Controller -
xuxiaoyinliu:
Spring MVC 中的 forward 和 redirect
终于来到了基于注解的 Spring MVC 了。之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响应请求。实际上,ControllerClassNameHandlerMapping, MultiActionController 和选择恰当的 methodNameResolver(如 InternalPathMethodNameResolver) 就已经可以在很大程度上帮助我们省去不少的 XML 配置,谁让 ControllerClassNameHandlerMapping 极度的拥抱了 Convention Over Configuration 呢。
那为什么还要用基于注解的 Controller 呢?Spring MVC 在 Spring 2.5 发布中新添加了一种基于注解的 Controller 形式。借助于与 Spring 2.5 一同发布的容器内 <context:component-scan> 功能支持,基于注解的 Controller 几乎可以达到 XML 零配置,进而极大地提高我们的开发效率。
和其它 Controller 一样,基于注解的 Controller 同样有相应的 HandlerMapping,那就是 DefaultAnnotationHandlerMapping。同样,也有相应的 HandlerAdapter,那就是 AnnotationMethodHandlerAdapter。甚至,我们都可以不把 Controller 注册到容器里,那么肯定需要一种机制来帮助我们完成这点,这就是 <context:component-scan>。开发基于注解的 Controller,我们需要做以下准备工作:
● <context:compnent-scan>
● HandlerMapping
● HandlerAdaptor
好了,有了以上几点准备工作,我们就可以开始基于注解的 Controller 之旅了。下面我们来一个一个注解的来讲解。
● @Controller
● @RequestMapping
● @RequestParam(将请求参数绑定到方法参数)
● @PathVariable(将 url template 里的参数绑定到方法参数)
● @RequestBody(将请求正文绑定到方法参数)
● @ResponseBody(将处理完请求后返回的对象绑定到响应正文)
● @ModelAttribute
● @SessionAttributes
Spring MVC 里的大部分的注解,这里基本上都讲到了。日后随着 Spring 的升级,我也会逐一补充新加的注解。其实,仅凭以上的注解,是可以构建一个足够强大的 RESTFul Webservices 的了。
这里,补充讲下被标注了 @RequestMapping 注解的请求方法的签名。使用 @RequestMapping 标注的 web 请求处理方法的签名比较灵活,我们几乎可以声明并使用任何类型的方法参数。不过,以下几种类型的方法参数将拥有更多语义,它们均来自框架内部(或者说 AnnotationMethodHandlerAdapter)所管理的对象引用:
基于注解的 Controller 的请求处理方法返回类型可以有如下 4 种形式(当然,前面提到的 @ResponseBody 和 @ModelAttribute 并没下面所描述的返回类型,具体参见上面对各自注解的讲解):
String 类型的返回值为 null, 还有返回类型为 ModelMap 和 void,从请求路径中如何提取视图信息呢?框架将截取请求路径中的最后一个 / 后面的内容,并去掉后缀名,剩下来的内容就是视图名。如请求路径为 /spring3/user/welcome,那么视图名是 welcome,/spring3/user/welcome.action 的视图名也是 welcome。
接下来来讲最后一个部分,请求参数到方法参数的绑定。这个在 @RequestParam 中已经讲过,不过,这里要讲的是绑定复杂的对象。在 @RequestParam 中,我们这样请求,date=2011-01-01 其实是绑定不到 Date 对象的。因为不同的 Locale 处理日期的字符串的表达方式不一样。总之,这部分涉及到字符串到对象的转换,这很像 PropertyEditor,对吧?Spring MVC 中,可以为某个 Controller 定制数据绑定,即在被标注了 @InitBinder 的方法里写绑定逻辑,方法名可以随意,如:
在 Controller 里使用 @InitBinder 标注的初始化方法只能对一个 Controller 对应的 WebBinder 做定制。如果想在整个应用中共享绑定规则,可以为 AnnotationMethodHandlerAdapter 指定一个自定义的 org.springframework.web.bind.support.WebBindingInitializer 实例,这样可以避免在每个 Controller 中都重复定义几乎相同逻辑的 @InitBinder 的初始化方法。
结束该篇文章前,我们来看几个容易混淆的用于简化开发的配置: <mvc:annotation-driven />, <context:annotation-config/>, <context:component-scan />。
<mvc:annotation-driven /> 会做以下几件事:
很显然,错误是说,不支持 GET 请求,而你的代码:
仅支持 POST。这就是原因。
但问题是,我只是使用POST方式提交,不是使用GET
不可能,提示很明确了:Request method 'GET' not supported。你的请求方式不可能不是 GET。除非这是 spring mvc 的 bug。
很显然,错误是说,不支持 GET 请求,而你的代码:
仅支持 POST。这就是原因。
但问题是,我只是使用POST方式提交,不是使用GET
很显然,错误是说,不支持 GET 请求,而你的代码:
仅支持 POST。这就是原因。
这种情况下,改了 url,其实不用测试就能保证资源的映射。由于类变化了,肯定会要重启的。这种情况下,最好使用单元测试,不需要启动整个容器。
配置了<mvc:annotation-driven/>,的确不用再显式定义 HandlerMapping 和 HandlerAdaptor 了。但是,如果你要为 HandlerMapping 或 HandlerAdaptor 做定制化,即为它们自身的某些属性做某些设置,那就得你自己显式定义了。这个时候,最好不要在写 <mvc:annotation-driven/> 了。
这位朋友,你碰到这种情况,应该自己尝试下。我没碰到这种情况,我猜测,方法这样写:public void doSth(@RequestParam("key1") String[] keys);
这样写估计写对:public void doSth(@RequestParam("key1") List<String> keys);
OK,然后我随便建了个 spring mvc project,试了下,果然如此,两种方法都对。
所以,遇到问题,第一步应该做的是自己去实践下,去尝试下,而不是动不动就问。当然,问也是必需的一个过程,前提是你尝试后仍未解决才问哈。
恩,我尝试了,思路错了。
文档中也看到了。
Built-in support is available for converting a comma-separated string into an array/collection of strings or other types known to the type conversion system. For example a method parameter annotated with @RequestHeader("Accept") may be of type String but also String[] or List<String>.
这位朋友,你碰到这种情况,应该自己尝试下。我没碰到这种情况,我猜测,方法这样写:public void doSth(@RequestParam("key1") String[] keys);
这样写估计写对:public void doSth(@RequestParam("key1") List<String> keys);
OK,然后我随便建了个 spring mvc project,试了下,果然如此,两种方法都对。
所以,遇到问题,第一步应该做的是自己去实践下,去尝试下,而不是动不动就问。当然,问也是必需的一个过程,前提是你尝试后仍未解决才问哈。
方法注解。spring另一个实现类。具体名字忘记
你说的这个问题我曾经考虑过,就我所掌握的知识而言,基于注解的方式貌似达不到这个效果。既然是注解,就是必须在方法上写 @RequestMapping。
不过,注解,是一种特殊的 HandlerMapping,我们可以使用其它的 HandlerMapping,即,将 Controller 注册到 spring 容器,并配置合适的 MethodNameResolver,即可以达到你想要的效果。
那为什么还要用基于注解的 Controller 呢?Spring MVC 在 Spring 2.5 发布中新添加了一种基于注解的 Controller 形式。借助于与 Spring 2.5 一同发布的容器内 <context:component-scan> 功能支持,基于注解的 Controller 几乎可以达到 XML 零配置,进而极大地提高我们的开发效率。
和其它 Controller 一样,基于注解的 Controller 同样有相应的 HandlerMapping,那就是 DefaultAnnotationHandlerMapping。同样,也有相应的 HandlerAdapter,那就是 AnnotationMethodHandlerAdapter。甚至,我们都可以不把 Controller 注册到容器里,那么肯定需要一种机制来帮助我们完成这点,这就是 <context:component-scan>。开发基于注解的 Controller,我们需要做以下准备工作:
● <context:compnent-scan>
<!-- 切记,这不是必需的!除非你把注解的 Controller 一个个的注册到容器中。相信大家还是喜欢用 context:compnent-scan 吧。不要认为在 Spring MVC 中才提到 context:component-scan,就认为它只能扫描 @Controller。component-scan 默认扫描的注解类型是 @Component,不过,在 @Component 语义基础上细化后的 @Repository, @Service 和 @Controller 也同样可以获得 component-scan 的青睐 --> <context:component-scan base-package="org.zachary.spring3.anno.web" />
● HandlerMapping
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <description> 这点是必需的还是非必需的呢? 如果定义了 DefaultAnnotationHandlerMapping,它就可以将请求来的 url 和被注解了 @RequesMapping 的指进行匹配。当然,说这句话的前提是定义 DefaultAnnotationHandlerMapping 的优先级比定义了其它的 HandlerMapping 的优先级要高(如果定义了其它的话)。 如果没有定义 DefaultAnnotationHandlerMapping,并不代表不能映射到相应的 handler 上。因为如果你定义了其它的 HandlerMapping,请求过来的 url 和注解了的 @RequestMapping 里的值正好能匹配上,那么没有 DefaultAnnotationHandlerMapping,@Controller 一样可以如鱼得水的被捕获到。 当然,如果你要使用基于注解的 @Controller,最好还是老老实实地注册 DefaultAnnotationHandlerMapping。 </description> </bean>
● HandlerAdaptor
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <description> 和上面的 HandlerMapping 一样,是必需的还是非必需的呢? Spring MVC 中,如果我们没有注册任何 HandlerAdaptor 到容器中,注意,我说的是任何。那么 DispatcherServlet 将启用后备的几个默认使用的 HandlerAdaptor 实现,包括: org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter org.springframework.web.servlet.mvc.AnnotationMethodHandlerAdaptor 看见没,如果我们没有注册任何的 HandlerAdaptor,框架会准备 AnnotationMethodHandlerAdaptor 的。可是由于某些原因,我们需要为某些 HandlerAdaptoer 进行一些定制化,即在容器中注册了某个 HandlerAdaptor,那么很抱歉,框架只会启用你注册的那个,而框架本身准备的不会被启用。所以,你一旦为某个 HandlerMapping 进行了定制化,请别忘了把其它的 HandlerAdaptor 也注册进来,即便这些不需要定制化。否则的话,后果你是可以想象的。当然,除非你确保你真的只需要那一个你注册进容器的 HandlerAdaptor,否则,我再啰嗦一遍,别忘了把其它的 HandlerAdaptor 也注册进来。 </description> </bean>
好了,有了以上几点准备工作,我们就可以开始基于注解的 Controller 之旅了。下面我们来一个一个注解的来讲解。
● @Controller
/** * @Controller,类级别上的注解。我们定义的类可以只是一个 javabean,不需要实现任何接口。标注了 * @Controller,借助 <context:component-scan>,框架能自动识别到这就是一个 Controller */ @Controller public class MyController { // ...... }
● @RequestMapping
/** * @RequestMapping 可以出现在类级别上,也可以出现在方法上。如果出现在类级别上,那请求的 url 为 类级别 * 上的 @RequestMapping + 方法级别上的 @RequestMapping,否则直接取方法级上的 @RequestMapping。 * 类级别的 @RequestMapping 不是必需的。 */ @Controller @RequestMapping("/my") public class MyController { /** * 由于类级别上定义了 @RequestMapping,那么想匹配到这个方法来处理请求,url 必须为 /my/somelist。 * 如果没有定义类级别上的 @RequestMapping,url 为 /somelist 即可。同时,请求方法必须为 POST */ @RequestMapping(value="/somelist", method=RequestMethod.POST); public String getSomeList() {...} /** * 在方法级别使用 @RequestMapping 来限定请求处理的时候,可以指定两个属性。除了我们在上面刚使用过的 * method 属性,还有一个 params 属性。使用 params 属性,可以达到与使用 * ParameterMethodNameResolver 作为 MethodResolver的 MultiActionController 类似的功能。 * * params 有两种表达形式,这里先说第一种:"parameterName=parameterValue" * * 请求方法为 GET 或 POST,且具有 hello 参数,且值为 world 的请求才能匹配到该方法,如: * /my?hello=world */ @RequestMapping(params="hello=world", method={RequestMethod.GET, RequestMethod.POST}) public String helloworld() {...} /** * 请求方法为 GET 或 POST,且具有 hello 参数,且值为 java 的请求才能匹配到该方法,如: * /my?hello=java */ @RequestMapping(params="hello=java", method={RequestMethod.GET, RequestMethod.POST}) public String hellojava() {...} /** * params 属性的另外一种表达形式为:"parameter" * * 请求方法为 GET,且具有请求参数 java 即匹配此方法,而不管 java 参数的值是什么,如: * /my?java=anything */ @RequestMapping(params="java", method={RequestMethod.GET}) public String java() {...} /** * 请求方法为 GET,且具有请求参数 cplusplus 即匹配此方法,而不管 cplusplus 参数的值是什么,如: * /my?cplusplus=anything */ @RequestMapping(params="cplusplus", method={RequestMethod.GET}) public String cplusplus() {...} /** * @RequestMapping 还有一个参数化 headers,它和 params 非常相似,也有两种表达式,只不过它是对 * 请求头做限制罢了。大家可以通过 telnet 或 http-client 来发类似的请求以检验。以 telnet 为例: * * telnet localhost 8080 * POST /contextPath/my HTTP/1.1 * Host: localhost * hello: world # 这个就是自定义请求头,和标准的请求头的写法别无二致 * 【回车】 * 【回车】 */ @RequestMapping(headers="hello=world", method={RequestMethod.POST}) public String cplusplus() {...} }
● @RequestParam(将请求参数绑定到方法参数)
@Controller @RequestMapping("/my") public class MyController { /** * 注意,这里的方法有一个参数。若请求 url 为 /my/test,会匹配此方法。这里的方法的参数名为 userId, * 那么请求参数中一定有名为 userId 的参数,且值为整数。这也是默认的绑定行为,它是根据名称匹配原则进行 * 的数据绑定。当请求中的参数名与方法名一致的时候,相应的参数值将被绑定到相应的方法参数上。 * * 如果没有传递 userId 参数,框架会传入 null。可是这里我们定义的是 primitive type,异常伺候!若 * 要解决此问题,需要将 primitive type 定义成相应的 wrapper type 即可,这里使用 Integer 就行了。 * * 如果传递了 userId 参数,但值不是整数,你叫 test 怎么办呢?这种情况下,框架借助 PropertyEditor * 数据类型转换失败,ExceptionResolver 会接手处理,请求是不会进入 test 方法的。 * * 这种方式下,默认的绑定行为需要我们严格遵守命名一致性原则。如果我们对此不满,想自定义绑定关系,可以求 * 助于 @RequestParam。 */ @RequestMapping("/test") public String test(int userId) { ... } /** * 当我们不想使用 userId 作为方法的参数名,即不想使用默认的数据绑定方式。如果我们要使用 id 作为方法 * 的参数,为了保证名称为 userId 的请求参数可以绑定到新的名称为 id 的方法参数上,我们就可以使用 * @RequestParam 对这一参数进行标注。@RequestParam 只可以标注于方法参数上。 * * 如果请求参数中有 age,和方法的参数名称一致,故 age 参数不需要 @RequestParam 标注。如果没有传递 * age,我们又不想定义成 Integer,很显然框架会注入 null 值,报错是必然的。这是由于 @RequestParam * 的 required 属性决定的,默认就是 true。如果我们定义成 false, * 即 @RequestParam(required=false) int age * 这个时候定义成 int 型的 age,即便请求参数没有 age 参数,也是没问题的。 * * 同时,这里还能绑定 Date 类型,User 对象类型等等。如 date=2011-01-01&userName=Tom&userAge=18 * 这里,User 类的属性需要为 userName 和 userAge,以免和 age,name 混淆。所以,Spring MVC 对对象 * 的数据绑定就没有 Struts2 做的那么好了,Strtus2 可以这样:user.age=18&user.name=Tom */ @RequestMapping("/test2") public String test2(@RequestParam("userId") int id, int age, Date date, User user) { ... } }
● @PathVariable(将 url template 里的参数绑定到方法参数)
@Controller @RequestMapping("/my") public class MyController { /** * @PathVariable 是 url 模板,需要和 @RequestMapping 配合起来使用,这是 Spring 3.0 之后引入的。 * * 在这个例子中,请求的 url 必须满足类似 /my/user/zhangsan/18 这样的格式才能匹配方法。url 模板里 * 的参数名和方法参数名的绑定规则和 @RequestParam 类似,这里就不再赘述了。 * * @PathVariable 和 @RequestParam 的区别在于: * @PathVariable 的 url:/my//user/zhangsan/18 * @RequestParam 的 url:/my//user?nickname=zhangsan&age=18 */ @RequestMapping("/user/{nickname}/{age}"); public String getUserInfo(@PathVariable("nickname") String name, @PathVariable int age) {...} }
● @RequestBody(将请求正文绑定到方法参数)
/** * 来看一个 http 请求: * (请求行) POST /my HTTP/1.1 * (请求头) Host: localhost * (请求头) Content-Type: text/plain * (请求头) Content-Length: 5 * * (请求体) hello * * 这里的 hello,就是请求体,也称 request message。若有请求体,则必须提供请求体的类型和长度,这些信 * 息是写在请求头里的,即 Content-Type 和 Content-Length */ @Controller @RequestMapping("/my") public class MyController { /** * 我们定义的 body 的数据类型是 String,请求体嘛,肯定是 String。实际上,@RequestBody 是用于将请 * 求体的内容绑定到方法参数上,数据类型不一定是 String。Spring MVC 是通过 HttpMessageConverter * 来完成这种转换的。AnnotationMethodHandlerAdapter 默认注册了一些 HttpMessageConverters: * ByteArrayHttpMessageConverter - converts byte arrays * StringHttpMessageConverter - converts strings * FormHttpMessageConverter - converts form data to/from MultiValueMap<String,String> * SourceHttpMessageConverter - convert to/from a javax.xml.transform.Source * MappingJacksonHttpMessageConverter - converts json * MarshallingHttpMessageConverter - convert to/from an object using the * org.springframework.oxm package. * * 正如上所述,HttpMessageConverter 用于从请求正文绑定到对象和把对象序列化成 String 予客户端响应。 * 即 HttpMessageConverter is responsible for converting from the HTTP request message to * an object and converting from an object to the HTTP response body * * 我们可以在 AnnotationMethodHandlerAdapter 定义任意多的 HttpMessageConverters。 * * 既然 HttpMessageConverter 可以用于双向 convert,这里讨论的是 @RequestBody,那这部分我们只讲 * converting from the HTTP request message to an object。 * * 假设我们只向 AnnotationMethodHandlerAdapter 注入了 MappingJacksonHttpMessageConverter 和 * MarshallingHttpMessageConverter。处理请求的方法有如下签名: * public String test(@RequestBody User user) { ... } * * 不管请求正文的内容是什么,对于客户端和服务器而言,它们只是用文本来互相通信。把字符串转为 User 对 * 象,该用哪个 HttpMessageConverter 来完成此项工作呢? * * 在定义 HttpMessageConverters 时,我们可以为其指定 supportedMediaTypes。对于将请求正文转为对象 * 这个方向的操作,HttpMessageConverters 会从请求头得到 Content-Type 头信息,看其是否隶属于其定义 * 的 supportedMediaTypes。若没有匹配上,则会使用下一个 HttpMessageConverter 做同样的判断。只要 * 某个 HttpMessageConverter 支持请求头中的 Content-Type,那么就会应用此 HttpMessageConverter * 来将 String 转为 Object。当然,若请求正文并没有按照 Content-Type 所规定的格式来编写,必然要收到 * 500 的响应。同时请注意,请求头中还必须提供 Content-Length,否则拿不到请求正文。 * * 如果所有的 HttpMessageConverters 中定义的 supportedMediaTypes 均不能匹配上 Content-Type 请 * 求头中的类型,那么就会收到 415 Unsupported Media Type 响应。 */ @RequestMapping("/user/body"); public String getBody(@RequestBody String body) { // 这里的 body 的内容就是 hello System.out.println(body); return null; } }
● @ResponseBody(将处理完请求后返回的对象绑定到响应正文)
/** * 上面的 @RequestBody 讲了 HttpMessageConverter 从请求正文到对象转换的方向,现在来讲讲另外一个方 * 向,@ResponseBody,此时,HttpMessageConverter 用于将处理完请求后返回的对象序列化成字符串,即 * converting from an object to the HTTP response body. */ @Controller @RequestMapping("/my") public class MyController { /** * 该方法的返回类型是 User,并不符合含有 @RequestMapping 的注解所需的签名方式。但它仍然是合法的,因 * 为在返回类型前有 @ResponseBody 注解,此注解将告知框架,将 User 对象作为影响正文返回?什么?对象 * 作为响应正文!所以,HttpMessageConverter 在这里就起到作用了。这里讨论的是 @ResponseBody,所以 * 这里我们只讲 converting from an object to the HTTP response body。 * * User 对象要转成什么样的 String,或者说要转成什么格式的 String?这个时候需要从请求头中获得此信息 * 了,这里,就是请求头的 Accept 头。Accept 头可以使用逗号分隔定义多个类型,用以告知服务器我只接受 * 哪些类型的响应。AnnotationMethodHandlerAdapter 中同样注入了多个 HttpMessageConverter,每个 * HttpMessageConverter 都可以定义各自的 supportedMediaTypes。这个时候该用哪个 * HttpMessageConverter 来完成对象到文本的序列化操作呢? * * 遍历 Accept 头中的每种媒体类型,在定义的多个 HttpMessageConverters 中依次去匹配,若匹配上,就使 * 用该 HttpMessageConverter 来完成序列化操作,并且响应头的 Content-Type 并不是请求头 Accept 头 * 的诸多类型中第一个被匹配的类型,而是匹配到的 HttpMessageConverter 定义的 supportedMediaTypes * 中的第一个类型。 * * 如果所有的 HttpMessageConverters 中定义的 supportedMediaTypes 均不能匹配上 Accept 请求头中 * 的诸多的类型,那么就会收到 406 Not Acceptable 响应。 */ @RequestMapping("/user") public @ResponseBody User getUser() { return new User(18, "Jack", "计算机"); } }
● @ModelAttribute
/** * @ModelAttribute 可以为视图渲染提供更多的模型数据,而不需要在处理请求的方法里添加 ModelMap 或 * Model 类型的参数。 * * @ModelAttribute 可以标注在方法(存数据)上,也可以标注在方法参数(取数据)上。 */ @Controller @RequestMapping("/my") public class MyController { /** * 在处理该请求时,方法的返回类型是 User,貌似不符合返回类型的规范。由于这里使用了 @ModelAttribute * 注解,表示将返回的对象以 "user" 为 key 放入模型数据里。这里的 key 值默认值是返回的数据类型首字母 * 小写的结果。如果想自定义 key,可以写成 @ModelAttribute("myAttribute"),那么模型数据将会将 * User 对象绑定到 key 为 "myAttribute" 上。 * * jsp 里可以这样访问模型里的数据: * age: ${user.age} * name: ${user.name} * job: ${user.job} * * 当然,这里只是提到了 @ModelAttribute 存数据的操作。 */ @RequestMapping("/user") @ModelAttribute public User getUser() { return new User(18, "Jack", "计算机"); } /** * 这里将 @ModelAttribute 标注在方法参数上,表示要从模型数据里取 key 为 "user" 的对象,绑定在方法 * 参数上。如果这样做的话,其实你是得不到上面的那个请求放入的 User 对象,得到的是另外一个对象。其实 * 也好理解,这是两个互相独立的请求,作用域不一样。要想达到我们的目的,即能够从模型数据里取数据,需要 * 求助于 @SessionAttributes */ @RequestMapping("/user2") public String showUser(@ModelAttribute User user) { System.out.println(user); return null; } }
● @SessionAttributes
/** * @SessionAttributes 和 @ModelAttribute 类似,只不过 @SessionAttributes 是将数据存放于 session * 中或从 session 中取数据。 * * @SessionAttributes 只能应用在类型声明上。比如下面的类的声明中,只有属性名为 "the-attribute" 的数 * 据才会纳入到 session 的管理。 * * @SessionAttributes 允许以属性名名称或者类型两种方法,来表明将哪些数据通过 session 进行管理。这里 * 我们使用的是指定属性名称的方式,但通过类型来指定也是可行的,如: * @SessionAttributes(types=User.class) */ @Controller @RequestMapping("/my") @SessionAttributes("the-attribute") public class MyController { @RequestMapping("/getUser") public String getUser(int userId, Model model) { /** * 注意,这里将 User 对象添加到属性名为 "the-attribute" 上,所以 User 对象将纳入到 session 的 * 管理。如果这里添加的对象的属性名不是 "the-attribute",那么它只会作用于当前请求,而不会纳入到 * session 的管理中。 */ User user = userService.getUserById(userId); model.addAtrribute("the-attribute", user); return "userinfo"; } /** * 将模型里的 "the-attribute" 为 key 的对象绑定到 User 类上。由于在类级别上声明了只有 "the- * attribute" 的属性名才会纳入到 session 的管理,所以就解决了在 @ModelAttribute 注解中讲解中最 * 后提到的问题。 * * 另外,这个方法还有两个参数,BindingResult 和 SessionStatus。由于这里有绑定数据的动作,我们可以 * 根据 BindingResult 对象获得数据绑定结果以决定后继流程该如何处理。SessionStatus 在这里用于处理 * 完请求后,清空 session 里的数据。 */ @RequestMapping("/updateUser") public String updateUser(@ModelAttribute("the-attribute") User user, BindingResult result, SessionStatus status) { if (result.hasErrors) { return "error"; } userService.updateUser(user); // 我们通过调用 status.setComplete() 方法,该 Controller 所有放在 session 级别的模型属性数据 // 将从 session 中清空 status.setComplete(); return "redirect:getUser?userId=" + user.getId(); } }
Spring MVC 里的大部分的注解,这里基本上都讲到了。日后随着 Spring 的升级,我也会逐一补充新加的注解。其实,仅凭以上的注解,是可以构建一个足够强大的 RESTFul Webservices 的了。
这里,补充讲下被标注了 @RequestMapping 注解的请求方法的签名。使用 @RequestMapping 标注的 web 请求处理方法的签名比较灵活,我们几乎可以声明并使用任何类型的方法参数。不过,以下几种类型的方法参数将拥有更多语义,它们均来自框架内部(或者说 AnnotationMethodHandlerAdapter)所管理的对象引用:
- request/response/session
- org.springframework.web.context.request.WebRequest。当前处理方法中获得可用的 WebRequest 实例。
- java.util.Locale。通过相应的 LocalResolver 所返回的对应当前 web 请求的 Locale。
- java.io.InputStream/java.io.Reader。相当于 request.getInputStream() 或 request.getReader() 所获得的对象引用。
- java.io.OutputStream/java.io.Writer。相当于 response.getOutputStream() 或 response.getWriter() 所获得的对象引用。
- java.util.Map/org.springframework.ui.ModelMap。你现在可用对模型数据为所欲为了。
- org.springframework.validation.Errors/org.springframework.validation.BindingResult。用于对 Command 对象进行数据验证的 Errors 或者 BindingResult 对象。声明这两种类型的方法参数有一个限制,它们的声明必须紧跟着 Command 对象的定义。其它类型的方法参数是没有任何顺序限制的。
- org.springframework.web.bind.supportt.SessionStatus。SessionStatus 主要用于管理请求处理之后 Session 的状态,比如清除 Session 中的指定的数据。
基于注解的 Controller 的请求处理方法返回类型可以有如下 4 种形式(当然,前面提到的 @ResponseBody 和 @ModelAttribute 并没下面所描述的返回类型,具体参见上面对各自注解的讲解):
- org.springframework.web.servlet.ModelAndView。这个不用多说,视图信息和模型信息都能通过它返回。
- java.lang.String。该类型返回值代表逻辑视图名,模型数据需要以其它形式提供,比如为处理方法声明一个 ModelMap 类型的参数。注意,如果返回 null,并不代表向客户端输出空页面(定向思维惹的祸),这种情况下,框架会从请求路径中提取视图信息。如果返回 null 就是要表示方法内部已处理完请求,也不需要通知页面,就是想仅仅返回空白页面,唉,我还没有想出来咋整。。。反正 writer.write("") 这样写可以,还得声明一个 Writer 类型的方法参数。
- org.springframework.ui.ModelMap。ModelMap 类型返回值只包含了模型数据信息而没有视图信息,框架将根据请求的路径来提取视图信息。
- void。没有任何返回值,视图信息将从请求路径中提取,模型数据需要通过其它形式提供。
String 类型的返回值为 null, 还有返回类型为 ModelMap 和 void,从请求路径中如何提取视图信息呢?框架将截取请求路径中的最后一个 / 后面的内容,并去掉后缀名,剩下来的内容就是视图名。如请求路径为 /spring3/user/welcome,那么视图名是 welcome,/spring3/user/welcome.action 的视图名也是 welcome。
接下来来讲最后一个部分,请求参数到方法参数的绑定。这个在 @RequestParam 中已经讲过,不过,这里要讲的是绑定复杂的对象。在 @RequestParam 中,我们这样请求,date=2011-01-01 其实是绑定不到 Date 对象的。因为不同的 Locale 处理日期的字符串的表达方式不一样。总之,这部分涉及到字符串到对象的转换,这很像 PropertyEditor,对吧?Spring MVC 中,可以为某个 Controller 定制数据绑定,即在被标注了 @InitBinder 的方法里写绑定逻辑,方法名可以随意,如:
/** * 初始化方法不能有返回值,而且至少应该有一个类型为 org.springframework.web.bind.WebDataBinder 的 * 方法参数。同时,一个典型的基于注解的 Controller 的处理方法可以使用的方法参数中,除了 Command 对象 * 以及相关的 Errors/BindingResult 对象作为方法的参数外,都可以作为初始化方法的参数。 * * 这里,我们没有必要为日期再定制自定义绑定规则,Spring 已经为我们提供了 CustomDateEditor,这里只是演 * 示如何提供自定义数据绑定规则。 * * 这里的 WebDataBinder,是不是很像 PropertyEditorRegistry? */ @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Date.class, new PropertyEditorSupport() { final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); @Override public void setAsText(String text) throws IllegalArgumentException { try { Date date = sf.parse(text); setValue(date); } catch (ParseException e) { Date data = sf.parse(text); throw new IllegalArgumentException(e); } } }) }
在 Controller 里使用 @InitBinder 标注的初始化方法只能对一个 Controller 对应的 WebBinder 做定制。如果想在整个应用中共享绑定规则,可以为 AnnotationMethodHandlerAdapter 指定一个自定义的 org.springframework.web.bind.support.WebBindingInitializer 实例,这样可以避免在每个 Controller 中都重复定义几乎相同逻辑的 @InitBinder 的初始化方法。
public class MyBindingInitializer implements WebBindingInitializer { public void initBinder(WebBinder binder, WebRequest request) { binder.registerCustomEditor(SomeDataType.class, somePropertyEditor) // 如果需要,这里可以继续注册更多的 propertyEditor // ...... } }
<bean class=""org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter> <property name="webBindingInitializer"> <bean class="...MyBindingInitializer" /> </property> </bean>
结束该篇文章前,我们来看几个容易混淆的用于简化开发的配置: <mvc:annotation-driven />, <context:annotation-config/>, <context:component-scan />。
<mvc:annotation-driven /> 会做以下几件事:
- 向 spring 容器中注册 DefaultAnnotationHandlerMapping。
- 向 spring 容器中注册 AnnotationMethodHandlerAdapter。
- 配置一些 messageconverter。
- 解决了 @Controller 注解的使用前提配置,即 HandlerMapping 能够知道谁来处理请求。
- 向 spring 容器中注册 AutowiredAnnotationBeanPostProcessor。
- 向 spring 容器中注册 CommonAnnotationBeanPostProcessor。
- 向 spring 容器中注册 PersistenceAnnotationBeanPostProcessor。
- 向 spring 容器中注册 RequiredAnnotationBeanPostProcessor。
- 使用 <context:annotationconfig />之前,必须在 <beans> 元素中声明 context 命名空间 <context:component-scan />。<context:component-scan /> 对包进行扫描,实现注解驱动 Bean 定义。即,将 @Controller 标识的类的 bean 注册到容器中。
评论
22 楼
lIO01
2016-02-24
你能不能别用自己照片当头像?
21 楼
zachary.guo
2014-02-25
didoguan 写道
zachary.guo 写道
didoguan 写道
你好!出现了如下问题,请问我是哪里没有配置好呢?
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
很显然,错误是说,不支持 GET 请求,而你的代码:
@RequestMapping(value="/maincontent", method=RequestMethod.POST)
仅支持 POST。这就是原因。
但问题是,我只是使用POST方式提交,不是使用GET
不可能,提示很明确了:Request method 'GET' not supported。你的请求方式不可能不是 GET。除非这是 spring mvc 的 bug。
20 楼
didoguan
2014-02-23
zachary.guo 写道
didoguan 写道
你好!出现了如下问题,请问我是哪里没有配置好呢?
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
很显然,错误是说,不支持 GET 请求,而你的代码:
@RequestMapping(value="/maincontent", method=RequestMethod.POST)
仅支持 POST。这就是原因。
但问题是,我只是使用POST方式提交,不是使用GET
19 楼
zachary.guo
2014-02-22
didoguan 写道
你好!出现了如下问题,请问我是哪里没有配置好呢?
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
很显然,错误是说,不支持 GET 请求,而你的代码:
@RequestMapping(value="/maincontent", method=RequestMethod.POST)
仅支持 POST。这就是原因。
18 楼
didoguan
2014-02-21
你好!出现了如下问题,请问我是哪里没有配置好呢?
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
2014-2-21 21:37:26 org.springframework.web.servlet.PageNotFound handleHttpRequestMethodNotSupported
警告: Request method 'GET' not supported
<form id="form1" method="post" action="<%=basePath %>/maincontent"><input type="text" id="username" name="username"><input type="submit" value="提交"></form>
@RequestMapping(value="/maincontent", method=RequestMethod.POST) public String toMainPage() { System.out.println("=================进入主页"); return "/main/main"; }
<?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:p="http://www.springframework.org/schema/p" 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-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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="com.vaizn.data" ></context:component-scan> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <!-- 配置视图映射转换器 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="stringConverter" /> <ref bean="jsonConverter" /> <ref bean="xmlConverter" /> </list> </property> </bean> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes" value="application/json;charset=UTF-8" /> </bean> <bean id="stringConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>text/plain;charset=UTF-8</value> </list> </property> </bean> <bean id="xmlConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <property name="supportedMediaTypes" value="application/xml;charset=UTF-8" /> <property name="marshaller" ref="castorMarshaller"/> <property name="unmarshaller" ref="castorMarshaller"/> </bean> <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" /> <!-- 对静态资源文件的访问 --> <mvc:default-servlet-handler/> <!-- 视图解释类 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/pages/"/> <property name="suffix" value=".jsp"/> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean> </beans>
17 楼
zachary.guo
2014-02-15
honglei0412 写道
您好请教一下,关于springmvc 在控制层controller 里面修改一个url地址后您这边就是说有没有重新启动tomcat应用哈,如果没有的话能不能说一下您这边是怎么做的哈,多谢
这种情况下,改了 url,其实不用测试就能保证资源的映射。由于类变化了,肯定会要重启的。这种情况下,最好使用单元测试,不需要启动整个容器。
16 楼
honglei0412
2014-02-14
您好请教一下,关于springmvc 在控制层controller 里面修改一个url地址后您这边就是说有没有重新启动tomcat应用哈,如果没有的话能不能说一下您这边是怎么做的哈,多谢
15 楼
ccnu_ouy520
2013-09-26
写的太好了,受教了,谢谢
我遇到的问题还在尝试阶段
我们项目用的是:<mvc:annotation-driven />
现在我添加 <context:component-scan base-package
这个后就出现问题了
去掉上面的,服务能起来,但是访问有问题
其实我最想做的,web项目应该一个请求一个事物,这个地方用的 <context:component-scan base-package作为控制,如何在这个控制中添加一个事物管理了
我遇到的问题还在尝试阶段
我们项目用的是:<mvc:annotation-driven />
现在我添加 <context:component-scan base-package
这个后就出现问题了
去掉上面的,服务能起来,但是访问有问题
其实我最想做的,web项目应该一个请求一个事物,这个地方用的 <context:component-scan base-package作为控制,如何在这个控制中添加一个事物管理了
14 楼
zachary.guo
2013-09-14
cxl2012 写道
写的很棒,顺便请教个问题,<mvc:annotation-driven/>
1.向 spring 容器中注册DefaultAnnotationHandlerMapping。
2.向 spring 容器中注册 AnnotationMethodHandlerAdapter。
可不可以这样说,在配置文件中配置了<mvc:annotation-driven/>就不需要配置
HandlerMapping 和 HandlerAdaptor了?我们公司项目中三个都配置了,有点困惑,求解惑,谢谢!
1.向 spring 容器中注册DefaultAnnotationHandlerMapping。
2.向 spring 容器中注册 AnnotationMethodHandlerAdapter。
可不可以这样说,在配置文件中配置了<mvc:annotation-driven/>就不需要配置
HandlerMapping 和 HandlerAdaptor了?我们公司项目中三个都配置了,有点困惑,求解惑,谢谢!
配置了<mvc:annotation-driven/>,的确不用再显式定义 HandlerMapping 和 HandlerAdaptor 了。但是,如果你要为 HandlerMapping 或 HandlerAdaptor 做定制化,即为它们自身的某些属性做某些设置,那就得你自己显式定义了。这个时候,最好不要在写 <mvc:annotation-driven/> 了。
13 楼
cxl2012
2013-09-06
写的很棒,顺便请教个问题,<mvc:annotation-driven/>
1.向 spring 容器中注册DefaultAnnotationHandlerMapping。
2.向 spring 容器中注册 AnnotationMethodHandlerAdapter。
可不可以这样说,在配置文件中配置了<mvc:annotation-driven/>就不需要配置
HandlerMapping 和 HandlerAdaptor了?我们公司项目中三个都配置了,有点困惑,求解惑,谢谢!
1.向 spring 容器中注册DefaultAnnotationHandlerMapping。
2.向 spring 容器中注册 AnnotationMethodHandlerAdapter。
可不可以这样说,在配置文件中配置了<mvc:annotation-driven/>就不需要配置
HandlerMapping 和 HandlerAdaptor了?我们公司项目中三个都配置了,有点困惑,求解惑,谢谢!
12 楼
sealedbook
2013-08-27
zachary.guo 写道
sealedbook 写道
zachary.guo
谢谢你分享这部分内容,我有个问题
@RequestMapping中的param会匹配请求过来的参数,如果请求过来是一个数组的话应该怎么写?比如
这时候应该怎么办呢?
谢谢你分享这部分内容,我有个问题
@RequestMapping中的param会匹配请求过来的参数,如果请求过来是一个数组的话应该怎么写?比如
<input name="key1" value="value1"/> <input name="key1" value="value2"/>
这时候应该怎么办呢?
这位朋友,你碰到这种情况,应该自己尝试下。我没碰到这种情况,我猜测,方法这样写:public void doSth(@RequestParam("key1") String[] keys);
这样写估计写对:public void doSth(@RequestParam("key1") List<String> keys);
OK,然后我随便建了个 spring mvc project,试了下,果然如此,两种方法都对。
所以,遇到问题,第一步应该做的是自己去实践下,去尝试下,而不是动不动就问。当然,问也是必需的一个过程,前提是你尝试后仍未解决才问哈。
恩,我尝试了,思路错了。
文档中也看到了。
Built-in support is available for converting a comma-separated string into an array/collection of strings or other types known to the type conversion system. For example a method parameter annotated with @RequestHeader("Accept") may be of type String but also String[] or List<String>.
11 楼
zachary.guo
2013-08-13
sealedbook 写道
zachary.guo
谢谢你分享这部分内容,我有个问题
@RequestMapping中的param会匹配请求过来的参数,如果请求过来是一个数组的话应该怎么写?比如
这时候应该怎么办呢?
谢谢你分享这部分内容,我有个问题
@RequestMapping中的param会匹配请求过来的参数,如果请求过来是一个数组的话应该怎么写?比如
<input name="key1" value="value1"/> <input name="key1" value="value2"/>
这时候应该怎么办呢?
这位朋友,你碰到这种情况,应该自己尝试下。我没碰到这种情况,我猜测,方法这样写:public void doSth(@RequestParam("key1") String[] keys);
这样写估计写对:public void doSth(@RequestParam("key1") List<String> keys);
OK,然后我随便建了个 spring mvc project,试了下,果然如此,两种方法都对。
所以,遇到问题,第一步应该做的是自己去实践下,去尝试下,而不是动不动就问。当然,问也是必需的一个过程,前提是你尝试后仍未解决才问哈。
10 楼
sealedbook
2013-08-13
zachary.guo
谢谢你分享这部分内容,我有个问题
@RequestMapping中的param会匹配请求过来的参数,如果请求过来是一个数组的话应该怎么写?比如
这时候应该怎么办呢?
谢谢你分享这部分内容,我有个问题
@RequestMapping中的param会匹配请求过来的参数,如果请求过来是一个数组的话应该怎么写?比如
<input name="key1" value="value1"/> <input name="key1" value="value2"/>
这时候应该怎么办呢?
9 楼
在世界的中心呼喚愛
2013-05-26
YYang5968 写道
类上面写@RequestMapping,能指定执行的方法吗,就是通过URL来指定到Controller里面的方法,不想在方法的@RequestMapping里面写("/方法名")
方法注解。spring另一个实现类。具体名字忘记
8 楼
johncheen
2013-05-09
很仔细,真的很仔细,很具体。学习了2个小时
7 楼
zachary.guo
2013-04-18
YYang5968 写道
类上面写@RequestMapping,能指定执行的方法吗,就是通过URL来指定到Controller里面的方法,不想在方法的@RequestMapping里面写("/方法名")
你说的这个问题我曾经考虑过,就我所掌握的知识而言,基于注解的方式貌似达不到这个效果。既然是注解,就是必须在方法上写 @RequestMapping。
不过,注解,是一种特殊的 HandlerMapping,我们可以使用其它的 HandlerMapping,即,将 Controller 注册到 spring 容器,并配置合适的 MethodNameResolver,即可以达到你想要的效果。
6 楼
YYang5968
2013-04-14
类上面写@RequestMapping,能指定执行的方法吗,就是通过URL来指定到Controller里面的方法,不想在方法的@RequestMapping里面写("/方法名")
5 楼
pyfhua
2012-11-19
感谢!学习!
4 楼
kevin_java_eye
2012-10-17
3 楼
virusfu
2012-07-03
不错
发表评论
-
Spring MVC 中的 forward 和 redirect
2012-12-28 20:53 86786Spring MVC 中,我们在返回逻辑视图时 ... -
Spring MVC 中处理静态资源
2012-12-28 20:52 6496Spring MVC 中的核心 servlet ... -
Spring MVC 概述
2011-12-31 15:29 78现在,开始我们的 Spring MVC 之旅。 ... -
Spring MVC 中的 HandlerMapping 和 Controller
2011-12-31 15:29 84作为 Spring MVC 框架,接受请求并进 ... -
Spring MVC 中的 HandlerExceptionResolver
2011-12-29 22:24 161Spring MVC 中作为处理请求的 han ... -
PropertyEditor 拾遗
2011-12-19 20:50 0PropertyEditor,说熟悉也熟悉,说 ... -
Spring MVC 中的 HandlerInterceptor
2011-12-12 22:04 22889在做 web 开发中,特别是使用 MVC 框架 ... -
Spring MVC 中的 HandlerAdaptor
2011-12-08 15:20 141Spring MVC 中 ... -
Spring MVC 中的 MultipartResolver
2011-12-06 21:26 185MultipartResolver 在 Spr ... -
Spring MVC 中的 ViewResolver 和 View
2011-12-05 19:16 99常用的 ViewResolver 有 Inte ... -
基于 Spring 构建的 web 应用程序的 ApplicationContext 分析
2011-11-25 12:33 111在使用 Spring ...
相关推荐
Spring Mvc AOP通过注解方式拦截controller等实现日志管理
学习Spring MVC,关于注解的Spring MVC,简单例子,关于控制器的Spring MVC,学习Spring,简单Spring MVC实例
Spring MVC AOP通过注解方式拦截Controller等实现日志管理demo版本2
基于注解的spring mvc,dao 层注解:@Repository("userDao"), entity层注解:@Entity,service层注解:@Service("userService"), action层注解:@Controller("userController") @RequestMapping("/user.do")
基于注解的spring MVC讲解。包括基础知识,配置,还有Controller不同的返回值分析。
Spring MVC之Controller层的常用注解
Spring MVC基于Model-View-Controller(MVC)架构模式,优化了Web应用程序的设计和开发。在Spring MVC中,DispatcherServlet作为前端控制器,负责请求的接收和响应结果的处理。处理器映射器(HandlerMapping)和...
基于注解驱动的 Spring MVC,你还在配置实用框架,实现零配置是用spring框架。
Spring mvc注解方式实现Controller
此demo是基于注解的SpringMVC,结构清晰,新手可以参考一下,所有用到的jar包我都打包进去了;
Spring MVC是Spring框架中的一部分,全称是Spring Web MVC,主要用于实现MVC设计模式的Web框架。它分离了控制器、模型对象、过滤器以及处理程序对象的角色,使得它们更容易进行定制。 Spring MVC的优点包括: 基于...
有人问 Sping AOP用AspectJ注解的方式拦截不到SpringMVC的controller方法? 我这里提供了一种解决方法,仅供参考
使用spring-mvc 注解方式 注入 Controller 控制器 访问路径 精确到方法名 无需 多余注解 简单方便 附带实例
SpringMVC不能只使用@Controller而不使用@RequestMapping
工具类数据校验 jsp自定义标签 Spring自定义注解 默认requestMapping 1.1.2 代码生成器 1.1.3 首页修改 dateformat.js 时间参数转换 SpringMVC配置文件集中 快递参数接口 1.1.4 des加解密字符串和文件 1.1.5 redis...
关于Spring注解的配置,使用都有详细的注释说明 spring的MVC架构这里不是很明显,但LZ稍作添加即可!
Spring Web model-view-controller (MVC)框架是围绕 DispatcherServlet 设计的,并分发请求到处理程序(handler),Spring MVC支持可配置的处理程序映射(handler mapping),视图解析(view resolution)、 区域设置...
有包,可以部署上的,简单易理解,容易上手,可以用的
简单的模板spring mvc框架,实现了实例化controller、service,依赖注入等功能,可以下载学习一下,更加深入理解spring mvc框架