URL 地址映射

@RequestMapping 注解:注解在控制器类或者控制器类的方法

  • 注解在控制类上,会将一个特定的请求或请求模式映射到一个控制器上
  • 注解在控制器类的方法上

    1. @RestController
    2. // 注解在方法上,即 http://localhost:8080/demo/** 会被映射到此控制器
    3. @RequestMapping("/demo")
    4. public class DemoController {
    5. // 访问路径:http://localhost:8080/demo
    6. @RequestMapping
    7. public String demo(){
    8. return "demo";
    9. }
    10. // 即访问路径为: 主机+端口/应用路径/类路径/方法路径
    11. // 访问路径:http://localhost:8080/demo/d01
    12. @RequestMapping(value = "/d01")
    13. public String demo01(){
    14. return "d01";
    15. }
    16. // 支持绑定多个URL
    17. @RequestMapping(value = {"/d02","/d03"})
    18. public String demo02(){
    19. return "d02";
    20. }
    21. }

@RequestMapping 参数说明:

  • value:指定请求的实际地址
  • method:请求的 method 类型,参数为 RequestMethod 枚举类的实例,常用的有
    • RequestMethod.GET
    • RequestMethod.POST
    • RequestMethod.PUT
    • RequestMethod.DELETE
  • consumes:指定处理请求提交的内容类型(Content-Type),可以使用字符串或 MediaType 类的静态变量来指定
  • produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回,可以使用字符串或 MediaType 类的静态变量来指定
  • params:指定 request 中必须包含某些参数值时,才让该方法处理
  • headers:指定 reques 中必须包含某些指定的 header 值,才能让该方法处理请求

其他衍生注解:

  • @GetMapping
  • @PostMapping
  • @DeleteMapping
  • @PutMapping

参数绑定

1、基本类型:

  • 请求参数要和方法的形参同名即可正确传参
  • 如果需要设置参数的更多细节,可以使用 @RequestParam 注解

    @RequestParam:将请求参数绑定到控制器方法的参数上(是 SpringMVC 中接受普通参数的注解)

    • value:参数名
    • required:是否包含该参数,默认为 true,表示该请求路径中必须包含该参数,如果不包含就报错
    • defaultValue:默认参数值,如果设置了该值,required = true 将失效,自动设置为 false,如果没有传递该参数,就使用默认值
  1. // http://localhost:8080/bind/p01?age=15&money=12.6&gender=true
  2. // 如果未设置默认值,某个参数未传会报500服务器异常
  3. @RequestMapping("/p01")
  4. public void p01(@RequestParam(defaultValue = "10") int age,
  5. @RequestParam(defaultValue = "12.5") double money,
  6. @RequestParam(defaultValue = "false") boolean gender) {
  7. System.out.println("age = " + age);
  8. System.out.println("money = " + money);
  9. System.out.println("gender = " + gender);
  10. }

2、基本类型的包装类型和 String 类型:

  • 请求参数要和控制器中的方法参数名一致,当某个参数未传入时,该参数为 null
  • 使用 @RequestParam 注解指定更多细节
    1. // http://localhost:8080/bind/p02?age=15&money=12.6&gender=true
    2. // 如果参数未传,该参数会被设置为null而不报错
    3. @RequestMapping("/p02")
    4. public void p02(Integer age,
    5. Double money,
    6. Boolean gender) {
    7. System.out.println("age = " + age);
    8. System.out.println("money = " + money);
    9. System.out.println("gender = " + gender);
    10. }
    11. // 访问http://localhost:8080/bind/p02,输出
    12. age = null
    13. money = null
    14. gender = null

3、数组参数绑定:简单类型的数组

  1. // http://localhost:8080/bind/p03?ints=12&ints=13&ints=14
  2. // 传参形式:ints=1&ints=2
  3. @RequestMapping("/p03")
  4. public void p03(Integer[] ints) {
  5. System.out.println(Arrays.toString(ints));
  6. }

4、JavaBean 参数绑定:

  • 请求参数和实体的属性字段同名 ```java @Data public class User { private Integer id; private String name; private Boolean gender; }

// http://localhost:8080/bind/p04?id=1&name=李四&gender=false @GetMapping(“/p04”) public void p04(User user) { System.out.println(user); }

  1. 5ListSetMap 集合类型参数绑定
  2. - 需要绑定在对象上,而不能直接写在 Controller 方法的参数中
  3. - set map 在进行绑定时必须先创建对象
  4. ```java
  5. @Data
  6. static class User {
  7. List<String> hobby;
  8. Set<String> sets = new HashSet<>();
  9. Map<String, String> maps = new HashMap<>();
  10. }
  11. // http://localhost:8080/bind/p05?hobby=basketball&hobby=baseball&sets=hello&sets=world&maps[ni]=shijie&maps[wang]=da
  12. // List参数:hobby=basketball&hobby=baseball
  13. // Set参数:sets=hello&sets=world
  14. // Map参数:maps[ni]=shijie&maps[wang]=da
  15. @RequestMapping("/p05")
  16. public void p05(User user) {
  17. System.out.println(user.getHobby());
  18. System.out.println(user.getSets());
  19. System.out.println(user.getMaps());
  20. }

