SpringMVC 注解

@Controller注解

@Controller注解用于声明某类的实例是一个控制器。

1
2
3
4
5
6
package net.biancheng.controller;
import org.springframework.stereotype.Controller;
@Controller
public class IndexController {
// 处理请求的方法
}

Spring MVC 使用扫描机制找到应用中所有基于注解的控制器类,所以,为了让控制器类被 Spring MVC 框架扫描到,需要在配置文件中声明spring-context,并使用<context:component-scan/>元素指定控制器类的基本包(请确保所有控制器类都在基本包及其子包下)。

在应用的配置文件springmvc-servlet.xml中添加以下代码:

1
2
<!-- 使用扫描机制扫描控制器类,控制器类都在net.biancheng.controller包及其子包下 -->
<context:component-scan base-package="net.biancheng.controller" />

@RequestMapping注解

一个控制器内有多个处理请求的方法,如UserController里通常有增加用户、修改用户信息、删除指定用户、根据条件获取用户列表等。每个方法负责不同的请求操作,而@RequestMapping就负责将请求映射到对应的控制器方法上。

在基于注解的控制器类中可以为每个请求编写对应的处理方法。使用@RequestMapping注解将请求与处理方法一一对应即可。

@RequestMapping注解可用于类或方法上。用于类上,表示类中的所有响应请求的方法都以该地址作为父路径。

@RequestMapping注解常用属性如下。

1. value 属性

value属性是@RequestMapping注解的默认属性,因此如果只有value属性时,可以省略该属性名,如果有其它属性,则必须写上value属性名称。

1
2
@RequestMapping(value="toUser")
@RequestMapping("toUser")

value属性支持通配符匹配,如@RequestMapping(value="toUser/*")表示http://localhost:8080/toUser/1http://localhost:8080/toUser/hahaha都能够正常访问。

2. path属性

path属性和value属性都用来作为映射使用。即@RequestMapping(value="toUser")@RequestMapping(path="toUser")都能访问toUser()方法。

path属性支持通配符匹配,如@RequestMapping(path="toUser/*")表示http://localhost:8080/toUser/1http://localhost:8080/toUser/hahaha都能够正常访问。

3. name属性

name属性相当于方法的注释。如@RequestMapping(value = "toUser",name = "获取用户信息")

4. method属性

method属性用于表示该方法支持哪些HTTP请求。如果省略method属性,则说明该方法支持全部的HTTP请求。

@RequestMapping(value = "toUser",method = RequestMethod.GET)表示该方法只支持GET请求。也可指定多个HTTP请求,如@RequestMapping(value = "toUser",method = {RequestMethod.GET,RequestMethod.POST}),说明该方法同时支持GETPOST请求。

5. params属性

params属性用于指定请求中规定的参数。

1
2
3
4
@RequestMapping(value = "toUser",params = "type")
public String toUser() {
return "showUser";
}

以上代码表示请求中必须包含type参数时才能执行该请求。即http://localhost:8080/toUser?type=xxx能够正常访问toUser()方法,而http://localhost:8080/toUser则不能正常访问toUser()方法。

1
2
3
4
@RequestMapping(value = "toUser",params = "type=1")
public String toUser() {
return "showUser";
}

以上代码表示请求中必须包含type参数,且type参数为 1 时才能够执行该请求。即http://localhost:8080/toUser?type=1能够正常访问toUser()方法,而http://localhost:8080/toUser?type=2则不能正常访问toUser()方法。

6. header属性

header属性表示请求中必须包含某些指定的header值。

@RequestMapping(value = "toUser",headers = "Referer=http://www.xxx.com")表示请求的header中必须包含了指定的Referer请求头,以及值为http://www.xxx.com时,才能执行该请求。

7. consumers属性

consumers属性用于指定处理请求的提交内容类型(Content-Type),例如:application/json、text/html。如@RequestMapping(value = "toUser",consumes = "application/json")

8. produces属性

produces属性用于指定返回的内容类型,返回的内容类型必须是request请求头(Accept)中所包含的类型。如@RequestMapping(value = "toUser",produces = "application/json")

除此之外,produces属性还可以指定返回值的编码。如@RequestMapping(value = "toUser",produces = "application/json,charset=utf-8"),表示返回utf-8编码。

使用@RequestMapping来完成映射,具体包括 4 个方面的信息项:请求 URL、请求参数、请求方法和请求头。

通过请求URL进行映射

方法级别注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package net.biancheng.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping(value = "/index/login")
public String login() {
return "login";
}
@RequestMapping(value = "/index/register")
public String register() {
return "register";
}
}

上述示例中有两个RequestMapping注解语句,它们都作用在处理方法上。在整个 Web 项目中,@RequestMapping映射的请求信息必须保证全局唯一。

用户可以使用如下 URL 访问login方法(请求处理方法),在访问login方法之前需要事先在/WEB-INF/jsp/目录下创建login.jsp

