SpringMVC基础知识(2)
在之前的servlet中我们可以通过request.getParameter()来获取请求中的参数,但是在我们编写的SpringMVC的应用程序中,在具体请求的方法中并不包含request参数,
需要使用以下几个注解:
@RequestParam:获取请求的参数
@RequestHeader:获取请求头信息
@CookieValue:获取cookie中的值
@RequestParam的基本使用
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class RequestController { /** * 如何获取SpringMVC中请求中的信息 * 默认情况下,可以直接在方法的参数中填写跟请求一样的名称,此时会默认接受参数 * 如果有值,直接赋值,如果没有,那么直接给空值 * * @RequestParam:获取请求中的参数值,使用此注解之后,参数的名称不需要跟请求的名称一致,但是必须要写 * public String request(@RequestParam("user") String username){ * * 此注解还包含三个参数: * value:表示要获取的参数值 * required:表示此参数是否必须,默认是true,如果不写参数那么会报错,如果值为false,那么不写参数不会有任何错误 * defaultValue:如果在使用的时候没有传递参数,那么定义默认值即可 * @param username * @return */ @RequestMapping("/request") public String request(@RequestParam(value = "user",required = false,defaultValue = "hehe") String username){ System.out.println(username); return "success"; } }
@RequestHeader的基本使用:
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import sun.management.resources.agent; @Controller public class RequestController { /** * 如果需要获取请求头信息该如何处理呢? * 可以使用@RequestHeader注解, * public String header(@RequestHeader("User-Agent") String agent){ * 相当于 request.getHeader("User-Agent") * * 如果要获取请求头中没有的信息,那么此时会报错,同样,此注解中也包含三个参数,跟@RequestParam一样 * value * required * defalutValue * @param agent * @return */ @RequestMapping("/header") public String header(@RequestHeader("User-Agent") String agent){ System.out.println(agent); return "success"; } }
@CookieValue的基本使用
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import sun.management.resources.agent; @Controller public class RequestController { /** * 如果需要获取cookie信息该如何处理呢? * 可以使用@CookieValue注解, * public String cookie(@CookieValue("JSESSIONID") String id){ * 相当于 * Cookie[] cookies = request.getCookies(); * for(Cookie cookie : cookies){ * cookie.getValue(); * } * 如果要获取cookie中没有的信息,那么此时会报错,同样,此注解中也包含三个参数,跟@RequestParam一样 * value * required * defalutValue * @param id * @return */ @RequestMapping("/cookie") public String cookie(@CookieValue("JSESSIONID") String id){ System.out.println(id); return "success"; } }
在SpringMVC的控制中,能直接完成对象的属性赋值操作,不需要人为干预。
User.java
package com.llxazy.bean; import java.util.Date; public class User { private Integer id; private String name; private Integer age; private Date date; private Address address; //省略get/set/toString方法 }
Address.java
package com.llxazy.bean; public class Address { private String province; private String city; private String town;
//省略get/set/toString方法
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="addUser" method="post"> 编号:<input type="text" name="id"/><br> 姓名:<input type="text" name="name"/><br> 年龄:<input type="text" name="age"/><br> 日期:<input type="text" name="date"/><br> 省份:<input type="text" name="address.province"/><br> 城市:<input type="text" name="address.city"/><br> 区域:<input type="text" name="address.town"/><br> <input type="submit" value="submit"/><br> </form> </body> </html>
UserController.java
package com.llxazy.controller; import com.llxazy.bean.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class UserController { @RequestMapping("/addUser") public String addUser(User user){ System.out.println(user); return "success"; } }
2、
GET请求:在server.xml文件中,添加URIEncoding=“UTF-8”
POST请求:web.xml中编写过滤器进行实现
注意:如果配置了多个过滤器,那么字符编码过滤器一定要在最前面,否则失效。
<filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!--解决post请求乱码--> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <!--解决响应乱码--> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
package com.llxazy.controller; import com.llxazy.bean.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.ServletInputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.BufferedReader; import java.io.PrintWriter; @Controller public class UserController { @RequestMapping("/addUser") public String addUser(User user){ System.out.println(user); return "success"; } /** * SpringMVC也可以在参数上使用原生的Servlet API * * HttpSession * HttpServletRequest * HttpServletResponse * * java.security.Principal 安全协议相关 * Locale:国际化相关的区域信息对象 * InputStream: * ServletInputStream inputStream = request.getInputStream(); * OutputStream: * ServletOutputStream outputStream = response.getOutputStream(); * Reader: * BufferedReader reader = request.getReader(); * Writer: * PrintWriter writer = response.getWriter(); * @param session * @param request * @param response * @return */ @RequestMapping("api") public String api(HttpSession session, HttpServletRequest request, HttpServletResponse response){ request.setAttribute("requestParam","request"); session.setAttribute("sessionParam","session"); return "success"; } }
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map; @Controller public class OutputController { @RequestMapping("output1") public String output1(Model model){ model.addAttribute("msg","hello,Springmvc"); return "output"; } @RequestMapping("output2") public String output2(ModelMap model){ model.addAttribute("msg","hello,Springmvc"); return "output"; } @RequestMapping("output3") public String output1(Map map){ map.put("msg","hello,Springmvc"); return "output"; } }
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class OutputController { @RequestMapping("mv") public ModelAndView mv(){ ModelAndView mv = new ModelAndView(); mv.setViewName("output"); mv.addObject("msg","hello.modelAndView"); return mv; } }
发现当使用modelAndView对象的时候,返回值的类型也是此对象,可以将要跳转的页面设置成view的名称,来完成跳转的功能,同时数据也是放到request作用中。
@Controller @SessionAttributes(value = "msg") public class OutputController { @RequestMapping("output1") public String output1(Model model){ model.addAttribute("msg","hello,Springmvc"); System.out.println(model.getClass()); return "output"; } }
package com.llxazy.bean; public class User { private Integer id; private String name; private String password; private Integer age; //省略get/set/toString }
如果添加的@ModelAttribute(“”)属性的值不对,那么也是获取不到值的。同时可以添加@SessionAttributes属性,但是注意,如果没有设置值的话,会报错
UserController.java
package com.llxazy.controller; import com.llxazy.bean.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @Controller
@SessionAttributes("u") public class UserController { Object o1 = null; Object o2 = null; Object o3 = null; @RequestMapping("update") public String update(@ModelAttribute("user") User user,Model model){ System.out.println(user); o2 = model; //可以看到所有的model都是同一个对象 System.out.println(o1==o2); //可以看到存储的user对象也是同一个 System.out.println(user == o3); return "output"; } @ModelAttribute public void MyModelAttribute(Model model){ o1 = model; User user = new User(); user.setId(1); user.setName("张三"); user.setAge(12); user.setPassword("123"); model.addAttribute("user",user); System.out.println("modelAttribute:"+user); o3 = user; } }
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <form action="update" method="post"> <input type="hidden" value="1" name="id"> 姓名:李四<br> 密码:<input type="text" name="password"><br> 年龄:<input type="text" name="age"><br> <input type="submit" value="提交"> </form> </body> </html>
其实在使用的时候可以简化写法,也就是说,在方法的参数上不加@ModelAttribute也不会有问题
@RequestMapping("update")
public String update(User user,Model model){
System.out.println(user);
o2 = model;
//可以看到所有的model都是同一个对象
System.out.println(o1==o2);
//可以看到存储的user对象也是同一个
System.out.println(user == o3);
return "output";
}
注意:ModelAttribute除了可以使用设置值到model中之外,还可以利用返回值。
package com.llxazy.controller; import com.llxazy.bean.User; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.SessionAttributes; @Controller public class UserController { Object o1 = null; Object o2 = null; Object o3 = null; @RequestMapping("update") public String update(@ModelAttribute("u") User user,Model model){ System.out.println(user); o2 = model; //可以看到所有的model都是同一个对象 System.out.println(o1==o2); //可以看到存储的user对象也是同一个 System.out.println(user == o3); return "output"; } @ModelAttribute("u") public User MyModelAttribute(Model model){ o1 = model; User user = new User(); user.setId(1); user.setName("张三"); user.setAge(12); user.setPassword("123"); // model.addAttribute("user",user); System.out.println("modelAttribute:"+user); o3 = user; return user; } }
1、方法的参数使用参数的类型首字母小写,或者使用@ModelAttribute("")的值
2、先看之前是否在model中设置过该属性值,如果设置过就直接获取
3、看@SessionAttributes注解标注类中的方法是否给session中赋值,如果有的话,也是直接获取,没有报异常
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ForWardController { /** * 当使用转发的时候可以添加前缀forward:index.jsp,此时是不会经过视图解析器的,所以要添加完整的名称 * forward:也可以由一个请求跳转到另外一个请求 * @return */ @RequestMapping("/forward01") public String forward(){ System.out.println("1"); return "forward:/index.jsp"; } @RequestMapping("/forward02") public String forward2(){ System.out.println("2"); return "forward:/forward01"; } }
package com.llxazy.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class RedirectController { /** * redirect :重定向的路径 * 相当于 response.sendRedirect("index.jsp") * 跟视图解析器无关 * @return */ @RequestMapping("redirect") public String redirect(){ System.out.println("redirect"); return "redirect:/index.jsp"; } @RequestMapping("/redirect2") public String redirect2(){ System.out.println("redirect2"); return "redirect:/redirect"; } }
重定向和转发的区别:
转发:
由服务器的页面进行跳转,不需要客户端重新发送请求:
特点如下:
1、地址栏的请求不会发生变化,显示的还是第一次请求的地址
2、请求的次数,有且仅有一次请求
3、请求域中的数据不会丢失
4、根目录:localhost:8080/项目地址/,包含了项目的访问地址

重定向:
在浏览器端进行页面的跳转,需要发送两次请求(第一次是人为的,第二次是自动的)
特点如下:
1、地址栏的地址发生变化,显示最新发送请求的地址
2、请求次数:2次
3、请求域中的数据会丢失,因为是不同的请求
4、根目录:localhost:8080/ 不包含项目的名称

对比:
| 转发forward() | 重定向sendRedirect() | |
|---|---|---|
| 根目录 | 包含项目访问地址 | 没有项目访问地址 |
| 地址栏 | 不会发生变化 | 会发生变化 |
| 哪里跳转 | 服务器端进行的跳转 | 浏览器端进行的跳转 |
| 请求域中数据 | 不会丢失 |
<body> hello springmvc <img src="${ctx}/images/timg.jpg"> </body>
发现此时是找不到对应的mapping映射的,是因为DispatcherServlet会拦截所有的请求,而此时我们没有对应图片的请求处理方法,所以报错了,想要解决的话非常简单,只需要添加如下配置即可
<!-- 此配置表示 我们自己配置的请求由controller来处理,但是不能请求的处理交由tomcat来处理 静态资源可以访问,但是动态请求无法访问 --> <mvc:default-servlet-handler/> <!--保证静态资源和动态请求都能够访问--> <mvc:annotation-driven/>

浙公网安备 33010602011771号