SpringMVC+ mybatis 企业级开发实战连载(三)

        Spring从2.5版本开始引入注解,用户可以使用@Controller,@RequestMapping,@RequestParam,@ModelAttribute 等类似这样的注解。到目前为止,Spring的版本虽然发生了很大的变化,但注解的特性却一直延续下来,并不断扩展,让广大的开发者的工作变得更轻松。这都离不开Annotation的强大作用,本次重点讲解SpringMVC4中的常用注解。


       (1)@Controller注解

          org.springframework.steretype.Controller注解类型用于指示Spring类的实例是一个控制器,使用@Controller注解的类不需要继承特定的父类或者实现特定的接口,相对之前的版本实现Controller接口变得更加简单。而且Controller接口的实现类只能处理一个单一请求动作,而@Controller注解的控制器可以支持同事处理多个请求动作,更加灵活。

           @Controller用于标记一个类,使用它标记的类就是一个SpringMVC Controller对象,即一个控制器类。Spring使用扫描机制查找应用程序中基于注解的控制器类。分发处理器会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解,而使用@ RequestMapping注解的方法才是真正处理请求的处理器。为了保证Spring能找到控制器,需要完成两件事情:

           在SpringMVC的配置文件的头文件中引入spring-context.

    使用<context:compnent-scan/>元素,该元素的功能为:启动包扫描功能,以便注册带有@Controller,@Service,@repository,@Component等注解的类成为Spring的Bean。base-package属性指定需要扫描的类包,类包及其递归子包中所有的类都会被处理。配置文件如下所示:

          <context:component-scan base-package="org.fkit.controller"/>

         应该将所有控制器类都放在基本包下,并指定扫描该包,即org.fkit.controller, 而不应该指定扫描org.fkit包,以免SpringMVC扫描了无关的包。


示例:@Controller注解的使用

         新建一个项目ControllerTest,加入所需要的jar文件,新建HelloWorldController类:


      代码如下:

package org.fkit.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloWorldController {
	@RequestMapping("/helloWorld")
	public String helloWorld(Model model) {
		model.addAttribute("message", "Hello World!");
		return "helloWorld";
		
	}
}

    HelloWorldController是一个基于@Controller注解的控制器,@RequestMapping注释用来映射一个请求,value="/helloWorld"表示请求由helloWorld方法进行处理。helloWorld方法接收一个org.springframework.ui.Model类型的参数,本例在model中添加了一个名为"message"的字符串对象,该对象可以在返回的视图当中通过request对象获取。最后,方法返回一个字符串"helloWorld"作为视图名称。

新建springmvc-config.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"   
    xmlns:mvc="http://www.springframework.org/schema/mvc"  
    xmlns:context="http://www.springframework.org/schema/context"    
    xsi:schemaLocation="    
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd  
        http://www.springframework.org/schema/mvc  
        http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-4.2.xsd  ">    
            
   <!-- spring可以自动去扫描base-pack下面的包或者子包下面的java文件,
                    如果扫描到有Spring的相关注解的类,则把这些类注册为Spring的bean --> 
   <context:component-scan base-package="org.fkit.controller"/>
   <!-- 视图解析器 -->
   <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix">
             <value>/WEB-INF/content/</value>
        </property>
        <!-- 后缀 -->
        <property name="suffix">
             <value>.jsp</value>
        </property>
    </bean>
  
</beans>    

       由于使用了注解类型,因此不需要再在配置文件中XML描述Bean。<context:component-scan base-package="org.fkit.controller"/>指定spring扫描org.fkit.controller包及其子包下面的所有Java文件。最后配置了视图解析器InternalResourceViewResolver来解析视图,将View呈现给用户。视图解析器中所配置prefix属性表示视图的前缀,suffix表示视图的后缀,返回的视图字符串是"helloWorld", 经过视图解析器之后,则视图的完整路径为:/WEB-INF/content/helloWorld.jsp. 需要注意的是,此处没有配置处理器映射器和处理器适配器,当用户没有配置这两项时,Spring会使用默认的处理器映射器和处理器适配器处理请求。

             此外,还需要在wen.xml文件中配置SpringMVC的前端控制器DispatcherServlet,因为每次配置基本一致,故此处不在赘述,以及在WEB-INF 下新建content目录,新建helloWorld.jsp,jsp内容可参考之前博文中配置内容自行配置。

