http://ttaale.iteye.com/blog/787586

spring 基于注解的控制器配置

  • 博客分类:
  • spring
SpringBeanServletMVCWeb

13.12. 基于注解的控制器配置

现时对于一些类型的配置数据有一个趋势,就是偏爱注解方式而不是XML文件。为了方便实现,Spring现在(从2.5开始)提供了使用注解配置 MVC框架下的组件的支持。

Spring 2.5为MVC控制器引入了一种基于注解的编程模型,在其中使用诸如@RequestMapping@RequestParam@ModelAttribute ,等等。 这种注解支持在Servlet MVC和Portlet MVC中均可使用。通过这种方式实现的控制器不必由特定的基类继承而来,或者实现特定的接口。 更进一步的,它们通常并不直接依赖于Servlet或Portlet API,虽然如果需要,它们可以方便的访问Servlet或Portlet的功能。

提示

Spring发行版本附带了PetClinic 示例,它是一个在简单的表单处理的上下文中, 利用了本节中说明的注解支持的Web应用程序。 可以在“samples/petclinic ”目录中找到PetClinic 应用程序。

另外一个建立在基于注解的Web MVC上的示例应用程序,请见imagedb 。 这个示例集中在无状态的multi-action控制器,包括多段文件上传的处理。 可以在“samples/imagedb ”目录找到imagedb 应用程序。

下面的章节记录了这些注解以及通常如何使用它们。

13.12.1. 建立dispatcher实现注解支持

只有对应的HandlerMapping (为了实现类型级别的注解)和/ 或HandlerAdapter (为了实现方法级别的注解)出现在 dispatcher中时, @RequestMapping 才会被处理。 这在DispatcherServletDispatcherPortlet 中都是缺省的行为。

然而,如果是在定义自己的HandlerMappingsHandlerAdapters , 就需要确保一个对应的自定义的DefaultAnnotationHandlerMapping 和 /或AnnotationMethodHandlerAdapter 同样被定义——假设想要使用@RequestMapping

<?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-2.5.xsd">
<bean class="org.springframework.web.servlet.mvc.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.AnnotationMethodHandlerAdapter"/>
... (controller bean definitions) ...
</beans>

如果你想要自定义映射策略,显式的定义一个DefaultAnnotationHandlerMapping 和 /或AnnotationMethodHandlerAdapter 也有实际意义。 例如,指定一个自定义的PathMatcher 或者WebBindingInitializer (见下面)。

13.12.2. 使用@Controller 定义一个控制器

注解@Controller 指明一个特定的类承担控制器 的职责, 而没有扩展任何控制器基类或者引用Servlet API的必要。当然,如果需要还是可以引用特定Servlet功能。

注解@Controller 的基本目标是担任所注解的类的原型的角色,指明它的职责。 Dispatcher将会在这样被注解的类中扫描映射的方法,探测注解@RequestMapping (见下一节)。

所注解的控制器bean可以被显式定义,这个过程是在dispatcher的上下文中使用一个标准的Spring bean定义完成的。 然而,@Controller 原型也允许自动探测,就像 Spring 2.5对探测组件的类以及为它们自动注册bean定义的普遍支持一样。

要实现对这样的所注解的控制器的自动探测,必须要向配置中加入组件扫描的部分。 通过使用在下面的XML片段中所展示出的spring-context schema,这很容易实现:

<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="org.springframework.samples.petclinic.web"/>
...
</beans>

13.12.3. 使用@RequestMapping 映射请求

注解@RequestMapping 被用于映射如 “/editPet.do”这样的URL到一个完整的类或者一个特定的处理方法。 典型的,顶层的注解映射一个特定的请求路径(或者路径模式)到一个表单控制器,另外的方法一级的注解可以缩小这个主要映射的范围,包括对于一个特定的 HTTP请求方法(“GET/POST”)或者特定的HTTP请求参数。

提示

