Springmvc常用注解参数与返回值

发布时间 2023-04-12 22:27:55作者: 孔武

1.常用注解

1.1.@RequestMapping

@RequestMapping注解是一个用来处理请求地址映射的注解,可用于映射一个请求或一个方法,可以用在类或方法上。

  标注在方法上

用于方法上,表示在类的父路径下追加方法上注解中的地址将会访问到该方法

@Controller
public class HelloController {

    @RequestMapping("/requestTest")
    public String requestTest(){
        return "success";
    }
}

此时请求映射所映射的请求的请求路径为:

  http://localhost:8080/springmvc01/requestTest(springmvc01表示项目名

标注在类和方法上  

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

注意:当你在类上添加RequestMapping注解后,如果要请求映射,就意味着请求要先映射到标注类的位置,然后再映射到该类的方法上

@Controller
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping("/requestTest")
    public String requestTest(){
        return "success";
    }
}

此时请求映射所映射的请求的请求路径为:

http://localhost:8080/springmvc01/hello/requestTest(springmvc01表示项目名

  参数列表

 

 

 示例一:@RequestMapping的params属性

@RequestMapping(value = "/test",params = "username")
public String test(){
    return "success";
}

注意:我们设置了params属性,就意味着该请求映射的请求必须包含username才能够请求成功。

示例二:@RequestMapping的headers属性

@RequestMapping(value = "/test",headers = "Host = localhost:8081")
public String test(){
    return "success";
}

注意:如果当前请求不满足headers属性,此时页面就会显示404错误,即资源未找到。

扩展:

 @GetMapping:处理get方式请求的映射

@PostMapping:处理post方式请求的映射

@PutMapping:处理put方式请求的映射

@DeleteMapping:处理delete方式请求的映射

@GetMapping就相当于@RequestMapping(method=RequestMethod.GET),它会将get映射到特定的方法上。

1.2.@RequestParam

@RequestParam主要用于将请求参数区域的数据映射到控制层方法的参数上

 

 示例:

@RequestMapping("/queryBooks")
public List<Book> queryBooks(
    @RequestParam(required = false,defaultValue = "0",value="page") int page,
    @RequestParam(required = false,defaultValue = "10",value = "rows") int rows){
        return bookService.queryBooks(page,rows);
}

1.3.@ModelAttribute

@ModelAttribute一个具有如下三个作用:

  绑定请求参数到命令对象**:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用;

  暴露表单引用对象为模型数据**:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用;

  暴露@RequestMapping方法返回值为模型数据**:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。

示例一:绑定请求参数到命令对象

如用户登录,我们需要捕获用户登录的请求参数(用户名、密码)并封装为用户对象,此时我们可以使用@ModelAttribute绑定多个请求参数到我们的命令对象。

public String test1(@ModelAttribute("user") UserModel user) 

它的作用是将该绑定的命令对象以“user”为名称添加到模型对象中供视图页面展示使用。我们此时可以在视图页面使用${user.username}来获取绑定的命令对象的属性。

示例二:暴露表单引用对象为模型数据

@ModelAttribute
public void init(Model model){
model.addAttribute("book",new Book());
}

如上代码会在执行功能处理方法之前执行,并将其自动添加到模型对象中。

@RequestMapping("/toBookList")
public String toBookList(){
    System.out.println("toBookList");
    return "book/bookList";
}

示例三:暴露@RequestMapping方法返回值为模型数据

@ModelAttribute注解的返回值会覆盖@RequestMapping注解方法中的@ModelAttribute注解的同名命令对象。

public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user) 

1.4.@SessionAttributes

在默认情况下,当ModelMap中的属性作用域是request级别时,也就是说,当本次请求结束后,ModelMap中的属性将销毁。如果希望在多个请求中共享ModelMap中的属性,必须将其属性转存到session中,这样ModelMap的属性才会被跨请求访问;

spring允许我们有选择地指定ModelMap中的哪些属性需要转存到session中,以便下一个请求属对应的ModelMap的属性列表中还能访问到这些属性。

SpringMVC为我们提供这样一个注解来实现上面的场景:`@SessionAttributes`:将ModelMap的属性值共享到session中。

注意:@SessionAttributes注解只能使用在类上,用于在多个请求之间传递参数,类似于Session的Attribute,但不完全一样,一般来说@SessionAttributes设置的参数只用于暂时的传递(存入sessionAttributeStore),而不是长期的保存,长期保存的数据还是要放到Session中。

有两种方式将ModelMap中的属性值共享到session中:

1、使用注解的value属性:可以通过属性名指定需要放到会话中的属性;

@Controller 
@SessionAttributes("user")    //将ModelMap中key为user的属性共享到session中
public class DemoController {
    @RequestMapping("/hello")  
    public String hello(ModelMap model) {
        //向ModelMap中添加key为user和user1的属性
        model.addAttribute("user", new User(520, "U love me"));
        model.addAttribute("user1", new User("I love U"));
        return "result";
    }
}