3.测试

 部署ConntrollerTest这个Web应用,在浏览器输入URL来测试应用:

http://localhost:8080/ControllerTest/helloWorld.

若看到以下界面,表示SpringMVC访问成功。



   SpringMVC中用于参数绑定的注解有很多,都在org.springframework.web.bind.annotation包中,根据它们处理的request的不同内容部分可以分为四类(主要讲解常用类型)。

  •   处理request body部分的注解: @RquestParam, @RequestBody。
  •   处理requet  uri部分的注解: @PathVariable。
  •   处理request header部分的注解:@RequestHeader,@CookieValue。
  •   处理attribute类型的注解:@SessionAttributes, @ModelAttribute。

       (2). @RequestMapping 注解

        开发者需要在控制器内部为每一个请求动作开发相应的处理方法。org.springframework.web.bind.annotation.RequestMapping注解类型指示Spring用哪一个类或方法来处理请求动作,该注解可用于类或方法。(@RequestMapping虽然也在org.springframework.web.bind.annotation下面,但是严格来说,它并不属于参数绑定注解)。

         @RequestMapping可以用来注释一个控制器类,在这种情况下,所有方法都将映射为相对于类级别的请求,表示该控制器处理的所有请求都被映射到value属性所指示的路径下。示例代码如下:

@Controller
@RequestMapping(value="/user")
public class UserController {
   @RequestMapping(value="register")
   public String register(){
       return "register";
   }
   @RequestMapping(value="/login")
   public String login(){
     return "login";
   }
}

       由于UserController类中加了value="/user"的@RequestMapping注解,因此所有相关路径都要加上"/user",此时方法被映射到如下请求URL:

     http://localhost:8080/user/register

     http://localhost:8080/user/login

     使用@RequestMapping注解可指定如表所示的属性。

  