1
http://localhost:8080/springmvcDemo/index/login

类级别注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package net.biancheng.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/register")
public String register() {
return "register";
}
}

在类级别注解的情况下,控制器类中的所有方法都将映射为类级别的请求。用户可以使用如下 URL 访问login方法。

1
http://localhost:8080/springmvcDemo/index/login

通过请求参数、请求方法进行映射

@RequestMapping除了可以使用请求 URL 映射请求之外,还可以使用请求参数、请求方法来映射请求,通过多个条件可以让请求映射更加精确。

1
2
3
4
5
6
7
8
9
10
package net.biancheng.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping(value = "/index/success" method=RequestMethod.GET, params="username")
public String success(@RequestParam String username) {
return "index";
}
}

@Autowired和@Service注解

将依赖注入到 Spring MVC 控制器时需要用到@Autowired@Service注解。

@Autowired注解属于org.springframework.beans.factory. annotation包,可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。

@Service注解属于org.springframework.stereotype包,会将标注类自动注册到 Spring 容器中。

在配置文件中需要添加<component-scan/>元素来扫描依赖基本包。

1
<context:component-scan base-package="net.biancheng.service"/>

示例

新建 Web 应用springmvcDemo3进一步说明 Spring MVC 如何应用依赖注入。

1
2
3
4
5
6
package net.biancheng.po;
public class User {
private String name;
private String pwd;
/*省略setter和getter方法*/
}
1
2
3
4
5
6
package net.biancheng.service;
import net.biancheng.po.User;
public interface UserService {
boolean login(User user);
boolean register(User user);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package net.biancheng.service;
import org.springframework.stereotype.Service;
import net.biancheng.po.User;
@Service
public class UserServiceImpl implements UserService {
@Override
public boolean login(User user) {
if ("bianchengbang".equals(user.getName()) && "123456".equals(user.getPwd())) {
return true;
}
return false;
}
@Override
public boolean register(User user) {
if ("bianchengbang".equals(user.getName()) && "123456".equals(user.getPwd())) {
return true;
}
return false;
}
}

注意:为了使类能被 Spring 扫描到,必须为其标注@Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package net.biancheng.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import net.biancheng.po.User;
import net.biancheng.service.UserService;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public String getLogin(Model model) {
User us = new User();
us.setName("bianchengbang");
userService.login(us);
model.addAttribute("user", us);
return "login";
}
@RequestMapping("/register")
public String getRegister(Model model) {
User us = new User();
us.setName("bianchengbang");
userService.login(us);
model.addAttribute("user", us);
return "register";
}
}

UserService上添加@Autowired注解会使UserService的一个实例被注入到UserController实例中。

springmvc-servlet.xml代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan
base-package="net.biancheng" />
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!--后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>

web.xml代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>springMVC</display-name>
<!-- 部署 DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
<!-- 表示容器再启动时立即加载servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 处理所有URL -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

index.jsp文件内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ 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>
未注册的用户,请
<a href="${pageContext.request.contextPath }/user/register"> 注册</a>
<br /> 已注册的用户,去
<a href="${pageContext.request.contextPath }/user/login"> 登录</a>
</body>
</html>

login.jsp文件内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
<%@ 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>
登录页面! 欢迎 ${user.name} 登录
</body>
</html>

register.jsp文件内容如下。

1
2
3
4
5
6
7
8
9
10
11
12
<%@ 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>
注册页面!
注册账号成功,用户名为: ${user.name }
</body>
</html>

@ModelAttribute注解

@ModelAttribute用来将请求参数绑定到Model对象。

Controller中使用@ModelAttribute时,有以下几种应用情况。

  • 应用在方法上
  • 应用在方法的参数上
  • 应用在方法上,并且方法也使用了@RequestMapping

需要注意的是,因为模型对象要先于controller方法之前创建,所以被@ModelAttribute注解的方法会在Controller每个方法执行之前都执行。因此一个Controller映射多个 URL 时,要谨慎使用。

应用在方法上

1.应用在无返回值的方法

示例 1:创建ModelAttributeController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package net.biancheng.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;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ModelAttributeController {
// 方法无返回值
@ModelAttribute
public void myModel(@RequestParam(required = false) String name, Model model) {
model.addAttribute("name", name);
}
@RequestMapping(value = "/model")
public String model() {
return "index";
}
}

创建index.jsp页面。

1
2
3
4
5
6
7
8
9
10
11
12
<%@ 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>测试</title>
</head>
<body>
${name}
</body>
</html>

访问地址:http://localhost:8080/springmvcDemo2/model?name=%E7%BC%96%E7%A8%8B%E5%B8%AE

在请求/model?name=%E7%BC%96%E7%A8%8B%E5%B8%AE后,Spring MVC 会先执行myModel方法,将name的值存入到Model中。然后执行model方法,这样name的值就被带到了model方法中。

