和大彪一起来学习-SpringMvc之第三回(注解使用详解)

和大彪一起来学习-SpringMvc之第三回(注解使用详解)

简述:

在上一篇文章中,介绍了适配器和映射器的一些概念,这篇文章主要是介绍SpringMvc注解的使用,下面先从一个最简单注解程序开始,慢慢引入一些常用的注解(@Controller,@Component,@Service,@Repository,@RequestMapping,@InitBinder,

@RequestParam,@PathVariable,@RequestBody ,@ResponseBody)

一、第一个注解项目

1.创建项目,加入Jar包,编写web.xml

可以加入第一篇文章里面给出的那些jar包,项目结构如下:
web.xml编写如下,前面已经有介绍过了,这里直接贴图了。

2.编写springmvc-servlet.xml加入注解支持



		
		
		
		 
		
		
	
		
		
		
		
		 
			
		
			
			
		

3.编写Controller类

package com.billstudy.springmvc.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * SpringMvc/Spring 企业开发常用注解使用演示
 * @author Bill
 * @since V1.0 2015/01/23
 */

/** 标明为Controller类,可以被Spring 扫描到,一般此类注解都作用于类上 ,与此相似的还有:
 *  @Service : 一般用于MVC设计中M(model)层,也就是业务层
 *  @Repository : 一般用于DAO层,也就是数据访问层
 *  @Component : 仅仅表示一个组件 (Bean),比较泛化,当我们写了一个类不好定位其在MVC那层的时候,可以使用这个
 *  @Controller:一般用于MVC设计中C(Controller)层,也就是控制层
 * **/
@Controller	
public class AnnotationDemoController{
	
	@RequestMapping("/annotationTest01")/** 定义访问规则 **/
	public ModelAndView annotationTest01(HttpServletRequest request,HttpServletResponse response){
		ModelAndView result = new ModelAndView();
		result.setViewName("/annotationTest01");	// 这里的ViewName,我们把它看成逻辑视图名,最终结合视图解析器,路径为:/WEB-INF/jsp/annotationTest01.jsp
		result.addObject("msg", "注解使用成功了!"); 
		return result;
	}
}

4.部署,测试

二、注解应用

1.@RequestMapping

使用方法1(路径映射):

【URL】加在Controller具体方法上,称为子路径映射。如:@RequestMapping(“/annotationTest01”),这个时候若没有在类上用这个注解,那么可以直接通过【项目名/annotationTest01】访问这个方法了。若是类上面写了@RequestMapping(“/parent“),那么这时候访问就是【项目名/parent/annotationTest01】了,也就是说类中所有的方法,都应该带上/parent,类上面我们称其为根路径映射。
演示:
子路径:
jsp/result.jsp内容:
访问效果:

根路径:类上面写了,那么访问具体方法时,都要带上根路径。
访问测试:

使用方法2(URI
模板模式映射):

@RequestMapping(value=”/parent/{id}”):{×××}占位符,
请求的URL可以是“/
parent/001”或“/parent/abc”,通过在方法中使用@PathVariable获取{×××}中的×××变量。若是有多个,则直接@RequestMapping(value=”/parent/{id}/{name}/{age}“)就可以了
演示:

使用方法3(请求方式限定):

也就是规定客户端请求的类型,如get/post,不按照要求来报 http
405错误
下面使用Firefox的HttpRequest测试,我就不写form/表单测试了,效果都一样。
如果想让方法同时支持get/post,那么可以这么写:@RequestMapping(value=”/postMethod”,method={RequestMethod.POST,RequestMethod.GET}),就是写多个就可以了。
下面的注解解决了一些请求参数绑定,所以例子和请求参数一起测试。

三、注解配合请求实现参数绑定

默认支持(Java基本数据类型,HttpServletRequest 通过request对象获取请求信息
HttpServletResponse 通过response处理响应信息 HttpSession 通过session对象得到session中存放的对象 Model 通过model向页面传递数据),若是页面是多个表单元素使用同一个name,那么就可以直接使用String[]接收值,这个和别的框架一样。没啥特别的。如果是Date类型,则需要注册转换器了,否则会报错,如下:

1.@InitBinder

下面,创建了几个类:

package com.billstudy.springmvc.bean;

import java.util.Date;

/**
 * User Bean 
 * @author Bill
 * @since V1.0 2015/01/25
 */ 
public class User {
	
