Controller详解
1. 方法的返回值
有4中类型
- ModelAndView 表示返回的是数据模型和视图
- String 表示返回的是视图
三种写法:
- 普通字符串——>表示视图名字
- “forward:”+url——>转发
- “redirect:”+url——>重定向
- void将请求的url作为视图名
- Object 表示返回的是数据模型(一般返回的是json数据)
@RequestMapping("login2")
public String Login(String username, String password, Model model){
if("admin".equals(username) && "123".equals(password)){
model.addAttribute("username", username);
return "success";//success是视图名
}else{
model.addAttribute("loginError", "username or password error");
// return "login";
return "forward:showLogin2";//表示转发
}
}
//void返回值,将请求的url即/test1作为视图名,等价于返回值类型为String时,return "test1";
@RequestMapping("/test1")
public void test1(){
System.out.println("returnController.test1");
}
2. SpringMVC注解
注解 | 解释 |
---|---|
@Controller | 将类映射为Controller层,添加到IoC容器中 |
@RequestMapping | 配置请求映射路径,即url |
@RequestParam | 表示参数来源于请求参数 |
@PathVariable | 表示参数来源于url |
@RequestHeader | 表示参数来源于请求头 |
@CookieValue | 表示参数来源于cookie |
@RequestBody | 表示参数来源于请求体 |
@ModelAttribute | 将请求数据转换为对象 |
@Valid | 后台校验 |
@InitBinder | 类型转换,注册为属性编辑器 |
@ControllerAdvice | 统一异常处理,处理全局异常 |
@ExceptionnHander | 异常处理器,处理特定异常的方法 |
@ResponseBody | 结合返回值为Object的方法使用,用来返回JSON数据 |
@RestController | 将类映射为Controller层,默认为所有方法添加@ResponseBody注解 |
3. @RequestMapping
3.1 基本用法
该注解可以定义在方法上,也可以定义在类上,表示层级关系。
如下例,在LoginController的方法上配置一个url为/showLogin
,新建一个PathController,在其方法上配置一个url也为/showLogin
,这样程序就会报错。在PathController类上面添加注释@RequestMapping("/path")
,就不会产生冲突了
@Controller
public class LoginController {
@RequestMapping("/showLogin")
public ModelAndView showLogin(){
ModelAndView mav = new ModelAndView();
mav.setViewName("login");
return mav;
}
@Controller
@RequestMapping("/path")
public class PathController {
@RequestMapping("/showLogin")
public String showLogin(){
return "login";
}
}
3.2 URL中的/
return "forward:showLogin";
中不加/
,表示的是相对路径,从当前目录下寻找urlreturn "forward:/showLogin";
中加/
,表示的是绝对路径,从根目录寻找url
@Controller
@RequestMapping("/path")
public class PathController {
@RequestMapping("/showLogin")
public String showLogin(){
System.out.println("PathController.showLogin");
return "login";
}
@RequestMapping("/forwardLogin")
public String forwardLogin(){
System.out.println("PathController.forwardLogin");
return "forward:showLogin";
//return "forward:/showLogin";
}
}
@Controller
public class LoginController {
@RequestMapping("/showLogin")
public ModelAndView showLogin(){
ModelAndView mav = new ModelAndView();
mav.setViewName("login");
System.out.println("LoginController.showLogin");
return mav;
}
@RequestMapping("/login")
public ModelAndView login(String username, String password){
ModelAndView mav = new ModelAndView();
if("admin".equals(username) && "123".equals(password)){
mav.addObject("username",username);
mav.setViewName("success");
}else{
mav.addObject("loginError", "用户名或密码错误");
mav.setViewName("login");
}
return mav;
}
}
LoginController和PathController中都声明了值为/showLogin
的URL,当地址栏输入http://localhost:8080/path/forwardLogin
时,根据public String forwardLogin()
中返回值的不同,跳转的路径也不同。
1)、当public String forwardLogin()
中返回值为forward:showLogin时,则会匹配到当前方法所在层级下值为showLogin
的URL,即PathController中的showLogin
2)、当public String forwardLogin()
中返回值为forward:/showLogin时,则会匹配到项目根路径下值为showLogin
的URL,即LoginController中的showLogin
3.3 URL的多种写法
请求映射路径有三种写法:
- Ant风格(较少使用)
*
表示单层目录,匹配任意字符,也可以没有字符,但是正斜杠必须有
**
表示多层或单层目录,可以没有字符,正斜杠也可以没有
?
表示单个字符,必须有一个字符@RequestMapping("/test1/*") public String test1(){ return "hello"; }
- 如果@RequestMappig映射的值为
/test1/*
,那么地址栏为http://localhost:8080/path/test1/
、http://localhost:8080/path/test1/abc
都能跳转到hello.jsp - 如果@RequestMappig映射的值为
/test1/**
,那么地址栏为http://localhost:8080/path/test1/
、http://localhost:8080/path/test1
、http://localhost:8080/path/test1/abc
、http://localhost:8080/path/test1/abc/def
都能跳转到hello.jsp - 如果@RequestMappig映射的值为
/test1/?
,那么地址栏为http://localhost:8080/path/test1/a
能跳转到hello.jsp - 这三种方式可以混合使用,如
@RequestMapping("/test4/?/*/a?b/**/c")
-
Rest风格(较常用)
{变量} 表示URL中的占位符,可以结合@PathVariable获取值@RequestMapping("/test2/{id}/{name}") public String test5(@PathVariable int id, @PathVariable("name") String username){ System.out.println("PathController.test2.id: " + id + ", name: " + username); return "hello"; }
运行后在地址栏输入
localhost:8080/path/test2/1/wql
,会跳转到hello.jsp,在控制台会输出
如果地理栏参数与函数参数不一致,可以使用类似@PathVariable("name") String username
的方式,表示把name值传给username{变量:正则表达式} 可以使用正则表达式限制占位符的格式
如{id\d+}表示可以输入多个数字@RequestMapping("/test2/{id\\d+}/{name}") public String test2(@PathVariable int id, @PathVariable("name") String username){ System.out.println("PathController.test2.id: " + id + ", name: " + username); return "hello"; }
-
固定写法
value和path互为别名,值为数组,可以指定多个值
URL为固定的值,如@RequestMapping("/test3")
,等价于@RequestMapping(path="/test3")
,也等价于@RequestMapping(value="/test3")
其中value值可以使是一个数组,通过数组中的任意一个元素都可以访问要访问的页面
例如@RequestMapping(value = {"/test3", "test4"}) public String test3(){ return "hello"; }
通过
localhost:8080/path/test3
和localhost:8080/path/test4
都能访问到hello.jsp
3.4 根据请求方式访问
请求方式:GET,POST,OPTIONS,PUT,PATCH,DELETE,TRACE
关于GET与POST的区别,这篇博文写得很精彩。点击链接
在RequestMapping中,可以通过RequestMethod方式限定请求方式
如下面的例子,URL一样,但是系统可以根据不同的请求方式作出不同的操作
@RequestMapping(path = "/user/{id}", method = RequestMethod.GET)
public String deleteUser(@PathVariable Integer id){
System.out.println("PathController.deleteUser, id: " + id);
return "hello";
}
@RequestMapping(path = "/user/{id}", method = RequestMethod.POST)
public String selectUser(@PathVariable Integer id){
System.out.println("PathController.selectUser, id: " + id);
return "hello";
}
为了书写方便,又有了更简便的注解
@GetMapping("/user/{id}")
等价于@RequestMapping(path = "/user/{id}", method = RequestMethod.GET)
@PostMapping("/user/{id}")
等价于@RequestMapping(path = "/user/{id}", method = RequestMethod.POST)
3.5 其他属性
-
params
限定请求参数,必须符合指定条件
例:限定访问路径里必须包含id,username和password,且username为admin,password不能是123@RequestMapping(path = "/test4", params = {"id", "username=admin", "password!=123"}) public String test4(){ return "hello"; }
在地址栏输入
localhost:8080/path/test4
是无法访问hello.jsp的
必须将参数输入完整,如http://localhost:8080/path/test4/?id=1&username=admin&password=121
-
headers
用来限定请求头部,必须符合指定的条件
我们发送一个请求,然后查看其请求头都有哪些内容
比如说我们想要发送请求的时候,其请求头里必须有Cookies,且Accept-Language值必须等于zh-CN,zh;q=0.9,en;q=0.8,则必须如下配置@RequestMapping(path = "/test5", headers = {"Cookies","Accept-Language=zh-CN,zh;q=0.9,en;q=0.8"}) public String test5(){ return "hello"; }
如果Accept-Language的值与所要求的的值不匹配,则拒绝访问。
还可根据请求头限定发送请求的浏览器。我们也经常会遇到需要用特定的浏览器访问某个网址,其中就是请求头的对其做了限制。