@RequestMapping 在类型一级也可以被用于Controller 接口的普通实现。 在这种情况下,请求处理的代码会遵循传统的handleRequest 模样,而控制器的映射将会通过一个@RequestMapping 注解体现。 这对于预先构建的Controller 基类,诸如SimpleFormController ,也一样有效。

在下面的讨论中,我们将会关注基于通过注解实现的处理方法的控制器。

下面是一个使用了这种注解的表单控制器的例子,它选自PetClinic:

@Controller
@RequestMapping("/editPet.do")

@SessionAttributes("pet")
public class EditPetForm {
private final Clinic clinic;
@Autowired
public EditPetForm(Clinic clinic) {
this.clinic = clinic;
}
@ModelAttribute("types")
public Collection<PetType> populatePetTypes() {
return this.clinic.getPetTypes();
}
@RequestMapping(method = RequestMethod.GET)

public String setupForm(@RequestParam("petId") int petId, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
}
@RequestMapping(method = RequestMethod.POST)

public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result,
SessionStatus status) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}
else {
this.clinic.storePet(pet);
status.setComplete();
return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
}
}
}

对于一个传统的multi-action控制器,由于控制器会响应多个URL,URL就通常被直接映射到方法上。 下面是一个使用了@RequestMapping 的multi- action控制器的例子,它选自PetClinic:

@Controller
public class ClinicController {
private final Clinic clinic;
@Autowired
public ClinicController(Clinic clinic) {
this.clinic = clinic;
}
/**
* Custom handler for the welcome view.
* Note that this handler relies on the RequestToViewNameTranslator to
* determine the logical view name based on the request URL: "/welcome.do"
* -> "welcome".
*/
@RequestMapping("/welcome.do")

public void welcomeHandler() {
}
/**
* Custom handler for displaying vets.
* Note that this handler returns a plain {@link ModelMap} object instead of
* a ModelAndView, thus leveraging convention-based model attribute names.
* It relies on the RequestToViewNameTranslator to determine the logical
* view name based on the request URL: "/vets.do" -> "vets".
*
* @return a ModelMap with the model attributes for the view
*/
@RequestMapping("/vets.do")

public ModelMap vetsHandler() {
return new ModelMap(this.clinic.getVets());
}
/**
* Custom handler for displaying an owner.
* Note that this handler returns a plain {@link ModelMap} object instead of
* a ModelAndView, thus leveraging convention-based model attribute names.
* It relies on the RequestToViewNameTranslator to determine the logical
* view name based on the request URL: "/owner.do" -> "owner".
*
* @param ownerId the ID of the owner to display
* @return a ModelMap with the model attributes for the view
*/
@RequestMapping("/owner.do")

public ModelMap ownerHandler(@RequestParam("ownerId") int ownerId) {
return new ModelMap(this.clinic.loadOwner(ownerId));
}
}

