Spring MVC(2):控制器详解

本文详细介绍了SpringMVC框架中控制器的基本使用方法,包括控制器的定义、请求映射规则、请求处理方法的签名及模型数据处理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


控制器的基本使用


在 Spring MVC 中,在 POJO 类定义注解  @Controller ,再在mvc配置文件中通过   <context:component-scan /> 扫描相应的类包,就可以使一个 POJO 类变成一个可以处理 HTTP 请求的控制器(具体代码见:http://blog.youkuaiyun.com/al_assad/article/details/79012665);
用户可以创建数量不限的控制器,用于分别处理不同的业务请求,每个控制器拥有多个处理请求的方法;



使用 @RequestMapping  映射请求


@RequestMapping 注解用于将请求映射到对应的控制器方法中,这个过程包含一系列的映射规则,这些映射规则包括4个方面的信息: 请求URL、请求参数、请求方法、请求头
@RequestMapping 的 value 、method、params、headers 参数分别表示映射条件:请求URL、请求方法、请求参数、请求报文头;

1)通过 URL 映射

 
@Controller
public class UserController {
    
    @RequestMapping("/user/createUser")  // 等同于 @RequestMapping(path="/user/createUser")
    public String createUser(){
        ....
        return "user/createSuccess";
    }
}
以上 createUser 方法响应 “Web应用部署路径/user/createUser” 的HTTP请求,如: http://www.assad.site/user/createUser”  ;

可以在控制器头标注基础 @RequestMapping,以下示例中 createUser 响应 “ Web应用部署路径/user/createUser ” 请求;
 
@Controller
@RequestMapping("/user")  //以下所有 @RequestMapping 的响应 url 基于该 @RequestMapping 定义的 url
public class UserController {
    
    @RequestMapping("/createUser")   //响应 "/user/createUser" 
    public String createUser(){
        ....
        return "user/createSuccess";
    }
}

@RequestMapping 除了支持标准的URL之外,还支持  带【 ?、*、**】 占位符Ant 风格的 URL 和  带 {xxx} 占位符的 URL
/user/*/createUser:匹配类似  “user/aa/createUser”;
/user/**/createUser:匹配类似 “user/aa/bbb/createUser”,“user/createUser”;
/user/createUser??:匹配类似 “user/createUseraa”;
/user/{userId}:匹配类似 “user/123”;
/company/{companyId}/user/{userId}:匹配类似  “/company/123/user/12345”;
 其中 {xxx} 占位符可以使用 @PathVariable 标注绑定的变量名;
 
@Controller
@RequestMapping("/user")  
public class UserController {
    
    @RequestMapping("/{userId}")   
    public String showDetail( @PathVariable("userId") String userId){
        System.out.println(userId);   //如果请求为 "/user/201502012",则 userId = "201502012"
        ...
        return ...;
    }
}

2)通过请求方法、请求参数,请求报头映射

 
@Controller
@RequestMapping("/user")  
public class UserController {
    
    /*使用请求方法和请求参数映射请求
    以下例子映射一个GET请求: /user/test1?userId=xxx */
    @RequestMapping(path="/test1",method=RequestMethod.GET,params="userId")  
    public String test1 ( @RequestParam("userId") String userId){   //使用 @RequestParam 标注请求参数
        System.out.println(userId); 
        ...
        return "user/test1";
    }
    
     /*使用报头映射请求*/
    @RequestMapping(path="/test2",headers="content-type=text/*")  
    public String test2(){
        ....
        return "user/deleteUserSuccess";
    }
    
}
对于使用请求方法、请求参数映射,可以使用 @RequestParam 对请求参数绑定到方法入参中;
params、headers 参数接受简单表达式,以 params 示例:
params="userId" :请求参数为  “userId”; 
params="!userId" :请求参数不为 “userId”;
params="userId!=123" :请求参数为 “userId” 且参数值不为 123;
params={"userId","gameId"} :请求参数为 “userId”,“gameId”;



请求处理方法签名


  • 入参:Spring MVC 对控制器方法请求的限制是很宽松的,必要时可以对方法入参标注相应的注解(如:@PathVariable@RequestParam、@RequestHeader 等);
  •  返回值:一般处理方法的返回值类型为ModelAndViewString,ModelAndView 包含模型和逻辑视图名,String 代表一个逻辑视图名;

① 使用 @RequestParam 绑定请求参数值
@RequestParam 注解包含以下参数:
  • value:参数名;
  • required:是否必须,默认为 true;
  • defaultValue:默认参数名,不常用;
 