@RuestMapping注解支持的属性
属性 类型 是否必要 说明
value  String[] 用于将指定请求的实际地址映射到方法上
name String 给映射地址一个别名
method RequestMethod[] 映射指定请求的方法类型,包括GET,POST,HEAD,OPTIONS,PUT,PATCH,DELETE,TARCE
consumes String[] 指定处理请求的提交内容类型(Content-Type),l例如application/josn,text/html等
produces String[] 指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型
params String[] 指定request中必须包含某些指定的header值,才能让该方法处理请求
Path String[] z在Servlet环境中只有:uri路径映射(例如:"/myPath.do")。也支持如ant的基于路径模式(例如“/myPath/*,”)。在方法层面上,支持相对路径(例如edit.do“”)

@RequestMapping注解支持的常用属性示例如下。

  1.  value属性

     @RequestMapping用来映射一个请求和一个方法。可以用@RequestMapping注释一个方法或类。

     一个采用@RequestMapping注释的方法将成为一个请求处理方法,例如:

@RequestMapping(value="/hello")
public ModelAndView hello(){
  return ...;
}

     该示例使用@RequestMapping注释的value属性将URL映射到方法上。在这个例子中,将hello映射到hello方法上,使用如下url访问应用时将由hello方法进行处理。

http;//localhost:8080/context/hello

      由于value属性是@RequestMapping注释的默认属性,因此,如果只有唯一的属性,则可以省略属性名,即如下两个标注含义相同。

@RequestMapping(value="/hello")
@RequestMapping("/hello")

 但如果有超过一个属性,就必须写上value属性名称。

value属性的值也可以是一个空字符串,此时该方法被映射到如下请求URL:

http://localhost:8080/context

2.method属性

该属性用来指示该方法仅仅处理哪些HTTP请求方式。

@RequestMapping(value="/hello",method=RequestMethod.POST)

以上代码method=RequestMethod.POST表示该方法只支持POST请求。

也可以同时支持多个HTTP请求方式。如:

@RequestMapping(value="/hello", method={RequestMethod.POST,RequestMethod.GET})

如果没有指定method属性值,则请求处理方法可以处理任意的HTTP请求方式。

3.consumes属性

该属性指定处理请求的提交内容类型(Content-Type)。

@RequestMapping(value="/hello",method=RequestMethod.POST, consumes="application/json")

表示方法仅处理request Content-Type为"application/json"类型的请求。

4.produces属性

该属性指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型。

@RequestMapping(value="/hello",method=RequestMethod.POST, produces="application/json")

方法仅处理request请求中Accept头中包含了"application/json"的请求,同时指明了返回的内容类型为application/json。

5.params属性

该属性指定request中必须包含某些参数值时,才让方法处理。

@RequestMapping(value="/hello",method=RequestMethod.POST,params="myParam=myValue")

方法仅处理其中名为"myParam",值为"myValue"的请求。

6.headers属性

该属性指定request中必须包含某些指定的header值时,才让该方法处理请求。

@RequestMapping(value="/hello",method=RequestMethod.POST, headers="Referer=http://www.fkit.org/")

方法仅处理request的header中包含了指定"Referer"请求头和对应值为"htttp://www.fkit.org/"的请求。

(3) 请求处理方法可出现的参数类型

 每个请求处理方法可以有多个不同类型的参数。

 如果需要访问HttpServletReuquest对象,则可以添加HttpServletRequest作为参数,Spring会将对象正确地传递给方法:

@RequestMapping(value="/login")
public String login(HttpServletReqquest request){
   return "login";
}

如果需要访问HttpSession对象,则可以添加HttpSession作为参数,Spring会将对象正确地传递给方法:

@RequestMapping(value="/login")
public String login(HttpSession session){
     return "login";
}

下面是可以在请求处理方法中出现的参数类型:

  • javax.servlet.ServletRequest或javax.servlet.http.HttpServletRequest
  • javax.servlet.ServletRespose或javax.servlet.http.HttpServletResponse
  • javax.servlet.http.HttpSession
  • org.springframework.web.context.request.WebRequest或 or.springframework.web.context.request.NativeWebRequest
  • java.util.Locale
  • java.io.InputStream或java.io.Reader
  • java.io.OutputStream或java.io.Writer
  • java.security.Principal
  • HttpEntity<?>
  • java.util.Map
  • org.springframework.ui.Model
  • org.springframework.ui.ModelMap
  • org.springframework.web.servlet.mvc.support.RedirectAttributes
  • org.springframework.validation.Errors
  • org.springframework.validation.BindingResult
  • org.springframework.web.bind.support.SessionStatus
  • org.springframework.web.util.UriComponentsBuilder
  • @PathVariable,@@MatrixVariable注解
  • @RequestParam,@RequestHeader,@RequestBody,@RequestPart注解

   其中最重要的是org.springframework.ui.Model类型。这不是ServletApI类型,而是一个Spring MVC类型,其中包含了Map对象用来存储数据。如果方法中添加了Model参数,则每次调用请求处理方法时,SpringMVC都会创建Model对象,并将其作为参数传递给方法。

(4)请求处理方法可返回的类型

  每个请求处理方法可以返回以下类型的返回结果。

  • org.springframework.web.porlet.ModelAndView
  • org.springframework.ui.Model
  • java.util.Map<k,v>
  • org.springframework.web.servlet.View
  • java.lang.String
  • HttpEntity或ReponseEntity
  • java.util.concurrent.Callable
  • org.springframework.web.context.request.async.DeferredResult
  • void

   (5) Model 和 ModelAndView

       在请求处理方法可出现和返回的参数类型中,最重要的就是Model和ModelAndView了。对于MVC框架,控制器(controller)执行业务逻辑,用于产生模型数据(Model),而视图(view)则用于渲染模型数据。

         如何将模型数据传递给视图是SpringMVC框架的一项重要工作,SpringMVC提供了多种途径输出模型数据,如:

  •    Model 和 ModelMap
  •    ModelAndView
  •    @ModelAttribute
  •    @SessionAttributes

          下面将重点介绍Model,ModelMap以及ModelAndView, @ModelAttribute 和@SessionAttributes放到后面介绍。

   1.   Model  和  ModelMap

      SpringMVC在内部使用了一个org.springframework.ui.Model接口存储模型数据,它的功能类似java.util.Map接口,但是比Map易于使用。org.springframework.ui.ModelMap接口实现了Map接口。

      SpringMVC在调用处理方法之前会创建一个隐含的模型对象,作为模型数据的存储容器。如果处理方法的参数为Model或ModelMap类型,则SpringMVC会将隐含模型的引用传递给这些参数。在处理方法内部,开发者就可以通过这个参数对象访问模型中的所有数据,也可以向模型中添加新的属性数据。

        在处理方法中,Model和ModelMap对象都可以使用如下方法添加模型数据:

  •         addObject(String attributeName, Object attributeValue);

  示例: Model 和 ModelMap 使用

@Controller
public class UserlController{
	//@ModelAttribute修饰的方法会于login调用,该方法用于接收前台jsp页面传入的参数
	@ModelAttribute
	public void userModel(String loginname,String password,Model model){
  	logger.info("ulserModel");
  	//创建User对象存储jsp页面传入的参数
  	User user= new User();
  	user.setLoginname(loginname);
  	user.setPassword(password);
  	//将User对象添加到Model当中
  	model.addAttribute("user",user);
  }
  @RequestMapping(value="/login1")
  public String login(Model model){
  	logger.info("login");
  		//从Model当中取出之前存入的名为user的对象
  		User user= (User) model.asMap().get("user");
  		System.out.println(user);
  		//设置user对象的usernam属性
  		user.setUsername("测试");
  		return "result1";
  }
  
  
}
@ModelAttribute修饰的userModel方法会于login调用,它把请求参数值赋给对应变量,可以向方法中的Model添加对象,前提是要在方法签名中加入一个Model类型的参数。
@Controller
public class User2lController{
	private static final Log logger= LogFactory.getLog(UserlController.clas);
	//@ModelAttribute修饰的方法会于login调用,该方法用于接收前台jsp页面传入的参数
	@ModelAttribute
	public void userMode2(String loginname,String password,ModelMap modelMap){
  	logger.info("ulserModel");
  	//创建User对象存储jsp页面传入的参数
  	User user= new User();
  	user.setLoginname(loginname);
  	user.setPassword(password);
  	//将User对象添加到Model当中
  	modelMap.addAttribute("user",user);
  }
  @RequestMapping(value="/login2")
  public String login2(ModelMap modelMap){
  	logger.info("login");
  		//从Model当中取出之前存入的名为user的对象
  		User user= (User) modelMap.get("user");
  		System.out.println(user);
  		//设置user对象的usernam属性
  		user.setUsername("测试");
  		return "result2";
  }
  
  
}

User2Controller和UserController的代码功能基本一致,只是存储对象由Model改成了ModelMap.

2. ModelAndVIew

      控制器处理方法的返回值如果是ModelAndView,则其既包含模型数据信息,也包含视图信息,这样SpringMVC将使用包含的视图对模型数据进行渲染。可以简单地将模型数据看成一个Map<String, Object>对象。

      在处理方法中可以使用ModelAndView对象的如下方法添加模型数据:

      addObject(String attributeName, Object attributeValue);

      可以通过如下方法设置视图:

       setViewName(String viewName)


示例 :ModelAndView 的使用

@Controller
public class User3lController{
	private static final Log logger= LogFactory.getLog(UserlController.clas);
	//@ModelAttribute修饰的方法会于login调用,该方法用于接收前台jsp页面传入的参数
	@ModelAttribute
	public void userMode3(String loginname,String password,ModelAndView mv){
  	logger.info("ulserMode3");
  	//创建User对象存储jsp页面传入的参数
  	User user= new User();
  	user.setLoginname(loginname);
  	user.setPassword(password);
  	//将User对象添加到Model当中
  	mv.addObject("user",user);
  }
  @RequestMapping(value="/login3")
  public ModelAndView login3(ModelAndView mv){
  	logger.info("login3");
  		//从Model当中取出之前存入的名为user的对象
  		User user= (User) mv.getModel().get("user");
  		System.out.println(user);
  		//设置user对象的usernam属性
  		user.setUsername("测试");
  		mv.setViewName("result3");
  		return mv;
  }
  
  
}

User3Controller和UserControlller的代码功能基本一致,只是存储对象改成了ModelAndView 。









猜你喜欢

转载自blog.csdn.net/u014645946/article/details/80379454