控制台输出:
image.png

请求转发与重定向

静态页面的访问:

  • 静态页面不应该被直接访问,应该由前端控制器进行请求转发
  • 静态页面应该放在 WEB-INF 目录下,强制不接受外界直接访问,只能由控制器请求转发访问,此时重定向无法直接访问静态页面,需要新增一个静态页面跳转的请求转发控制器

参数值的传递:控制器得到数据后,向视图层传递数据,从而可以在视图层进行渲染,使用户看到含有数据的页面

  • 请求转发:使用 Request 作用域
  • 重定向跳转:使用 Session 作用域

请求转发与重定向:

  • 增删改之后,为了防止请求重复提交,重定向跳转
  • 在查询之后,可以作转发跳转

请求转发与重定向:
1、请求转发:

  • 使用 HttpServletRequest 的 request.getRequestDispatcher(“views/index.jsp”).forward(req, resp);
  • 使用 ViewResolver 进行跳转,即返回字符串
  • ModelAndView 请求转发 ```java @Controller @RequestMapping(“/views”) public class ViewController { @RequestMapping(“/forward01”) public String forward01() {

    1. // 跳转到绝对路径,即以 / 开头的路径,即 webapp/index.jsp 页面
    2. // 如果使用相对路径,跳转的路径会带上类上的路径,即 /views/ + 跳转
    3. return "forward:/index.jsp?username=直接转发";

    }

    @RequestMapping(“/forward02”) public ModelAndView forward02() {

    1. ModelAndView mv = new ModelAndView();
    2. // ModelAndView:模型和视图对象
    3. // mv.addObject()添加参数在请求转发时会放到Request域中
    4. mv.setViewName("forward:/index.jsp?username=请求转发");
    5. return mv;

    } }

// 路径中的参数可以在 jsp 中通过 ${param.username} 进行获取 // Request域中的参数可以通过 ${requestScope.xxx} 进行获取

  1. 2、重定向:两次请求,在SpringMVC支持多种重定向方式
  2. - 使用 HttpServletResponse 类的 response.sendRedirect() 方法
  3. ```java
  4. @RequestMapping(value="/redirect01",method = { RequestMethod.POST, RequestMethod.GET })
  5. public ModelAndView redirect01(HttpServletResponse response){
  6. response.sendRedirect("/index");
  7. return null;
  8. }
  • ViewResolver 直接跳转重定向 ```java // 不带参数 @RequestMapping(value=”/redirect02”,method = { RequestMethod.POST, RequestMethod.GET })
    public String redirect02(){
    return “redirect:/index”;
    }

// 带参数 @RequestMapping(“/redirect03”) public String redirect03(Model model, RedirectAttributes redirectAttributes) { // 重定向如果参数中存在中文,此时可能会出现乱码,通过声明 RedirectAttributes 类型参数,携带重定向参数 // 使用 RedirectAttributes 的 addAttribute 方法传递参数会跟随在URL后面 redirectAttributes.addAttribute(“username”, “世界”);

  1. // Model.addFlashAttribute()不会跟随在URL后面,而是将该参数值暂时保存于Session,待重定向url获取该参数后从session中删除
  2. // 注意此方法的redirect必须是方法映射路径,不能是jsp
  3. attr.addFlashAttribute("key", "value");
  4. return "redirect:/api/user";

}

  1. - ModelAndView 重定向
  2. ```java
  3. // 不带参数
  4. @RequestMapping(value="/redirect04",method = { RequestMethod.POST, RequestMethod.GET })
  5. public ModelAndView redirect04(){
  6. ModelAndView mv = new ModelAndView();
  7. mv.setViewName("redirect:/index.jsp");
  8. return mv;
  9. }
  10. // 带参数
  11. @RequestMapping("/redirect05")
  12. public String redirect05() {
  13. ModelAndView mv = new ModelAndView();
  14. mv.setViewName("redirect:/index.jsp");
  15. // 当视图对象为请求转发时,addObject添加的参数会添加到路径中
  16. mv.addObject("username","重定向");
  17. return mv;
  18. }

参数传递

1、参数值传递:

参数值存到 Request 域:

  • ModelAndView:返回值 ModelAndView
  • ModelMap:返回值为 String
  • Model:返回值为 String
  • Map:返回值为 String
  • HttpServletRequest:返回值为 String