@RequestMapping(path="/handle1",method= RequestMethod.POST,params={"userName","password"})
public String handle(@RequestParam("userName") String userName,
                      @RequestParam(value="password", required=false) String passowrd){
    User user = new User(userName,passowrd);
    .....
}
② 使用 @CookieValue 绑定请求中的 Cookie 值
 
@RequestMapping("/handle2")
public String handle(@CookieValue("userid") String userId){
    ......
}
③ 使用 @Request 绑定请求报文头的属性值
 
@RequestMapping("/handle3")
public String handle(@RequestHeader("Accept-Language") String acceptLanguage){
    ....... 
}
④ 使用命令/表单对象绑定请求的参数值
命令/表单对象不需要实现任何接口,仅仅是一个拥有若干属性的POJO,以下代码中 User 为一个命令/表单对象,类结构为 User(userName,password)
假设响应的 “/handle4”  请求具体为 "/handle4?userName=assad&password=1234",以下方法会将其正确映射为一个 User(userName=“assad”,password="1234");
 
@RequestMapping("/handle4")
public ModelAndView handle2(User user){
     return new ModelAndView("success","user",user);
}
⑤ 使用 Servlet API 对象作为入参
在 Spring MVC 中,控制器类可以不依赖于任何 Servlet API 对象,但是可以将这些 Servlet API 对象绑定到入参中;
 
@RequestMapping("/handle5")
public String handle3(HttpServletRequest request, @RequestParam("userId") String userId){
    request.getSession().setAttribute("userId",userId);  //通过 HTTPServletRequest 对象设置 Session
    return "success";
}
使用 I/O 对象作为入参
Spring MVC 允许控制器的处理方法使用 java.io.InputStream / java.io.Reader,java.io.OutputStream / java.io.Writer 作为方法入参,Spring MVC 将获取 ServletRequest 的 InputStream/Reader,ServletReponse 的 OutputStream/Writer ,然后传递给控制器的处理方法;
 
RequestMapping("/handle5")
public void handle5(OutputStream out) throws IOException {
   Resource resource = new ClassPathResource("/image/imageTest.jpg");  //复制图片文件给ServletRequest的输出流
   FileCopyUtils.copy(resource.getInputStream(),out);
}


模型数据处理


Spring MVC 提供了以下多种途径输出模型:
  • ModelAndView:当处理方法返回值类型为ModelAndView时,方法体可以通过该对象添加模型数据;
  • @ModelAttribute:在方法入参标注该注解后,入参的对象就会放置在该数据模型中;
  • Map 和 Model:如果方法入参为 org.springframework.ui.Model、org.springframework.ui.ModelMap、java.util.Map 时,当处理方法返回时,Map中的数据会自动添加到模型中;
  • @SessionAttribute:将模型中的某个属性暂存在 HttpSession 中,以便多个请求共享该属性;

① ModelAndView
ModelAndView 包含视图信息和模型数据,可以简单把它的数据模型看成一个 Map<String,Object> 对象;
 
@RequestMapping("/handle4")
public ModelAndView handle2(User user){
    ModelAndView mav = new ModelAndView();
     mav.setViewName("success");
     mav.addObject("user",user);
     return mav;
}
//或者
@RequestMapping("/handle4")
public ModelAndView handle2(User user){
    ModelAndView mav = new ModelAndView("success");
    mav.addObject("user",user);
    return mav;
}
//或者
@RequestMapping("/handle4")
public ModelAndView handle2(User user){
    return new ModelAndView("success","user",user);
}
Spring MVC 会把 ModelAndView 的数据模型放置到 ServletRequest 中,在 JSP页面获取该数据模型有以下的方式:
 
<%--通过EL表达式的Request域隐含对象获取--%>
<h1>your name is <c:out value="${user.name}"/> </h1>
<h1>your name is ${user.name} </h1>
    
<%--通过JSP隐式对象获取--%>
<h1>your name is <c:out value="request.getAttribute('user').getName()"/> </h1>
注意:由于ModelAndView中的模型数据在经过Web服务器时,可能由于Web服务器的字符编码和程序编码不统一,会造成类似中文字符乱码,有一个解决方式是将字符串放置到模型时强制编码格式,如下:
 
@RequestMapping("/handle4")
public ModelAndView handle2(User user){
   if(user == null)
       return new ModelAndView("fail","error",new String("用户对象为空值".getBytes(),"UTF-8"));  
    //将中文字符强制转为与程序编码相同的”UTF-8“
   else
       return new ModelAndView("success","user",user);
}