	private Integer id;
	private String name;
	private Integer age;
	private Boolean status;
	private Date birthday;
	
	public User() {
		// TODO Auto-generated constructor stub
	}

	public User(Integer id,String name, Integer age, Boolean status, Date birthday) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.status = status;
		this.birthday = birthday;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", age=" + age
				+ ", status=" + status + ", birthday=" + birthday + "]";
	}

	public Boolean getStatus() {
		return status;
	}

	public void setStatus(Boolean status) {
		this.status = status;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}
	
	
}

package com.billstudy.springmvc.controller;

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

import com.billstudy.springmvc.bean.User;

/**
 * 配合User bean演示相关注解使用
 * @author Bill
 * @since V.10 2015/01/25
 */
@Controller
@RequestMapping("/user")
public class UserController {
	/**
	 * 测试用户信息注入
	 * @param user
	 */
	@RequestMapping("/userSave")
	public void userSave(User user){
		System.out.println(user);
	}
}

WebContent/user/userEdit.jsp

<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>






	
姓名
年龄
状态 checked value="true"/>true checked value="false"/>false
生日 '/>
操作

下面打开页面测试,会发现500异常,原因是Date转换不支持。


异常:
这个时候,@InitBinder派上用场了。
在UserController中加上如下代码:

@InitBinder /* register Date parse support*/
	public void bindBinbar(ServletRequestDataBinder binder){ 
		binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));/** true:允许为空 **/
	}

再测一把,将表单提交

页面会报404错误,这个我们不管,因为方法没有返回值,它找的默认路径,默认路径没有对应的jsp页面,我们的关注点在参数自动绑定这块。可以看到参数已经绑定了,但是存在乱码,解决乱码:在web.xml加入org.springframework.web.filter.CharacterEncodingFilter的支持,如下


   
	characterEncodingFilter
  	org.springframework.web.filter.CharacterEncodingFilter
  	
  		encoding 
  		UTF-8
  	
   
   
  
	characterEncodingFilter
	/*
  

若是get乱码则可以修改Tomcat/server.xml的编码,或者在代码中对具体中文参数进行ISO-8859-1 To UTF-8的方法,个人偏向修改Tomcat编码,简单省事。

加入Filter之后,效果如下:
可以看到,我的名字没有乱码了。 这里可以看出,springmvc会将表单中的name绑定到方法参数中,和struts2不同的是。这里没有用对象.属性的方式,当然这里也支持。那就是复杂对象里面包含复杂对象的时候。如下面这个类的定义:
package com.billstudy.springmvc.bean;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * List , Map , String[] Test Bean
 * @author Bill
 * @since V1.0 2015/01/25
 */
public class Other {
	
	private List tUsers;
	
	private Map tMaps;
	
	private String[] tStrs;
	
	private User mainUser;
	
	public List gettUsers() {
		return tUsers;
	}

	public void settUsers(List tUsers) {
		this.tUsers = tUsers;
	}

	public Map gettMaps() {
		return tMaps; 
	}

	public void settMaps(Map tMaps) {
		this.tMaps = tMaps;
	}

	public String[] gettStrs() {
		return tStrs;
	}

	public void settStrs(String[] tStrs) {
		this.tStrs = tStrs;
	}

	public Other(List tUsers, Map tMaps, String[] tStrs) {
		super();
		this.tUsers = tUsers;
		this.tMaps = tMaps;
		this.tStrs = tStrs;
	}

	public User getMainUser() {
		return mainUser;
	}

	public void setMainUser(User mainUser) {
		this.mainUser = mainUser;
	}
	public Other() {
	}
}
这个对象中包含了User对象,我们暂且把它称为复杂对象。那么在页面想要给这里面的user注入值时,就可以使用mainUser.name/mainUser.age的方式了。可以看到,里面还有List,Map,String[]等类型的属性,这个下面也对其参数绑定进行演示。
添加页面:/WebContent/user/injectTest.jsp
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>






	

List test


姓名
年龄
状态 true false
生日

姓名
年龄
状态 true false
生日

姓名
年龄
状态 true false
生日

Map test


Map key flyName :
Map key flyAge :
Map key flyAddress :

String Array test


mainUser 填写

姓名
年龄
状态 true false
生日
操作

录入参数如下:

控制台输出如下:
List tUsers:[User [id=null, name=姓名1, age=10, status=false, birthday=Mon Nov 11 00:00:00 CST 1991], User [id=null, name=姓名2, age=22, status=true, birthday=Tue Nov 12 00:00:00 CST 1991], User [id=null, name=姓名3,
age=33, status=false, birthday=Wed Nov 13 00:00:00 CST 1991]]
Map tMaps:{flyAddress=上海, flyAge=20, flyName=飞机}
String[] tStrs:[数组值01, 数组值02, 数组值03, 数组值04]
User mianUser:User [id=null, name=mainUser用户, age=100, status=true, birthday=Sun Jan 03 00:00:00 CST 1993]

2.@RequestParam

绑定单个请求参数

value参数名字,即入参的请求参数名字,如value=“id表示请求的参数区中的名字为id的参数的值将传入;

required是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;

defaultValue默认值,表示如果请求中没有同名参数时的默认值

添加方法如下(报错的测试,大家可以自己去做):

/**
	 * 用了defaultValue,其实required=true也不会报错,因为有默认值。请求时需要将id的值以userId=xx的形式提交,会自动将值绑定到形参id中
	 * @param model
	 * @param id
	 * @return
	 */ 
	@RequestMapping("/requestParamTest")
	public String requestParamTest(Model model,@RequestParam(defaultValue="520",required=true,value="userId")String id){
		model.addAttribute("msg", "requestParamTest id:"+id); 
		return "/result";
	}

测试如下:

不传递值,使用默认值

传递值:

3.@RequestBody

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上,下面演示将客户端传递过来的JSON转成Java对象。

要使用这个注解,需要先加入两个jar包(jackson-core-asl-1.9.11.jar,jackson-mapper-asl-1.9.11.jar),同时需要在springmvc-servlet.xml适配器中加入对jackson的支持,修改之后如下:

	
		
			 
				
					
				 
			
		


在UserController中加入方法:

/**
	 * 演示JSON 	TO Java Object
	 * @param user
	 */
	@RequestMapping("/requestBodyTest")
	public void requestBodyTest(@RequestBody User user){
		System.out.println("user:"+user);
	}

利用HttpRequest测试:


控制台输出:


4.@ResponseBody

该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

加入方法如下:

测试效果:

5.@ModelAttribute

Model一般可以用于在方法中放置变量在View取值,这个注解可以帮助我们将一些通用的变量返回到View(页面)。很方便取值,如下演示。
添加如下三个方法,2个添加参数,1个直接跳转到指定页面。测试能否取值
方法:

/** 
	 * 将key 为citys的数组对象传递到页面
	 * @return
	 */
	@ModelAttribute("citys")
	public String[] getCitys(){
		return new String[]{"中国","美国","伊拉克","日本"};
	}
	/** 
	 * 将key 为users的List对象传递到页面
	 * @return
	 */
	@ModelAttribute("users")
	public List getUsers(){
		List users = new ArrayList(); 
		for (int i = 0; i < 3; i++) {
			// 构造函数 : User(Integer id,String name, Integer age, Boolean status, Date birthday)
			users.add(new User(i,"测试姓名"+i,10+i,true,Calendar.getInstance().getTime()));
		}
		return users; 
	}
	/**
	 * 直接跳转到页面,不存放任何数据
	 * @return
	 */ 
	@RequestMapping("/toShowValue") 
	public String toShowValue(){
		return "/showValue"; 
	}

页面:

<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>



测试ModelAttribute


	citys:
${city}
Users:
${user}

访问结果:

三、forward/redirect

转发/重定向。也就是在方法内部设置ViewName或者直接返回String时可以达到转发/重定向的效果。
转发:方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到
重定向:方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,因为转发即执行了一个新的request和response。
使用演示:

/**
	 * 演示转发,重定向用法,看注释部分就好了
	 * @param request
	 * @param response
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String demoForwardRedirect(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
		// request.getRequestDispatcher("").forward(request,response);	// 转发
		// return "forward:/xx/xx.jsp";									// 转发
		
		// response.sendRedirect("/xx/xx.jsp");							// 重定向
		// return "redirect:/xx/xx.jsp";								// 重定向
		return null;
	}

注解部分还有@CookieValue,@RequestHeader@RequestPart,这些就小伙伴们自己去研究看看吧。 哈哈,收工。读书去了

本文所有代码:点击下载本文代码

上面分享的这些注解你会用了吗? 这里是 热爱生活,热爱技术,喜欢交友的大彪
.

版权声明:本文为博主原创文章,未经博主允许不得转载。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注