参数值存到 Session 域:

  • HttpSession

    1. @Controller
    2. @RequestMapping("/views")
    3. public class ViewController {
    4. // http://localhost:8080/views/index
    5. @GetMapping("/index")
    6. public ModelAndView toIndex() {
    7. /**
    8. * 模型数据:Model
    9. * 视图信息:View
    10. */
    11. ModelAndView mv = new ModelAndView();
    12. // 添加属性
    13. mv.addObject("username", "世界之窗");
    14. // 绑定视图
    15. mv.setViewName("index");
    16. return mv;
    17. }
    18. // http://localhost:8080/views/index/01
    19. @GetMapping("/index/01")
    20. public String toIndex01(Model model) {
    21. // 通过Model进行设置
    22. model.addAttribute("username", "世界之窗1");
    23. return "index";
    24. }
    25. // http://localhost:8080/views/index/02
    26. @GetMapping(value = "/index/02")
    27. public String toIndex02(HttpServletRequest request) {
    28. // 在Request域中设置属性
    29. request.setAttribute("username", "世界之窗2");
    30. return "index";
    31. }
    32. // http://localhost:8080/views/index/03
    33. @GetMapping(value = "/index/03")
    34. public String toIndex03(ModelMap map) {
    35. // 通过ModelMap进行设置
    36. map.addAttribute("username", "世界之窗3");
    37. return "index";
    38. }
    39. // http://localhost:8080/views/index/04
    40. @GetMapping(value = "/index/04")
    41. public String toIndex04(Map<String, Object> map) {
    42. // 通过Map进行设置
    43. map.put("username", "世界之窗4");
    44. return "index";
    45. }
    46. }

    2、在 index.jsp 中获取:${username}

静态资源映射

tomcat 存在一个默认的 defaultServlet 来处理静态资源,然而在 Spring MVC 中配置了 dispatcherServlet 拦截了所有的请求,所以静态资源无法访问

1、DispatcherServlet 采用其他的 url-pattern(如 .action、.do),如所有的 handler 的路径都以 action 结尾,即在 web.xml 中对 DispatcherServlet 作如下配置:

  1. <!-- 前端控制器 -->
  2. <servlet>
  3. <servlet-name>dispatcher</servlet-name>
  4. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  5. <init-param>
  6. <!-- 指定配置文件的位置 -->
  7. <param-name>contextConfigLocation</param-name>
  8. <param-value>classpath:spring-mvc.xml</param-value>
  9. </init-param>
  10. <!-- 在web部署的时候初始化该servlet -->
  11. <load-on-startup>1</load-on-startup>
  12. </servlet>
  13. <servlet-mapping>
  14. <!-- 使用前端控制器分发do结尾的请求 -->
  15. <servlet-name>dispatcher</servlet-name>
  16. <url-pattern>*.do</url-pattern>
  17. </servlet-mapping>

2、静态资源:

  • DispatcherServlet 的 url-pattern 依然采用”/“,但追加配置,额外增加一个 handler ,且其 requestMapping 为 /**,可以匹配所有请求,但优先级最低
  • 因此其他所有的 handler 都无法匹配时,请求转向该 handler

在spring-mvc.xml中增加如下配置:

  1. <!-- 配置静态资源访问 -->
  2. <mvc:default-servlet-handler/>

3、配置 /xx/** 将静态资源文件映射到 ResourceHttpRequestHandler 进行处理

  1. <mvc:resources mapping="/js/**" location="/WEB-INF/views/js/"/>
  2. <mvc:resources mapping="/css/**" location="/WEB-INF/views/css/"/>

4、激活 tomcat 的 defaultServlet 来处理静态文件:
在 web.xml 中配置如下映射,default 为 tomcat 默认的 Servlet

  1. <servlet-mapping>
  2. <servlet-name>default</servlet-name>
  3. <url-pattern>*.jpg</url-pattern>
  4. </servlet-mapping>
  5. <servlet-mapping>
  6. <servlet-name>default</servlet-name>
  7. <url-pattern>*.png</url-pattern>
  8. </servlet-mapping>
  9. <servlet-mapping>
  10. <servlet-name>default</servlet-name>
  11. <url-pattern>*.js</url-pattern>
  12. </servlet-mapping>
  13. <servlet-mapping>
  14. <servlet-name>default</servlet-name>
  15. <url-pattern>*.css</url-pattern>
  16. </servlet-mapping>

中文乱码解决

1、前端页面中字符集统一:

  1. JSP:<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. HTML:<meta charset="UTF-8">

2、在tomcat的 server.xml 中进行设置:

  1. <Connector port="8080" redirectPort="8443" connectionTimeout="20000" protocol="HTTP/1.1" URIEncoding="utf-8"/>

3、在 web.xml 中配置一个设置编码的 filter ,对 post 请求中,中文参数乱码有效

  • SpringMVC 为我们提供了这样一个类,无需自己实现
    1. <!-- 配置文件编码过滤器 -->
    2. <filter>
    3. <filter-name>encoding</filter-name>
    4. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    5. <init-param>
    6. <param-name>encoding</param-name>
    7. <param-value>utf-8</param-value>
    8. </init-param>
    9. <init-param>
    10. <param-name>forceEncoding</param-name>
    11. <param-value>true</param-value>
    12. </init-param>
    13. </filter>
    14. <filter-mapping>
    15. <!-- 对全部请求进行过滤 -->
    16. <filter-name>encoding</filter-name>
    17. <url-pattern>/*</url-pattern>
    18. </filter-mapping>
    等效于:
    1. // 在获取参数前,设置request的编码与页面编码一致,一般写在filter中
    2. req.setCharacterEncoding("utf-8");
    3. // 响应双端的编码设置
    4. response.setContentType("text/html;charset=UTF-8");