myModelmodel方法合二为一后,代码如下。

1
2
3
4
5
@RequestMapping(value = "/model")
public String model(@RequestParam(required = false) String name, Model model) {
model.addAttribute("name", name);
return "index";
}

2.应用在有返回值的方法

示例 2:修改ModelAttributeController控制类,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package net.biancheng.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;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ModelAttributeController {
// 方法有返回值
@ModelAttribute("name")
public String myModel(@RequestParam(required = false) String name) {
return name;
}
@RequestMapping(value = "/model")
public String model() {
return "index";
}
}

修改 index.jsp,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
<%@ 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>编程帮</title>
</head>
<body>
${string }
</body>
</html>

访问地址和运行结果与示例 1 相同。

对于以上情况,返回值对象name会被默认放到隐含的Model中,在Modelkey为返回值首字母小写,value为返回的值。等同于model.addAttribute("string", name);

但正常情况下,程序中尽量不要出现keystring、int、float等这样数据类型的返回值。使用@ModelAttribute注解value属性可以自定义key,代码如下。

1
2
3
4
5
6
7
// 方法有返回值
@ModelAttribute("name")
public String myModel(@RequestParam(required = false) String name) {
return name;
}
// 等同于
model.addAttribute("name", name);

应用在方法的参数上

@ModelAttribute注解在方法的参数上,调用方法时,模型的值会被注入。这在实际使用时非常简单,常用于将表单属性映射到模型对象。

1
2
3
4
5
6
7
8
9
10
@RequestMapping("/register")
public String register(@ModelAttribute("user") UserForm user) {
if ("zhangsan".equals(uname) && "123456".equals(upass)) {
logger.info("成功");
return "login";
} else {
logger.info("失败");
return "register";
}
}

上述代码中@ModelAttribute("user") UserForm user语句的功能有两个:

  • 将请求参数的输入封装到user对象中
  • 创建UserForm实例

user为键值存储在Model对象中,和model.addAttribute("user",user)语句的功能一样。如果没有指定键值,即@ModelAttribute UserForm user,那么在创建UserForm实例时以userForm为键值存储在Model对象中,和model.addAtttribute("userForm", user)语句的功能一样。

ModelAttribute+RequestMapping

示例 3:修改ModelAttributeController,代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package net.biancheng.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;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class ModelAttributeController {
// @ModelAttribute和@RequestMapping同时放在方法上
@RequestMapping(value = "/index")
@ModelAttribute("name")
public String model(@RequestParam(required = false) String name) {
return name;
}
}

index.jsp代码如下。

1
2
3
4
5
6
7
8
9
10
11
12
<%@ 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>编程帮</title>
</head>
<body>
${name }
</body>
</html>

访问地址:http://localhost:8080/springmvcDemo2/index?name=%E7%BC%96%E7%A8%8B%E5%B8%AE

@ModelAttribute@RequestMapping注解同时应用在方法上时,有以下作用:

  1. 方法的返回值会存入到Model对象中,keyModelAttributevalue属性值。
  2. 方法的返回值不再是方法的访问路径,访问路径会变为@RequestMappingvalue值,例如:@RequestMapping(value = "/index")跳转的页面是index.jsp页面。

总而言之,@ModelAttribute注解的使用方法有很多种,非常灵活,可以根据业务需求选择使用。

ModelModelView的区别:
Model:每次请求中都存在的默认参数,利用其addAttribute()方法即可将服务器的值传递到客户端页面中。

ModelAndView:包含modelview两部分,使用时需要自己实例化,利用ModelMap来传值,也可以设置view的名称。

拓展

@ModelAttribute注解的方法会在每次调用该控制器类的请求处理方法前被调用。这种特性可以用来控制登录权限。
控制登录权限的方法有很多,例如拦截器、过滤器等。

创建BaseController

1
2
3
4
5
6
7
8
9
10
11
package net.biancheng.controller;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.ModelAttribute;
public class BaseController {
@ModelAttribute
public void isLogin(HttpSession session) throws Exception {
if (session.getAttribute("user") == null) {
throw new Exception("没有权限");
}
}
}

创建ModelAttributeController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package net.biancheng.controller;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/admin")
public class ModelAttributeController extends BaseController {
@RequestMapping("/add")
public String add() {
return "addSuccess";
}
@RequestMapping("/update")
public String update() {
return "updateSuccess";
}
@RequestMapping("/delete")
public String delete() {
return "deleteSuccess";
}
}

在上述ModelAttributeController类中的add、update、delete请求处理方法执行时,首先执行父类BaseController中的isLogin方法判断登录权限,可以通过地址http://localhost:8080/springMVCDemo2/admin/add测试登录权限。

打赏
  • Copyrights © 2017-2023 WSQ
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信