简述:
在上一篇文章中,介绍了适配器和映射器的一些概念,这篇文章主要是介绍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,这些就小伙伴们自己去研究看看吧。 哈哈,收工。读书去了
本文所有代码:点击下载本文代码
上面分享的这些注解你会用了吗? 这里是 热爱生活,热爱技术,喜欢交友的大彪 .