使用@RequestMapping 注解的处理器方法允许具有非常灵活的外观。 它们可以拥有下面类型的参数,在任意的顺序下(除非是对于验证结果,它需要紧跟在对应的命令对象后面,如果需要):

  • 请求和/或响应对象(Servlet API或者Portlet API)。 可以选择任何特定的请求/响应类型,例如,ServletRequest/HttpServletRequest或者PortletRequest /ActionRequest/RenderRequest。 注意那个Portlet的例子里,一个被显式声明了的action/render参数被用于映射特定的请求类型到一个处理方法(在没有提供其他信息来区分 action和render requests的情况下)。

  • 会话对象(Servlet API或者Portlet API):不管是HttpSession还是PortletSession。 一个此种类型的参数将会保证出现一个对应的会话。这样就造成,这样一个参数永远也不可以是null注意会话访问可以并不是线程安全的,特别是在Servlet环境中:如果允许多个请求同时访问一个会话,就考虑把AnnotationMethodHandlerAdapter 的 “synchronizeOnSession”旗标置为“true”

  • org.springframework.web.context.request.WebRequestorg.springframework.web.context.request.NativeWebRequest 。 允许像访问请求/会话属性一样的访问一般的请求参数,而不是锁定在原生的Servlet/Portlet API上。

  • java.util.Locale 用于当前请求区域属性(由可用的最接近的区域属性解析器决定,也就是, 在Servlet环境中配置好的LocaleResolver 以及在Portlet环境中的portal locale)。

  • java.io.InputStream /java.io.Reader 用于访问请求的内容。 这将是Servlet/Portlet API暴露出的天然的InputStream/Reader。

  • java.io.OutputStream /java.io.Writer 用于生成响应的内容。 这将是Servlet/Portlet API暴露出的天然的OutputStream/Writer。

  • @RequestParam 注解的参数用于访问特定的 Servlet/Portlet请求参数。 参数的值将被转换为声明的方法参数类型。

  • java.util.Map /org.springframework.ui.Model /org.springframework.ui.ModelMap 用于充实将被暴露到Web视图的隐含模型。

  • 绑定参数到的命令/表单对象:带有自定义的类型转换的bean属性或者域,依赖于@InitBinder 方法和/或HandlerAdapter配置——参见AnnotationMethodHandlerAdapter 的“webBindingInitializer ”属性。 这样的命令对象,包括它们的验证结果,将会暴露为模型属性,默认的会在属性注解中使用非限定的命令类名(例如,对于类型 “mypackage.OrderAddress”使用“orderAddress”)。 为声明一个特定的模型属性名称指定一个参数级别的ModelAttribute 注解。

  • org.springframework.validation.Errors /org.springframework.validation.BindingResult 验证结果用于前面的一个命令/表单对象(前面紧接的参数)。

  • org.springframework.web.bind.support.SessionStatus 状态处理用于把表单处理过程标记为已完成(触发会话属性的清理,这些会话属性是在句柄类型级别由@SessionAttributes 注解指示出的)。

13.12.4. 使用@RequestParam 绑定请求参数到方法参数

@RequestParam 注解是用于在控制器中绑定请求参数到方法参数。

下面取自PetClinic实例程序的代码片段说明了这种用法:

@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
public class EditPetForm {
// ...

@RequestMapping(method = RequestMethod.GET)
public String setupForm(@RequestParam("petId") int petId

, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
}
// ...

使用这个注解的参数默认是必需的,但是可以把@RequestParamrequired 属性置为false 从而让这个参数可选(例如,@RequestParam(value="id", required="false") )。

13.12.5. 使用@ModelAttribute 提供一个从模型到数据的链接

@ModelAttribute 在控制器中有两种使用场景。 当作为一个方法参数时,@ModelAttribute 用于映射一个模型属性到特定的注解的方法参数(见下面的processSubmit() 方法)。 这是控制器获得持有表单数据的对象引用的方法。另外,这个参数也可以被声明为特定类型的表单支持对象,而不是一般的java.lang.Object ,这就增加了类型安全性。

@ModelAttribute 也用于在方法级别为模型提供引用数据 (见下面的populatePetTypes() 方法)。 在这种用法中,方法编写可以包含与上面描述的@RequestMapping 注解相同的类型。

注意: 使用@ModelAttribute 注解的方法将会在选定的使用@RequestMapping 注解的方法之前 执行。 它们有效的使用特定的属性预先填充隐含的模型,这些属性常常来自一个数据库。 这样一个属性也就可以通过在选定的方法中使用@ModelAttribute 注解的句柄方法参数来访问了,潜在的可以应用绑定和验证。

下面的代码片段展示了此注解的这两种用法:

@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
public class EditPetForm {
// ...

@ModelAttribute("types")

public Collection<PetType> populatePetTypes() {
return this.clinic.getPetTypes();
}
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet

, BindingResult result,
SessionStatus status) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}
else {
this.clinic.storePet(pet);
status.setComplete();
return "redirect:owner.do?ownerId=" + pet.getOwner().getId();
}
}
}

13.12.6. 使用@SessionAttributes 指定存储在会话中的属性

