一.注解详情
注解的内容实在是又多又麻烦哦,这里基本上都是按学的注解来的,大概上就是罗列很多,一方面是能够促进记忆,另一方面也方便自己查阅相关的注解。也有穿插一部分路径知识,有一部分没搞懂,老师讲的也不清楚,也可能我憨,烦躁哦。 ----------看注解看的憨了
一.@RequestMapping
- value 写的是路径,是一个数组的形式,可以匹配多个路径。
- path 实测是和value作用一致的,二者任选其一都可以,作用一样,下面附的图是@RequsetMapping注解的源码部分,个人觉得很奇怪,Mapping作为映射,我能理解他映射的肯定是个路径,也就是path,但是path别名是value,value别名又是path,一开始看的我是有点懵了。什么骚操作,后来查了@AliasFor别名的标签,大概意思就是他们两个互为别名,可以理解为他们实际的就是同一个东西。
// @RequestMapping(value={"/m1","/m2"})
@RequestMapping(path = {"/m1","/m2"})
public String m(){
System.out.println("进来了");
return "forward";
}
两种代码注解方式都可以,源码如下:
- method 来说,格式是:@RequestMapping(method=“RequestMethod.GET”)这里的method的作用是缩小了映射的范围,也就是在这里是get的情况下,该控制器只能接受get类型的请求,其他类型的请求会被拒绝。
- params 格式是:@RequestMapping(params={“girl”,“boy”}),这里的params实质作用也是缩小了映射的范围,必须提供这两个参数以后,才能访问。也可以限制参数值,params={“girl=wang”,"boy=“yu”}这种写法就直接限定了参数的值。
- headers 能够影响浏览器行为————一般很少用到
- consumers 消费者,媒体类型,可以限定必须为application/json;charset=UTF-8
- produces 产生的响应的类型
二.补充一下请求路径的知识
springMVC支持ant(蚂蚁)风格
- ? 一个任意字符,斜杆除外
- * 0到n个任意 字符随便都行,不能是斜杠
- ** 支持任意层路径,写法:/m/ * * 这样才可以体现出来,如果是/m * *那效果就等同于m后面任意多个字符
三.@GetMapping、@PostMapping······
- 相当于把RequsetMapping中的method方法值改成了GET,Post,限定了只支持的请求类型,其实有很多请求。
四.对于非get post请求的支持
- 对于非get post请求的支持,需要添加额外的内容,要增加一个过滤器来额外处理
- 返回的不再是页面而是数据
<!--注册一个支持所有http请求类型的过滤器-->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 表单里面还要添加一个隐藏的参数
name="_method" value=“DELETE” - 不知道什么原因嗷,这个没搞定-------发现原因了,发post请求才可以,而且路径缺少了一个y,这个路径的 东西,后面不然再发一个,单独写出来,有看到一个小技巧。
五.关于静态资源访问的问题
- 由于我们的servlet设置了URL匹配的方式为/所以,它将静态资源也当作了一个后台的请求,比如http://localhost:8080/y/static/css/index.jsp
它尝试去匹配一个static/css/index.jsp的Controller里面的ReuqestMapping的组合,因为没有,所以404,解决方式很多,最简单的,是让springmvc单独处理,将这些交给容器的默认的Servlet处理,就不让DispatcherServlet来处理了。
eg:使用index页面,链接了一个css文件,index.css,访问index页面,打开控制台后的输出有
可以看到,index.css的type是stylesheet文件,静态资源访问不到,报了404。 - 解决方法:在springMVC的xml中加入下面的内容
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation= http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
还有这个
即可,重新访问的结果如下:
注意:如果只加了default-servlet-handler的话,Controller资源全部就都不能访问了,必须加上annotation-driven,也就是开启注解,才可以。
六.@PathVariable()
- 其实是一种url的风格吧,叫做restful
- 具体内容参考罗伊菲尔丁的博士论文
- 访问路径的写法:http://localhost:8080/y/product/add/name/222/228.3f
七.@Responsebody
- 返回数据的,一般情况下返回json格式
八.关于POST请求中文乱码问题解决
- 之前在javaMVC中处理----------写一个过滤器
- 现在springMVC提供了一个编码过滤器,直接在web.xml中进行注册就可以了,init-param中的内容可以点进去CharacterEncodingFilter中就能对应上
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--指定字符编码-->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!--这个是是否强制请求编码-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
九.@ModelAttribute-----controller里面任意一个处理具体的方法之前都会执行
- 使用方式(一):
@Controller
@RequestMapping("/user")
public class User2Controller {
//就是在controller里面任意一个处理具体的方法之前都会执行,类似过滤器
@ModelAttribute
public User init(){
User user = new User();
user.setName("冬雨");
return user;
}
@RequestMapping("/login")
public String login(Model model){
System.out.println(model.containsAttribute("user"));
System.out.println(model.containsAttribute("u"));
System.out.println(model.containsAttribute("gogogo"));
return "msg";
}
}
- 如果某些对象从头到尾每次请求中都要存在,不消失,就适合这么用
- 使用方式(二):不用return的方式
@ModelAttribute
public void init(Model model){
User user = new User();
user.setName("周");
model.addAttribute("user",user);
}
@RequestMapping("/login")
public String login(@ModelAttribute User user){
System.out.println(user.getName());
return "msg";
}
- 这里要是没有传user.name那么user.name的值不会变,依然是周,但是如果一个表单提交数据中有一个input的name是name,那么这里再输出user.getName就会变成表单数据中的内容,相当于覆盖掉了原始的数据。
十.@RequestBody
- json数据,不是通过form表单传递
ajax({
data:
})
十一.@SessionAttributes------负责存会话
- 这个用在类上,会将模型自动填充到会话中
- SessionAttributes和SessionAttribute两个的用法乱七八糟的,如果用model就很简单,一旦用下面这个写法就真的就看不懂,这特么SessionAttribute中的内容到底是数值的类型还是name,页面输出的时候到底是输出SessionAttributes中的还是我接受的,然后SessionAttribute检查会话到底是监测名字还是监测tmd
@Controller
@RequestMapping("/dog")
@SessionAttributes("dog")
public class dogController {
@RequestMapping("/regist")
public String init(Dog dog){
return "dog";
}
//检查当前会话里面是否有dog
@RequestMapping("/login")
public String login(@SessionAttribute Dog dog){
return "redirect:/jsp/dog.jsp";
}
}
- 格式是:@SessionAttributes(),括号中的内容是addAttribute的键名,如果要存多个attribute(属性),写法如下
@Controller
@RequestMapping("/user3")
@SessionAttributes("user")
public class User3Controller {
@ModelAttribute("user")
public void init(Model model){
User user = new User();
user.setName("hanhan");
model.addAttribute("user",user);
}
//转发后一般数据就丢失了,这里查看是否是会话,会话不会丢失
@RequestMapping("/login")
public String login(@ModelAttribute User user){
System.out.println(user.getName());
return "redirect:/jsp/user3.jsp";
}
}
十二.@SessionAttribute---------负责检查会话中有没有某个对象
- 要求当前这次访问当中的会话里面必须有某个对象
十三.@RestController
- 作用:如果你的整个controller中的方法都是@ResponseBody的情况下,你就可以用@RestController去替换你的@Controller,并且不再需要@ResponseBody这个注解。
- @RestController = @Controller + @ResponseBody
二.关于form表单提交数据的方式
方式一:通过属性名字绑定
- 通过属性名称进行绑定,可以完成数据传递。
- 页面中表单元素的name值要和后台的形参的名字保持一致
- 如果有多个,多个形参按名字绑定即可,当传入的值较多的时候就有点麻烦
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${ctx}/user/put" method="post">
<input type="hidden" name="_method" value="put">
<input type="text" name="name">
<input type="submit" value="提交">
</form>
</body>
</html>
@Controller
@RequestMapping("/user")
public class UserController {
@PutMapping("/put")
//需要额外json包的支持,如果return map的话
@ResponseBody
public String put(String name){
System.out.println(name);
// Map<String,String> map = new HashMap<>();
// map.put("msg","ok");
return "ojbk";
}
}
方式二:@RequestParam传递请求参数
- jsp页面不变
- 后台参数略有变化
@PutMapping("/put")
//需要额外json包的支持
@ResponseBody
public String put(@RequestParam("name") String name,@RequestParam("password") String password){
System.out.println(name+password);
// Map<String,String> map = new HashMap<>();
// map.put("msg","ok");
return "ojbk";
}
方式三:直接使用pojo形式传递
- jsp不变
- 后台
@PutMapping("/put")
//需要额外json包的支持
@ResponseBody
public String put(User user){
System.out.println(user.getName()+user.getPassword());
// Map<String,String> map = new HashMap<>();
// map.put("msg","ok");
return "ojbk";
}
二.关于form表单提交日期格式数据问题
- 问题:在前端表单给后端传了Date类型的数据以后,假如使用pojo接收传递的值,那就会报错,不能获取到Date的具体值。
- 一.处理日期(没有时间)
@InitBinder("user")
public void init(WebDataBinder dataBinder){
//这里指定什么格式,前端就只能传什么格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//这里是对日期格式是否严格匹配
sdf.setLenient(false);
//
dataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,false));
}
@PostMapping("/put")
@ResponseBody
public String put (@ModelAttribute("user") User user){
System.out.println(user.getDate());
return user.getDate().toString();
}
- 二.上述方式不指定名字,根据数据类型一样可以分析解析转换成功
@InitBinder
public void init(WebDataBinder dataBinder){
//这里指定什么格式,前端就只能传什么格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//这里是对日期格式是否严格匹配
sdf.setLenient(false);
//
dataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sdf,false));
}
@PostMapping("/put")
@ResponseBody
public String put (@ModelAttribute User user){
System.out.println(user.getDate());
return user.getDate().toString();
}
- 三.在pojo属性上面添加额外的注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;