注解Controller和RequestMapping
在前面的样例中,在springmvc-servlet.xml中配置的超链接请求与控制器之间的映射关系,在这里我们使用注解配置映射关系(记得开启扫描)。
使用基于注解的控制器,具有如下两个优点:
- 可以在一个控制器类中编写多个处理方法,进而可以处理多个请求,减少控制器类的数量,方便后期的维护。不像在配置文件中部署映射每个控制器类只能对应一个请求。
- 不需要在配置文件中部署映射,仅需要使用RequestMapping注释类型注解一个方法进行请求处理。
RequestMapping注解分两种方法级别注解和类级别注解
1.1 方法级别
@RequestMapping(value = "/index/login")
value属性将请求URI映射到方法,是RequestMapping注解的默认属性,如果只有一个value属性,可以省略“value=”。
在上次项目的基础上
- 在springmvc-servlet开启注解扫描
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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="com.controller" />
<!-- 为控制器返回值自动添加前缀后缀 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
- 修改控制器类
@Controller
public class IndexController {
@RequestMapping(value = "/index/login")
public String login() {
/**return 的 login代表逻辑视图名称,需要根据Spring MVC配置
* 文件中internalResourceViewResolver的前缀和后缀找到对应的物理视图
*/
return "login";
}
@RequestMapping(value = "/index/register")
public String register() {
return "register";
}
}
1.2 类级别
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/register")
public String register() {
return "register";
}
}
Controller接收请求参数的常见方式
2.1 通过实体bean接收请求参数
- 建立参数们对应的JavaBean
package pojo;
public class UserForm {
private String uname;//与请求参数名称相同
private String upass;
private String reupass;
//getter和setter
}
- 修改JSP页面 login.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>
登录页面。
<form action="${pageContext.request.contextPath }/main" method="post">
<table>
<tr>
<td>姓名:</td>
<td><input type="text" name="uname" class="textSize"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="upass" class="textSize"></td>
</tr>
<tr>
<td colspan="2"><button onclick="gogo()"/> <button onclick="cancel()"/></td>
</tr>
</table>
${messageError}
</form>
</body>
</html>
main.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>主页面</title>
</head>
<body>
欢迎${sessionScope.u.uname }访问该系统。
</body>
</html>
- 修改控制器类
@RequestMapping("/main")
public String main(UserForm user, HttpSession session, Model model) {
if("herlo".equals(user.getUname())&&"123456".equals(user.getUpass())) {
session.setAttribute("u", user);
return "main";
}
else {
model.addAttribute("messageError", "用户名或密码错误");
return "login";
}
}
2.2 通过处理方法的形参接收请求参数
通过处理方法的形参接收请求参数,也就是直接把表单参数写在控制器类方法的形参中,即形参名称与请求参数名称完全相同。该接收参数方式适用于get和post提交请求方式。
/**
* 处理注册 使用UserForm对象(实体JavaBean)接收注册页面提交的请求参数
*/
@RequestMapping("/register")
public String register(String uname,String upass, Model model) {
if ( "zhangsan".equals(uname)&&"123456".equals(upass) ) {
//awa
}
}
2.3 通过HttpServletRequest接收请求参数
通过HttpServletRequest接收请求参数,适用于get和post提交请求方式。
<a href="${pageContext.request.contextPath}/register?param=test">注册</a>
@Controller
public class RegisterController{
@RequestMapping("/register")
public String register(HttpServletRequest request, Model model) {
System.out.println(request.getParameter("param"));
return "register";
}
}
2.4 通过@PathVariable接收URL中的请求参数
- @PathVariable无法接收对象,但是可以接收多个值。
- @PathVariable("xxx")通过 @PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形参中
<h1>pathVariable</h1>
<a href="${pageContext.request.contextPath}/hello/pathVariable/bigsea" > name is bigsea </a>
<br/>
<a href="${pageContext.request.contextPath}/hello/pathVariable/sea" > name is sea</a>
<br/>
/**
* localhost:8080/springmvc/hello/pathVariable/bigsea
* localhost:8080/springmvc/hello/pathVariable/sea
* 这些URL 都会 执行此方法 并且将 <b>bigsea</b>、<b>sea</b> 作为参数 传递到name字段
*/
@RequestMapping("/pathVariable/{name}")
public String pathVariable(@PathVariable("name")String name){
System.out.println("hello "+name);
return "helloworld";
}
2.5 通过@RequestParam接收请求参数
- 通过@RequestParam接收请求参数,适用于get和post提交请求方式。
- 通过@RequestParam接收请求参数与2.2“通过处理方法的形参接收请求参数”的区别是:当请求参数与接收参数名不一致时,后者不会报404错误,而“通过@RequestParam接收请求参数”会404错误。
/** * 处理注册 使用@RequestParam接收请求参数*/
@RequestMapping("/register")
public String register(@RequestParam String uname, @RequestParam String upass, Model model) {
if ("zhangsan".equals(uname)&&"123456".equals(upass)) {
//awa
}
}
2.6 通过@ModelAttribute接收请求参数
- @ModelAttribute注解放在处理方法的形参上时,用于将多个请求参数封装到一个实体对象,自动暴露为模型数据用于视图页面展示时使用。而2.1中只是将多个请求参数封装到一个实体对象,并不能暴露为模型数据(需要使用model.addAttribute语句才能暴露为模型数据,数据绑定与模型数据展示,可参考第12章的内容)。
- 通过@ModelAttribute注解接收请求参数,适用于get和post提交请求方式。
就是用@ModelAttribute xxx替代了原来的model.addAttribute(xxx,xxx)
@RequestMapping("/register")
public String register(@ModelAttribute("user") UserForm user) {
if ("zhangsan".equals(uname) && "123456".equals(upass)) {
logger.info("成功");
return "login"; // 注册成功,跳转到 login.jsp
} else {
logger.info("失败");
// 使用@ModelAttribute("user")与model.addAttribute("user",user)的功能相同
//register.jsp页面上可以使用EL表达式${user.uname}取出ModelAttribute的uname值
return "register"; // 返回 register.jsp
}
}
重定向与转发
重定向是将用户从当前处理请求定向到另一个视图(例如JSP)或处理请求,以前的请求(request)中存放的信息全部失效,并进入一个新的request作用域;
转发是将用户对当前处理的请求转发给另一个视图或处理请求,以前的request中存放的信息不会失效。
转发是服务器行为,重定向是客户端行为。