类型级别的@SessionAttributes 注解使用一个特定的句柄声明会话属性。 这通常会列出模型属性的名称,这些属性应被透明的保存在会话或者对话存储中,用于在后续的请求之间作为表单支持beans。

下面的代码片段展示了此注解的这种用法:

@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")

public class EditPetForm {
// ...

}

13.12.7. 自定义WebDataBinder 初始化

为了通过Spring的WebDataBinder 使用 PropertyEditors等自定义请求参数绑定,可以或者使用@InitBinder —— 在控制器之内的注解的方法, 或者通过提供一个定制的WebBindingInitializer 把配置具体化。

13.12.7.1. 使用@InitBinder 自定义数据绑定

使用@InitBinder 注解控制器方法,可以在控制器类内部直接配置 Web数据绑定。 @InitBinder 指定初始化WebDataBinder 的方法, 后者被用于填充注解的句柄方法的命令和表单对象参数。

这个init-binder方法支持@RequestMapping 支持的全部参数,除了命令/表单对象和对应的验证结果对象。 Init-binder方法必须没有返回值。因此,它们常被声明为void 。 典型的参数,包括 WebDataBinder 以及WebRequest 或者java.util.Locale ,允许代码注册上下文特定的编辑器。

下面的例子说明了@InitBinder 的用法,为所有的java.util.Date 表单属性配置一个CustomDateEditor

@Controller
public class MyFormController {
@InitBinder

public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
// ...

}

13.12.7.2. 配置一个定制的WebBindingInitializer

为了外化数据绑定初始化的过程,可以提供一个WebBindingInitializer 接口的自定义实现。 通过为一个AnnotationMethodHandlerAdapter 提供一个定制的bean配置可以使它启用,这样就覆盖了默认配置。

下面取自PetClinic应用的例子展示了一个使用WebBindingInitializer 接口的自定义实现的配置——org.springframework.samples.petclinic.web.ClinicBindingInitializer , 完成多个PetClinic控制器都需要的PropertyEditors的配置。

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="cacheSeconds" value="0" />
<property name="webBindingInitializer">
<bean class="org.springframework.samples.petclinic.web.ClinicBindingInitializer" />
</property>
</bean>
================
http://blog.csdn.net/sanshiqiduer/article/details/4791779

基于注解风格的Spring-MVC的拦截器

分类: Java 2009-11-09 22:16 4753人阅读 评论(3) 收藏 举报

转自  http://www.blogjava.net/atealxt/archive/2009/09/20/spring_mvc_annotation_interceptor_gae.html

Spring-MVC如何使用拦截器,官方文档只给出了非注解风格的例子。那么基于注解风格如何使用拦截器呢? 基于注解基本上有2个可使用的定义类,分别是DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter

Xml代码
  1. < bean   class = "org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
  2. < bean   class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
[xml] view plaincopyprint?
  1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

1、DefaultAnnotationHandlerMapping
DefaultAnnotationHandlerMapping本身支持自定义拦截器,只需按如下进行配置:

Xml代码
  1. < bean   class = "org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" >
  2. < property   name = "interceptors" >
  3. < list >
  4. < bean   class = "packageName.XXXInterceptor"   />
  5. </ list >
  6. </ property >
  7. </ bean >
[xml] view plaincopyprint?
  1. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <bean class="packageName.XXXInterceptor" /> </list> </property> </bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <bean class="packageName.XXXInterceptor" /> </list> </property> </bean>

Interceptor的定义为:

Java代码
  1. public   class  XXXInterceptor  extends  HandlerInterceptorAdapter {
  2. @Override
  3. public   boolean  preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) {
  4. String className = handler.getClass().getName();// packageName.ClassName
  5. if  (Error) {
  6. return   false ;
  7. }
  8. return   true ;
  9. }
  10. }
