和大彪一起来学习-SpringMvc之第三回(注解使用详解) 分类: SpringMvc 2015-01-23 22:40 600人阅读 评论(0) 收藏
Posted on 2015-01-23 22:40 LuckyBill 阅读(176) 评论(0) 编辑 收藏 举报简述:
在上一篇文章中,介绍了适配器和映射器的一些概念,这篇文章主要是介绍SpringMvc注解的使用,下面先从一个最简单注解程序开始,慢慢引入一些常用的注解(@Controller,@Component,@Service,@Repository,@RequestMapping,@InitBinder,
@RequestParam,@PathVariable,@RequestBody ,@ResponseBody)。
一、第一个注解项目
1.创建项目,加入Jar包,编写web.xml
2.编写springmvc-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" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd "> <!-- 0.指定扫描 @Controller,@Component,@Service,@Repository之类Bean的路径--> <context:component-scan base-package="com.billstudy.springmvc"/> <!-- 1.注解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 2.注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" /> <!-- 小技巧:以上1、2可以直接使用 <mvc:annotation-driven />,这个配置已经包含上面两个bean配置,所以也能实现支持注解的效果 --> <!-- 3.视图解析器 最终路径为:prefix + Controller内返回逻辑视图名 + suffix 如:方法返回/hello,那么实际路径为:/WEB-INF/jsp/hello.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp" /> <property name="suffix" value=".jsp"/> </bean> </beans>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(路径映射):
使用方法2(URI 模板模式映射):
使用方法3(请求方式限定):
三、注解配合请求实现参数绑定
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" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title></title> </head> <body bgcolor="#C7EDCC"> <form action="${pageContext.request.contextPath}/user/userSave.do" method="POST"> <input type="hidden" value="${user.id}" name="id"/> <div align="center"> <table border="2"> <tr> <td>姓名</td> <td><input name="name" value="${user.name}"/></td> </tr> <tr> <td>年龄</td> <td><input name="age" value="${user.age}"/></td> </tr> <tr> <td>状态</td> <td> <input name="status" type="radio" <c:if test="${user.status}">checked</c:if> value="true"/>true <input name="status" type="radio" <c:if test="${!user.status}">checked</c:if> value="false"/>false </td> </tr> <tr> <td>生日</td> <td><input name="birthday" value='<fmt:formatDate value="${user.birthday}" pattern="yyyy-MM-dd"/>'/></td> </tr> <tr> <td>操作</td> <td><input value="submit" type="submit"/></td> </tr> </table> </div> </form> </body> </html>下面打开页面测试,会发现500异常,原因是Date转换不支持。
异常:
@InitBinder /* register Date parse support*/ public void bindBinbar(ServletRequestDataBinder binder){ binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));/** true:允许为空 **/ }再测一把,将表单提交
<!-- 解决POST 中文乱码 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>若是get乱码则可以修改Tomcat/server.xml的编码,或者在代码中对具体中文参数进行ISO-8859-1 To UTF-8的方法,个人偏向修改Tomcat编码,简单省事。
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<User> tUsers; private Map<String,Object> tMaps; private String[] tStrs; private User mainUser; public List<User> gettUsers() { return tUsers; } public void settUsers(List<User> tUsers) { this.tUsers = tUsers; } public Map<String, Object> gettMaps() { return tMaps; } public void settMaps(Map<String, Object> tMaps) { this.tMaps = tMaps; } public String[] gettStrs() { return tStrs; } public void settStrs(String[] tStrs) { this.tStrs = tStrs; } public Other(List<User> tUsers, Map<String, Object> 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() { } }
<%@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" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title></title> </head> <body bgcolor="#C7EDCC"> <form action="${pageContext.request.contextPath}/user/inject.do" method="POST"> <input type="hidden" value="${user.id}" name="id"/> <div align="center" style="background-color: #1B7D00"> <h1>List test</h1><br/> <!-- List 使用[下标]的方式绑定值 --> 姓名 <input name="tUsers[0].name" /><br/> 年龄 <input name="tUsers[0].age" /><br/> 状态 <input name="tUsers[0].status" type="radio" value="true"/>true <input name="tUsers[0].status" type="radio" value="false"/>false<br/> 生日 <input name="tUsers[0].birthday" /><br/> <hr/> 姓名 <input name="tUsers[1].name" /><br/> 年龄 <input name="tUsers[1].age" /><br/> 状态 <input name="tUsers[1].status" type="radio" value="true"/>true <input name="tUsers[1].status" type="radio" value="false"/>false<br/> 生日 <input name="tUsers[1].birthday" /><br/> <hr/> 姓名 <input name="tUsers[2].name" /><br/> 年龄 <input name="tUsers[2].age" /><br/> 状态 <input name="tUsers[2].status" type="radio" value="true"/>true <input name="tUsers[2].status" type="radio" value="false"/>false<br/> 生日 <input name="tUsers[2].birthday" /><br/> <hr/> <h1>Map test</h1><br/> <!-- Map key value的形式,比较容易理解吧 --> Map key flyName :<input name="tMaps['flyName']" /><br/> Map key flyAge :<input name="tMaps['flyAge']" /><br/> Map key flyAddress :<input name="tMaps['flyAddress']" /><br/> <h1>String Array test</h1><br/> <!-- 这个就是同名的表单元素,在Controller中就是一个字符串数组,和request.getParameterValues()一个效果 --> <input name="tStrs" /> <input name="tStrs" /> <input name="tStrs" /> <input name="tStrs" /> <h2>mainUser 填写</h2> <div align="center"> <table border="2"> <tr> <td>姓名</td> <td><input name="mainUser.name" /></td> </tr> <tr> <td>年龄</td> <td><input name="mainUser.age" /></td> </tr> <tr> <td>状态</td> <td> <input name="mainUser.status" type="radio" />true <input name="mainUser.status" type="radio" />false </td> </tr> <tr> <td>生日</td> <td><input name="mainUser.birthday" /></td> </tr> </table> </div> 操作 <input value="submit" type="submit"/><br/> </div> </form> </body> </html>
录入参数如下:
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的支持,修改之后如下:
<!-- 2.注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" > <span style="color:#ff0000;"><property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" /> </list> </property></span> </bean>
在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
/** * 将key 为citys的数组对象传递到页面 * @return */ @ModelAttribute("citys") public String[] getCitys(){ return new String[]{"中国","美国","伊拉克","日本"}; } /** * 将key 为users的List<User>对象传递到页面 * @return */ @ModelAttribute("users") public List<User> getUsers(){ List<User> users = new ArrayList<User>(); 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" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>测试ModelAttribute</title> </head> <body> citys:<br/> <c:forEach items="${citys}" var="city"> ${city} </c:forEach><br/> Users:<br/> <c:forEach items="${users}" var="user"> ${user} <br/> </c:forEach> </body> </html>访问结果:
三、forward/redirect
/** * 演示转发,重定向用法,看注释部分就好了 * @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,这些就小伙伴们自己去研究看看吧。 哈哈,收工。读书去了
本文所有代码:点击下载本文代码
上面分享的这些注解你会用了吗? 这里是 热爱生活,热爱技术,喜欢交友的大彪 .
版权声明:本文为博主原创文章,未经博主允许不得转载。