SpringMVC的使用步骤和请求参数的获取
使用步骤:
-
导包
链接:https://pan.baidu.com/s/1b-1uN5GdeSO10cOU1GUuzQ
提取码:67mr -
配置配置文件,
-
springmvc的配置文件
- 配置注解扫描
- 配置注解解析器
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!--声明注解扫描--> <context:component-scan base-package="controller"></context:component-scan> <!--开启SpringMvc的注解驱动--> <mvc:annotation-driven></mvc:annotation-driven> <!--静态资源放行 注意,放行是指在遇到/js/的请求时,就放行,(先去找方法,找不到方法就找location的文件路径)--> <mvc:resources mapping="/js/**" location="/js/"></mvc:resources> </beans>
-
配置web.xml
- 配置DispatcherServlet的访问路径,为/
- 配置load-onstart-up
- 配置自定义springmvc的配置文件的路径
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--配置DispactherServlet--> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置自定义SpringMVC的配置文件的路径和文件名 注意: 如果没有配置则默认去当前项目下的web-inf下查找,并且文件名为 配置文件中配置的Servlet-name标签值-servlet.xml例如: mvc-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!--服务器启动就完成初始化--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/</url-pattern> <!-- /*表示拦截所有请求,/表示拦截除jsp以外的所有请求 --> </servlet-mapping> </web-app>
-
使用SpringMVC完成功能开发
- 在controller包下声明控制器类(@Controller注解)
- 在控制器类中声明单元方法(@RequestMapping(“方法的别名”))
package controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller //声明本类是个控制类 public class MyCon { @RequestMapping("dd") //声明请求方法的别名 public String demo(){ System.out.println("xixi,hello springmvc"); return "aa"; } }
-
启动项目,访问地址:localhost:8080/项目名/单元方法名
-
SpringMVC的请求参数的获取
-
紧耦方式:
/** * 紧耦合方式获取请求数据 * 使用:在单元方法上声明形参HttpServletRequest req * 作用:HttpServletRequest req形参用来接收DispatcherServlet接受的封装 * 了此次请求数据的request对象。 * 注意: * 在单元方法中使用request对象获取请求数据即可。 * 缺点: * 仍然需要程序员手动获取请求数据 */ @RequestMapping("demo1") public String demo1(HttpServletRequest request){ String sname = request.getParameter("sname"); String sage = request.getParameter("sage"); System.out.println(sname + sage); return "rr"; }
-
解耦方式:
-
方式一:
/** * 解耦方式一: * 使用:在单元方法上声明基本类型形参,接受请求数据。 * 注意: * 形参名必须和请求数据的键名一致,否则会获取不到。 * 注意2: * 如果形参中出现数值类型的参数,请求数据中对应的数据 * 必须是数值类型,否则会报错(400参数注入异常)。而且不能没有值。 * 扩展:springmvc会先获取形参的类型以及名字,拿着这个名字去找请求的key */ @RequestMapping("demo2") public String demo2(String sname,int sage){ System.out.println(sname + sage); return "rr"; }
/** * 解耦方式参数优化: * 问题: * 如果请求数据的键名和单元方法的形参名不一致怎么办? * 解决: * 在单元方法中不一致的形参前使用注解@RequestParam即可 * 使用: * RequestParam注解的属性值: * value:和键名一致的参数。 * 如果只设置不value的值,value可以省略不写。 * requred:必须的,表示该形参是否必须赋值。 * true:表示必须赋值 * false:形参可以为null,默认就是这个值 * defaultValue: * 设置形参的默认值,如果请求中没有,则将默认值赋值给形参。 * 注意: * requred和defaultValue不能同时使用。 */ @RequestMapping("demo3") public String demo3(@RequestParam(value = "sname") String sn,int sage){ System.out.println(sn + sage); return "rr"; }
-
方式二:
/** * 解耦方式二: * 问题: * 在单元方法上可以直接声明形参来接受请求数据, * 但是如果请求数据过多,使用此种方式,造成形参的 * 声明过多,怎么办? * 解决: * 直接在单元方法上声明实体类类型的形参接受请求数据即可。 * DispactherServlet会将请求数据封装到形参类型的对象中然后 * 传递给单元方法 * 注意: * 实体类的属性声明为包装类 * 属性名必须和请求数据的键名一致。 * 注意: * 如果涉及到日期类型的数据,需要在日期类型上使用注解 @DateTimeFormat(pattern="yyyy-MM-dd") * 声明转换格式。 */ @RequestMapping("demo4") public String demo4(User u){ System.out.println(u); return "rr"; }
-
方式三:
/** * 解耦方式三:获取同键不同值的请求数据 * 使用: * 在形参中使用String[]数组接受,形参名必须为请求数据的键名 * 在形参中使用List集合接受,但是必须使用@RequestParam("请求数据的键名")声明键名 */ @RequestMapping("demo5") public String demo5(@RequestParam("fav") ArrayList fav){ //处理请求 System.out.println("我是解耦方式获取同键不同值数据-----"+fav); //响应结果 return "aa"; }
-
restFul请求格式
/** * restFul请求格式 * 问题: * 使用SpringMVC的方式获取请求数据,还是用以前的Servlet获取请求数据 * 都有一个前提,请求数据的格式必须键值对,但是键值对中的键是声明在 * 前台页面中的,后获取数据的键是声明在后台的,后台获取数据的键名必须 * 和前台发送数据的键名一致,造成前台和后台之间的耦合性比较高,一旦键名 * 发生变更,就需要修改前台和后台的代码。 * 解决: * 请求数据的发送将键名移除,只发送数据。数据必须按照 * 制定的顺序排列好发送,后台按照指定的顺序获取即可。 * 实现: * restFul风格。 * 内容: * 原有格式: * localhost:8080/project/dd?sname=zhangsan&sage=18 * restFul格式: * localhost:8080/project/dd/zhangsan/18 * SpringMVC对restFul格式的支持 * 在声明单元方法别名的时候,需要声明请求数据的占位 * 例如: @RequestMapping("dd/{sname}/{sage}") * 并且需要在单元方法的形参上使用@PathVariable表明需要在路径上获取请求数据 * 注意: * 如果参数名和路径占位符的名不一致,则使用@PathVariable("路径上的占位符的名字") * 来获取数据。 */ @RequestMapping("demo6/{sname}/{age}") public String demoRest(@PathVariable String sname, @PathVariable("age") int sage){ System.out.println("restFul请求格式:"+sname+sage); return "/aa.jsp"; }
SpringMVC的其他注解
-
@RequestBody:用于获取请求体的内容,直接得到的是key=value&key=value,
注意:只适用于post请求,get请求没有请求体,不适用
<body> <form action="requestBody" method="post"> 用户名<input type="text" name="username"> 密码<input type="text" name="pwd"> <input type="submit" value="提交"> </form> </body>
@RequestMapping("requestBody") public String requestBody(@RequestBody String body){ System.out.println(body);//username=zz&pwd=123 return "show.jsp"; }
@RequestBody还可以向后台传输json数据,存到对象中
注意:如果出现415的响应码的原因: tomcat中{}是他的保留符号,我们可以修改tomcat的配置文件,释放该符号。
解决方式:修改tomcat的conf目录中的catalina.properties文件,将最后一行释放,在value中添加{}
<form id="f"> 用户名<input type="text" name="username"> 密码<input type="password" name="pwd"> <input id="btn" type="button" value="requestbody"> </form> <script type="text/javascript" src="js/j.js"></script> <script type="text/javascript"> $(function () { $("#btn").click(function () { //往后台传json数据,使用requestbody注解 var obj = $("#f").serializeArray(); var data = {} $.each(obj,function () { //遍历参数数组,将参数的值赋值给data的name属性 data[this.name] = this.value; }) /*将json字符串转换为json对象*/ var obj2 = JSON.stringify(data) $.ajax({ url:"user/addUser", contentType:"application/json", //请求头 type:"post", data:obj2, success:function(res){ alert(res.msg) } }); }) }) </script>
@RequestMapping("addUser") @ResponseBody public Map<String,String> addUser(@RequestBody User user){ //将获取到的json数据直接保存到对象中 System.out.println(user); Map<String,String> map = new HashMap<>(); map.put("msg","success"); return map; }
-
@RequestHeader:获取请求头的信息
@RequestMapping("demo2") public String demo2(@RequestHeader("Accept") String header){ System.out.println(header); //username=zz&pwd=123 return "show.jsp"; }
-
@CookieValue:用于获取指定cookie值的名称
@RequestMapping("demo3") public String demo3(@CookieValue("JSESSIONID") String cookie){ System.out.println(cookie); //username=zz&pwd=123 return "show.jsp"; }
-
@ModelAttribute:该注解是springmvc4.3之后的,表示当前方法会在控制器的方法执行之前先执行
作用:当表单提交的数据不是完整的实体类数据时,该方法就会给没有数据的属性先赋值
@RequestMapping("testModelAttribute") public String testModelAttribute(User user){ //user中封装了uname,pwd,date字段 System.out.println("testModelAttribute执行了"); return "show.jsp"; } /*该方法会先执行*/ @ModelAttribute public User show(String uname){ /*通过uname查找数据库的date值(模拟的),因为前台没有传*/ /* * 没有提交date字段,该方法会给date字段赋值 * */ User user = new User(); user.setDate(new Date()); System.out.println("show执行了"); //username=zz&pwd=123 }
如果show方法不写返回值,将user存到map集合中,之后map集合再给没有数据的字段赋值
@RequestMapping("testModelAttribute") public String testModelAttribute(@ModelAttribute("user") User user){ //user中封装了uname,pwd,date字段 System.out.println("testModelAttribute执行了"); return "show.jsp"; } /*该方法会先执行*/ @ModelAttribute public void show(String uname, Map<String,User> map){ /*通过uname查找数据库的date值(模拟的),因为前台没有传*/ /* * 没有提交date字段,该方法会给date字段赋值 * */ User user = new User(); user.setDate(new Date()); map.put("user",user); System.out.println("show执行了"); //username=zz&pwd=123 }
-
@sessionAttribute:用于多次执行控制器方法之间的参数共享
@Controller //声明本类是个控制类 @SessionAttributes(value = "msg") //先使用model将msg存到request中,在使用这个注解相当于将msg=123也存到session中 public class MyCon { /** * @return * @SessionAttribute */ @RequestMapping("testsessionAttribute") public String testsessionAttribute(Model model) { //Model和request用法一样,底层会把信息存储到request域中 model.addAttribute("msg", "123"); System.out.println("testsessionAttribute执行了"); return "show.jsp"; } @RequestMapping("getsessionAttribute") public String getsessionAttribute(ModelMap modelMap) { //ModelMap从session中获取msg值 String msg = (String) modelMap.get("msg"); System.out.println(msg); return "show.jsp"; } @RequestMapping("delsessionAttribute") public String delsessionAttribute(SessionStatus status) { //删除session中的数据 status.setComplete(); return "show.jsp"; } }
-