[java] view plaincopyprint?
  1. public class XXXInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) { String className = handler.getClass().getName();// packageName.ClassName if (Error) { return false; } return true; } }
public class XXXInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) { String className = handler.getClass().getName();// packageName.ClassName if (Error) { return false; } return true; } }

2、AnnotationMethodHandlerAdapter
目前,笔者没找到如何给AnnotationMethodHandlerAdapter配置自定义Interceptor的方法,但是有个customArgumentResolver可以利用一下,来充当Interceptor。

Xml代码
  1. < bean   class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
  2. < property   name = "customArgumentResolver" >
  3. < bean   class = "packageName.XXXResolver" />
  4. </ property >
  5. </ bean >
[xml] view plaincopyprint?
  1. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="customArgumentResolver"> <bean class="packageName.XXXResolver"/> </property> </bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="customArgumentResolver"> <bean class="packageName.XXXResolver"/> </property> </bean>

Resolver的定义为:

Java代码
  1. public   class  XXXResolver  implements  WebArgumentResolver {
  2. @Override
  3. public  Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest)  throws  Exception {
  4. String className = methodParameter.getMethod().getDeclaringClass().getName();// packageName.ClassName
  5. // 如何取得Response和Request
  6. HttpServletResponse resp = (HttpServletResponse) webRequest.getNativeResponse();
  7. HttpServletRequest req = (HttpServletRequest) webRequest.getNativeRequest();
  8. if  (Error) {
  9. if  (!resp.isCommitted()) resp.sendError(ERROR_STATUS);
  10. }
  11. return  UNRESOLVED;
  12. }
  13. }
