spring从2.5的版本开始引入了注解,我们前面讲过ioc和app的注解,springmvc也提供了相关的注解,让开发更加简洁。spring的版本一直在升级,但是注解却一直保留下来,并一直扩展,让广大开发者的工作变得更加的轻松。
1、如何使用注解完成一个springmvc的helloworld?
我们先看代码:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Test</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- 配置springmvc的中央处理器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定springmvc的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置spring的监听器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
在springmvc-config.xml中进行如下配置
<!-- 让springmvc扫描controller的包 -->
<context:component-scan base-package="com.springmvc.controller"></context:component-scan>
<!-- 使用springmvc默认的处理映射器 -->
<!-- 使用springmvc默认的处理适配器 -->
<!-- 使用springmvc默认的视图解析器 -->
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public String httpTest() {
System.out.println("网站访问成功了");
return "/WEB-INF/views/index.jsp";
}
}
使用注解@Controller将类标记为Controller,然后使用@RequestMapping注解给处理方法映射上链接。这样springmvc使用注解的helloworld就完成了,访问下列链接就可以访问网站成功:
http://localhost:8080/Test/test.do
2、处理器的请求处理方法参数有哪些?
在请求处理方法中,可以传参类型ServletRequest、ServletResponse、HttpSession三个servlet中的api,还可以传参视图类型Model或者ModelMap,使用方法和servlet中相同。控制器代码如下:
package com.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public String httpTest(HttpServletRequest request,HttpServletResponse response,HttpSession session) {
System.out.println("网站访问成功了");
return "/WEB-INF/views/index.jsp";
}
}
3、请求处理方法的返回值有哪些?
请求处理方法还可以返回参数类型ModleAndView、String、void等,看一下如何返回。
返回ModleAndView类型
package com.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public ModelAndView httpTest(HttpServletRequest request,HttpServletResponse response,HttpSession session) {
System.out.println("网站访问成功了");
return new ModelAndView("/WEB-INF/views/index.jsp");
}
}
返回String类型
package com.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public String httpTest(HttpServletRequest request,HttpServletResponse response,HttpSession session) {
System.out.println("网站访问成功了");
return "/WEB-INF/views/index.jsp";
}
}
没有返回值void
package com.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public void httpTest(HttpServletRequest request,HttpServletResponse response,HttpSession session) {
System.out.println("网站访问成功了");
}
}
如果有返回值,无论返回什么类型,视图解析器都会处理成View。如果没有返回值,则访问一个404页面。
4、如何使用注解指定请求参数?
我们使用@RequestParam来给请求处理方法传入请求的参数,代码如下:
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public void httpTest(@RequestParam("name") String name,@RequestParam("age") int age) {
System.out.println("网站访问成功了,获取的参数name="+name+",age="+age);
}
}
访问url
http://localhost:8080/Test/test.do?name=caixiaobai&age=18
控制台打印
网站访问成功了,获取的参数name=caixiaobai,age=18
控制台可以看到参数接收成功。
5、如何使用注解获取头信息?
我们可以使用@pathVariable获取映射路径的某字符串,可以使用@RequestHeader获取请求头协议,使用@CookieValue获取cookie,代码如下:
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/pathTest/{userid}.do")
public void httpTest(@PathVariable int userid,@RequestHeader("host") String host,@CookieValue(value="JSESSIONID") String sessionid) {
System.out.println("访问的网址的userid是"+userid);
System.out.println("访问的网址的host是"+host);
System.out.println("访问的浏览器的sessionid是"+sessionid);
}
}
访问url
http://localhost:8080/Test//pathTest/123.do
控制台打印
访问的网址的userid是123
访问的网址的host是localhost:8080
访问的浏览器的sessionid是20A5A6FF4352D781DA21D57293512060
可以看出,我们正确的使用三个注解拿到了请求的头协议。
6、怎么使用注解拿到session?
如果在类上写明注解@SessionAttributes,那么本类在model中添加键值对的时候,会从注解中查找是否有这个键的参数,如果有也会被添加到session中。我们看一下下面的代码:
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
@Controller
//使用@SessionAttribute注解,参数规定session的键
@SessionAttributes({"name","age"})
public class ControllerTest {
@RequestMapping("/test.do")
public String httpTest(Model model) {
model.addAttribute("name","caixiaobai");
model.addAttribute("age",18);
model.addAttribute("address", "Beijing");
return "/WEB-INF/views/index.jsp";
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
out.println("name==>"+request.getSession().getAttribute("name"));
out.println("age==>"+request.getSession().getAttribute("age"));
out.println("address==>"+request.getSession().getAttribute("address"));
%>
</body>
</html>
访问url
http://localhost:8080/Test/test.do
网页显示
name==>caixiaobai age==>18 address==>null
我们看到name和age都可以在session中拿到,但是address不可以在session中拿到,这是因为在handler中的@SessionAttributes注解中,我们在参数里配置了name和age,没有配置address,所以在添加到model的时候,name和age可以同时添加到session中,但是address不可以。
7、注解对视图模型有哪些帮助?
我们经常将视图和模型一起去说,其实视图和模型本身就是两个不同的概念。在springmvc中,视图就是可显示的各种页面,而模型就是数据,随着handler到视图中的数据。
在请求处理方法中,我们可以传入参数Model类型,这个类型的参数对象,可以向视图中传入请求参数,看下面例子:
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public String httpTest(Model model) {
model.addAttribute("name","caixiaobai");
return "/WEB-INF/views/index.jsp";
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
接收到的模型信息是<font>${name }</font>
</body>
</html>
访问url
http://localhost:8080/Test/test.do
页面显示
接收到的模型信息是caixiaobai
可以看到我们在handler中向model中添加的键值对,可以在index.jsp中使用el表达式获取到。ModelMap的使用方法和Model一样,但是ModelMap实现了Map的接口,具备了map的api的方法,使用上更加灵活。
ModelAndView除了包括我们上面说的模型,通过addObject()方法向模型添加数据,还包括视图,视图通过构造方法添加,看一下代码:
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public ModelAndView httpTest() {
ModelAndView mav = new ModelAndView("/WEB-INF/views/index.jsp");
mav.addObject("name", "caixiaobai");
return mav;
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
接收到的模型信息是<font>${name }</font>
</body>
</html>
访问url
http://localhost:8080/Test/test.do
页面显示
接收到的模型信息是caixiaobai
按照上面的写法,我们把视图和模型都在一个方法里面写好了,这样代码就没有了层次感,如果我们能让视图的方法只负责跳转或者转发,模型的方法只负责参数的传递,这样代码会不会更加规范,@ModelAttribute解决了这个问题。我们看一下代码:
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public String ViewTest() {
return "/WEB-INF/views/index.jsp";
}
@ModelAttribute("name")
public String ModelTest() {
return "caixiaobai";
}
}
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
接收到的模型信息是<font>${name }</font>
</body>
</html>
访问url
http://localhost:8080/Test/test.do
页面显示
接收到的模型信息是caixiaobai
上面的Controllertest类如果换成下面代码,效果和上面是一样的:
ControllerTest.java
package com.springmvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest {
@RequestMapping("/test.do")
public String ViewTest() {
return "/WEB-INF/views/index.jsp";
}
@ModelAttribute
public String ModelTest(Model model) {
model.addAttribute("name", "caixiaobai");
return "caixiaobai";
}
}
@ModelAttribute注解的方法要比@RequestMapping注解的方法执行早。这样,springmvc做到了先将数据存到模型,再进行页面的跳转或者转发。
8、本文中提到的注解整理总结有哪些?
现在将本博客中提到的注解进行整理:
- @Controller:类级别,将类表示为handler,需要在springmvc中扫描。
- @RequestMapping:类级别或者方法级别,给类或方法映射路径。
- RequestParam:参数级别,给参数指定请求参数。
- PathVariable:参数级别,可以从当前方法或者类的映射路径中获取{}的内容。
- RequestHeader:参数级别,可以给参数指定某个头信息。
- CookieValue:参数级别,可以将cookie中的某个属性指定给参数。
- SessionAttributes:类级别,将本类中添加到model的键值对添加到HttpSession中。
- ModelAttribute:方法级别,可以在请求处理方法前执行,将数据添加到模型中。