② @ModelAttribute
@ModelAttribute 注解可以直接将方法入对象直接添加到模型中;
 
@RequestMapping("/handle4")
public String handle7(@ModelAttribute("user") User user){
    user.setId("20130602613");
    return "success";
}
除了在控制器控制方法入参中使用 @ModelAttribute 之外,还可以在方法定义中使用该注解,Spring MVC 在调用给目标处理方法之前,会先逐个调用在方法级别上标注了@ModelAttribute 的方法, 如下示例:
 
@ModelAttribute("user")  
public User getUser(){
    User user = new User();
    user.setId("20130602613");
    return user;
}
@RequestMapping("/handle4")
public String handle7(@ModelAttribute("user") User user){
    return "success";
}

③ Map / Model 

Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口储存模型数据,该接口的功能类似于 java.util.Map,Spring MVC 在调用方法之前会创建一个隐含的 Model 数据模型对象,作为模型数据的储存容器, 如果处理方法的入参为 Map 或 Model 类型,Spring MVC 会将该隐含模型的引用传递给这些入参;
 
@RequestMapping("/handle9",params={"name","password","credits"})
public String handle(User user,ModelMap modelMap){
    modelMap.put("user",User);   //将user放置到ModelMap中
    return "showUser";
}
//等同于:
@RequestMapping("/handle9",params={"name","password","credits"})
public ModelAndView handle(User user){
    return new ModelAndModel("showUser","user",user);
}
//等同于:
@RequestMapping("/handle9",params={"name","password","credits"})
public String handle(@ModelAttribute("user") User user){
    return "showUser";
}

④ @SessionAttribute

如果需要在多个请求之间共用某个模型的属性数据,可以通过在控制器类中标注@SessionAttributes ,Spring MVC 会将模型中的对应属性暂存到 HttpSession 中;
 
//同个控制器内请求重定向,同时携带模型的示例
//整个路由过程:响应 "/user/handle1" 请求,输出到 "/user/showUser" 逻辑视图
@Controller
@RequestMapping("/user")
@SessionAttributes("user")  //自动将本处理器任何处理方法属性名为"user"的模型属性透明地储存到 HttpSession 中;
public class UserController {
    @RequestMapping("/handle1")
    public String handle1(@ModelAttribute("user") User user){  //获取到的 User 对象模型会自动添加到隐含对象user中
        user.setName("assad");
        return "redirect:/user/handle1";   //转发到 "/user/handle2" 请求,此时携带了隐含对象user
    }
    @RequestMapping("/handle2")
    public String handle2(ModelMap modelMap, SessionStatus sessionStatus){
        User user = (User)modelMap.get("user");   //读取隐含模型中"user"模型的数据
        if(user != null ){
            user.setName("Vancy");
            sessionStatus.setComplete();   //清除本处理器对应的会话属性,即清除HttpSession中的"user"模型
        }
        return "/user/showUser";
    }
}


请求转发和重定向

Spring MVC 对于控制器中控制方法的请求转发和重定向提供了很方便的支持,在请求路由前加上 ”forward:“表明该请求为转发请求,前加上 “redirect:”表明该请求为重定向请求;
在 Spring MVC 控制器中转发请求和重定向请求的区别在于:
  • 转发(forward):控制器内转发请求、接受请求的处理方法之间隐含对象共享;客户端浏览器中的页面URL不变,
  • 重定向(redirect):控制器内重定向请求、接受请求的处理方法之间隐含对象不共享;客户端浏览器中的页面URL改变为重定向后的URL;
转发(forward)
 
@Controller
@RequestMapping("/user")
public class UserController {
    
   @RequestMapping(value="/handle1",params="userId")
    public String handle1(HttpServletRequest request,@RequestParam("userId") String userId){
       request.setAttribute("userId",userId);
       return "forward:/user/handle2";  //转发请求到"/user/handle2"
   }
   @RequestMapping("/handle2")
    public String handle2(HttpServletRequest request){
        return "/user/showUser";   //在"user/showUser"中 ${userId} 可以获取到"/user/handle1"的请求参数"userId"值;
   }
}
重定向(redirect
 
   @RequestMapping("/handle1")
    public String redirectToBaidu(){
       return "redirect:https://www.baidu.com";  //重定向到百度
   }
   @RequestMapping("/handle2",method=RequestMethod.GET,params="keyword")
    public String baiduSearch(@RequestParam("keyword") String keyword){
        return "redirect:https://www.baidu.com?word="+keyword;   //重定向到百度,并进行关键词搜索
   }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值