[java] view plaincopyprint?
  1. public class XXXResolver implements WebArgumentResolver { @Override public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception { String className = methodParameter.getMethod().getDeclaringClass().getName();// packageName.ClassName // 如何取得Response和Request HttpServletResponse resp = (HttpServletResponse) webRequest.getNativeResponse(); HttpServletRequest req = (HttpServletRequest) webRequest.getNativeRequest(); if (Error) { if (!resp.isCommitted()) resp.sendError(ERROR_STATUS); } return UNRESOLVED; } }
public class XXXResolver implements WebArgumentResolver { @Override public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception { String className = methodParameter.getMethod().getDeclaringClass().getName();// packageName.ClassName // 如何取得Response和Request HttpServletResponse resp = (HttpServletResponse) webRequest.getNativeResponse(); HttpServletRequest req = (HttpServletRequest) webRequest.getNativeRequest(); if (Error) { if (!resp.isCommitted()) resp.sendError(ERROR_STATUS); } return UNRESOLVED; } }

仔细的人会看出,第二种方法其实根本不是拦截。其实第二种只是在映射Controller,调用方法的时候,给每一个方法的参数增加了一个切点。
上例在出错的时候往HttpServletResponse 写错误状态,来通知web容器进行错误重定向,达到了拦截器的作用。
这么做有一个缺点,就是每个参数都有自己的切点,比如方法有3个参数就会调3次resolveArgument。为了避免出错,需要判断一下 resp.isCommitted 。

customArgumentResolver的初衷不是用来做Interceptor的,但有些环境却不得不使用它,比如部署在GAE上。
GAE 是不支持DefaultAnnotationHandlerMapping的,因为此类用到了 org.springframework.beans.BeanUtils.findEditorByConvention,这个方法会调用 java.lang.ClassLoader.getSystemClassLoader,而这正是GAE所不允许的。

PS:
文中提到软件的版本:
spring - 2.5.X
google app engine - 1.2.5

参考资料
http://www.scottmurphy.info/spring_framework_annotation_based_controller_interceptors
http://groups.google.com/group/google-appengine-java/browse_thread/thread/54aadf8164be7bf0

spring 基于注解的控制器配置相关推荐

  1. Spring 基于注解(annotation)的配置之@Required注解

    从 Spring 2.5 开始就可以使用注解来配置依赖注入.注解连线在默认情况下在 Spring 容器中不打开.因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它: ...

  2. Spring基于注解的AOP配置

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  3. Spring 基于注解(annotation)的配置之@Autowired注解

    Setter 方法中的 @Autowired 当 Spring遇到一个在 setter 方法中使用的 @Autowired 注解,它会试图执行 byType 自动连接.换言之,加了@Autowired ...

  4. Spring 基于注解(annotation)的配置之@Qualifier注解

    使用@Qualifier可以分别为同样类型的Bean分别注入不同的依赖值.看个例子: Student.java: package com.sap;public class Student {priva ...

  5. 缓存初解(五)---SpringMVC基于注解的缓存配置--web应用实例

    之前为大家介绍了如何使用spring注解来进行缓存配置 (EHCache 和 OSCache)的简单的例子,详见 Spring基于注解的缓存配置--EHCache AND OSCache 现在介绍一下 ...

  6. Spring MVC-04循序渐进之基于注解的控制器

    概述 Spring MVC注解类型 Controller注解类型 RequestMapping注解类型 value属性 其他属性 编写请求处理方法 应用基于注解的控制器 目录结构 配置文件 Contr ...

  7. Spring 基于注解的配置

    转载自  Spring 基于注解的配置 基于注解的配置 从 Spring 2.5 开始就可以使用注解来配置依赖注入.而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注 ...

  8. java day58【 案例:使用 spring 的 IoC 的实现账户的 CRUD 、 基于注解的 IOC 配置 、 Spring 整合 Junit[掌握] 】...

    第1章 案例:使用 spring 的 IoC 的实现账户的 CRUD 1.1 需求和技术要求 1.1.1 需求 1.1.2 技术要求 1.2 环境搭建 1.2.1 拷贝 jar 包 1.2.2 创建数 ...

  9. (spring-第4回【IoC基础篇】)spring基于注解的配置

    (spring-第4回[IoC基础篇])spring基于注解的配置 基于XML的bean属性配置:bean的定义信息与bean的实现类是分离的. 基于注解的配置:bean的定义信息是通过在bean实现 ...

最新文章

  1. Python进阶【第五篇】函数式编程及某些特殊函数
  2. nagios部署安装中篇
  3. 开发日记-20190417 关键词 WheelView(视图绘制)
  4. 为什么微博“越改版越被骂“?数据却”越骂越好“?
  5. 第一个Canvas实例-钟表
  6. 首届中国服务创新大会在深举办 助力产业智慧升级
  7. REMarkerClusterer
  8. java客户端服务器聊天程序流程图_基于java的socket简单聊天编程
  9. python paramiko并发_Python之paramiko
  10. 全球首发!惯性导航导论(剑桥大学)第七部分
  11. Qt捕捉窗口关闭事件
  12. QT5.9.4支持的数据驱动查看
  13. Jupyter插件的使用
  14. HttpServletResponse(打开图片)
  15. Python读取并遍历CSV数据
  16. 电脑从硬盘启动计算机,如何设置电脑从硬盘启动优先
  17. HDU-4414 Finding crosses
  18. ZOJ Problem Set - 4043 Virtual Singers(2018acm 青岛赛区热身赛)
  19. EasyUi(完整版)
  20. js处理json数组

热门文章

  1. 主机甲和主机乙之间已建立一个TCP连接,TCP最大段长为1000B。若主机甲的当前拥塞窗口为4000B,在主机甲向主机乙连续发送两个最大段后,成功收到主机乙发送的第一个段的确认段,确认段中通告的接收窗
  2. 下列叙述正确的是( )
  3. Django安装与使用
  4. LINUX 基础命令和预处理
  5. 【机器视觉】 HDevelop语言基础(五)-多线程
  6. 【Linux】一步一步学Linux——dpkg-reconfigure命令(272)
  7. plc的时代背景_PLC发明史
  8. GVIM编辑器的配置
  9. html怎么给框格加背景图,怎么给word 2013表格添加漂亮的背景图片
  10. java thread signal_java — Thread之CountDownLatch的使用