2、使用注解的types属性:还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中。

@SessionAttributes(types = {User.class})
@Controller
public class DemoController{
    @RequestMapping("/hello")
    public String hello(Map<String, Object> map){
        map.put("user1", new User(520, "U love me"));
        return "hello";
    }
}

1.5.@RequestBody

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(即请求体中的数据的);

GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

简言之:

  一个请求:只有一个@RequestBody;
   一个请求:可以有多个@RequestParam。

Content-type:

(1)application/x-www-form-urlencoded:@RequestBody不是必须加的

(2)mutipart/form-data:@RequestBody不能处理这种格式

(3)其他格式,比如application/json,application/xml等,必须使用@RequestBody来处理

@RequestMapping("/hello")
public String toHello1(@RequestBody Book book){
    log.info(">>>> 使用@RequestBody传递JSON格式的参数:{}", JSON.toJSONString(book));
    return "index";
}

@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。

1.6.@RequestHeader

使用 @RequestHeader 注解可以获取指定的请求头信息。如果想要获取所有的请求头信息,可以使用 Map<String,String>、MultiValueMap<String,String>、HttpHeaders 这三个 Map 中的任何一个封装所有请求头的 name 和 value。

参数列表

 

  示例:

@GetMapping("/headParams")
public Map userInfo(
    @RequestHeader(value = "zking",defaultValue = "hello zking") String username,
    // 将请求头中 name=Accept-Encoding 赋值给形参 encoding
    @RequestHeader("Accept-Encoding") String encoding,
    // 将请求头中 name=Host 赋值给形参 host
    @RequestHeader("Host") String host,
    // 将所有请求头的 name 和 value 封装到 Map 集合 headsMap 中
    @RequestHeader Map<String,String> headsMap) {
        Map map = new HashMap<String, Object>();
        map.put("username",username);
        map.put("Accept-Encoding",encoding);
        map.put("Host",host);
        map.put("headsMap",headsMap);

        return map;
}

由于请求头中不存在 name=zking 这个信息,所以如果只用 value=zking 会抛出异常。

解决方案:

1、required 的默认值为 true ,也就是请求头中没有 name=zking 会报错,将其值改为 false,即没有该头信息也不报错

@RequestHeader(value = "zking",required = "false") String username

2、不修改 required=true 这个默认值,当头信息中不包含 name=zking ,给它一个默认值 hello zking

@RequestHeader(value = "zking",defaultValue = "hello zking") String username

1.7.@PathVariable

该注解请求URI中的模板变量部分到处理器功能处理方法的方法参数上的绑定。

即当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

//@PathVariable可以用来映射URL中的占位符到目标方法的参数中
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id)
{
    System.out.println("testPathVariable:"+id);
    return SUCCESS;
}

Res

即 Representational State Transfer。(资源)表现层状态转化。是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

   资源(Resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的 URI 。要获取这个资源,访问它的URI就可以,因此 URI 即为每一个资源的独一无二的识别符。
   表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层(Representation)。比如,文本可以用 txt 格式表现,也可以用 HTML 格式、XML 格式、JSON 格式表现,甚至可以采用二进制格式。
   状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)。而这种转化是建立在表现层之上的,所以就是 “表现层状态转化”。具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GETPOSTPUTDELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

示例:

- /order/1 HTTP GET    :得到 id = 1 的 order 
- /order/1 HTTP DELETE :删除 id = 1 的 order 
- /order/1 HTTP PUT    :更新 id = 1 的 order 
- /order   HTTP POST   :新增 order

1.8.@CookieValue

@CookieValue注解主要是将请求的Cookie数据,映射到功能处理方法的参数上。

参数列表

 

 示例:

@RequestMapping("/testCookieValue")
public Map<String, Object> testCookieValue(
    @CookieValue("JSESSIONID") String cookie) {
    response.put("cookie", cookie);
    return response;
}

2.参数传递

 2.1.基础类型+String

@RequestMapping("/hello")
public String toHello1(Integer bookId,String bookName){
    log.info(">>>> 基础类型+String传参:{},{}",bookId,bookName");
    return "index";
}

2.2.复杂类型

@RequestMapping("/hello")
public String toHello1(Book book,
                       Map<String,Object> params,
                       HttpServletRequest req,
                       HttpServletResponse resp,
                       HttpSession session){
    log.info(">>>> 对象传参:{}", JSON.toJSONString(book));
    log.info(">>>> Map集合传参:{}", JSON.toJSONString(params));
    log.info(">>>> HttpServletRequest/HttpServletResponse/HttpSession等等传参:{}", req.getRequestURI());
    return "index";
}

2.3.@RequestParam

@RequestMapping("/hello")
public String toHello1(@RequestParam Integer bookId,
                       @RequestParam("bName") String bookName){
    log.info(">>>> 使用@RequestParam注解传递参数:{},{}", bookId,bName);
    return "index";
}

2.4.@PathVariable

@RequestMapping("/hello/{bookId}")
public String toHello1(@PathVariable("bookId") Integer bookId){
    log.info(">>>> 使用@PathVariable注解传递参数:{}", bookId);
    return "index";
}

2.5.@RequestBody

@RequestMapping("/hello")
public String toHello1(@RequestBody Book book){
    log.info(">>>> 使用@RequestBody注解传递json数据格式的参数:{}", JSON.toJSONString(book));
    return "index";
}

请使用postman或者apipost等工具发送请求数据。

3.返回值

处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。

处理器方法返回 void 的应用场景,AJAX 响应。

/**
* 处理器返回void,响应Ajax请求
*/
@RequestMapping("/queryStudents")
public void queryStudents(HttpServletResponse response) throws IOException {

    //处理Ajax,使用json做数据格式
    Student student = new Student();
    student.setName("张三");
    student.setAge(18);

    String json = "";
    //将结果对象转为json格式数据
    if (student != null){
        ObjectMapper objectMapper = new ObjectMapper();
        json = objectMapper.writeValueAsString(student);
        System.out.println("student转换的json===="+json);
    }

    //输出数据,响应Ajax请求
    response.setContentType("application/json;charset=utf-8");
    PrintWriter pw = response.getWriter();
    pw.println(json);
    pw.flush();
    pw.close();
}

3.2.String

通过http://localhost:8080/springmvc01/toHello访问请求方法,并经过视图解析器跳转指定页面。

@RequestMapping("/toHello")
public String toHello(){
    //逻辑视图名
    return "hello";
}

返回类型为String,默认被作为视图名,指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/page/success.jsp

3.3.String+Model

通过http://localhost:8080/springmvc01/toHello访问请求方法,并经过视图解析器跳转指定页面,最后完成视图模型数据渲染操作。

@RequestMapping("/toHello")
public String toHello(Model model){
    //填充模型数据
    model.addAttribute("name","张三");
    //逻辑视图名
    return "hello";
}

3.4.ModelAndView

通过http://localhost:8080/springmvc01/toHello访问请求方法。

@RequestMapping("/toHello")
public ModelAndView toHello(){
    //创建ModelAndView
    ModelAndView mv=new ModelAndView();
    //设置逻辑视图名
    mv.setViewName("hello");
    //设置模型数据
    mv.addObject("name","张三");
    return mv;
}

4.页面跳转

转发(forward:path)和重定向(redirect:path)这两种跳转方式将会绕开视图解析器的前缀后缀;还有就是如果是在同一controller中则不用使用"/"从根目录开始,而如果是在不同的controller则一定要从根目录开始。

path为请求处理方法名,而非逻辑视图名。

转发(地址栏不变)

@RequestMapping("/helloPage")
public String toHelloPage(){
    System.out.println("toHelloPage");
    return "forward:helloBack";
}

它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用转发,既可以转发到jsp, 也可以转发到其他的控制器方法。

重定向(地址栏改变)

@RequestMapping("/helloPage")
public String toHelloPage(){
    System.out.println("toHelloPage");
    return "redirect:helloBack";
}

它相当于“response.sendRedirect(url)”。需要注意的是,如果重定向到jsp页面,则jsp页面不能写在WEB-INF目录中,否则无法找到。

5.静态资源访问

SpringMVC的工作机制是:来自浏览器的所有访问都会被前端控制器(DispatcherServlet)捕获,然后前端控制器把请求转交给处理器映射(HandlerMapping),HandlerMapping为请求分配对应的控制器(Controller)进行请求处理。

浏览器访问服务器的一个页面,实际上是包含了很多次请求的。除了请求页面本身,页面上的图片,js等静态资源也是通过请求资源在服务器上的相对地址实现的。但是SpringMVC的环境下,对静态资源的请求也会被前端控制器捕获,并转交给处理器映射。由于我们的代码中不会有对应的控制器处理请求,因此请求无法被相应,导致网页无法加载静态资源。

DispatcherServlet将捕获Web容器所有请求,包括静态资源请求

<&lt;mvc:resources> ,由springMVC框架自己处理静态资源,并可以添加一些有用的附加功能。

首先,<mvc:resources />允许静态资源放在任何地方,如WEB-INF目录下、类路径下等,你甚至可以将JavaScript等静态文件打到JAR包中。通过location属性指定静态资源的位置,由于location属性是Resources类型,因此可以使用诸如"classpath:"等的资源前缀指定资源位置。传统Web容器的静态资源只能放在Web容器的根路径下,<mvc:resources />完全打破了这个限制。

<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>

location:本地静态资源所在的目录 ,mappping:将静态资源映射到制定的路径下