RequestMapping
一、参数
value
method(get post delete put)
(异常 404 资源不存在 405 参数有问题 500程序有异常)、
params 参数是强制限定请求参数的名称或者值,或者名称和值
二、请求风格
传统url:localhost:8080/hello?id=12&name=tom
restful url : localhost:8080/hello/12/tom
@RequestMapping("/test2/{id}/{name}")
public String test2(@PathVariable("id") Integer id ,@PathVariable("name") String name){
System.out.println("name : " + name + "id : " + id);
return SUCCESS;
}
三、映射cookie
@RequestMapping("/getcookie")
public String test3(@CookieValue("JSESSIONID") String sessionId){
System.out.println("JSESSIONID" + sessionId);
return SUCCESS;
}
四、获取模型对象数据
直接在方法参数中定义一个pojo变量,支持级联赋值
@RequestMapping("/adduser")
public String test4(User user){
System.out.println(user);
return SUCCESS;
}
<form action="/hello/adduser" method="post">
<table>
<tr><td>姓名:</td><td><input type="text" name="name"></td></tr>
<tr><td>id :</td><td><input type="text" name="id"></td></tr>
<tr><td>编码 :</td><td><input type="text" name="address.code"></td></tr>
<tr><td>值 :</td><td><input type="text" name="address.value"></td></tr>
<tr><td></td><td><input type="submit" value="提交"></td></tr>
</table>
</form>
支持级联赋值,但必须要求包含的类有无参构造,否则无法创建会出现下面异常
org.springframework.beans.NullValueInNestedPathException: Invalid property 'address' of bean class [com.zw.entity.User]: Could not instantiate property type [com.zw.entity.Address] to auto-grow nested property path; nested exception is java.lang.NoSuchMethodException: com.zw.entity.Address.<init>()
乱码问题解决:
<filter>
<filter-name>EncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
五、重定向
redirect:物理路径
forward:物理路径
否则会无限次重新访问
@RequestMapping("/test2/{id}/{name}")
public String test2(@PathVariable("id") Integer id ,@PathVariable("name") String name){
System.out.println("name : " + name + "id : " + id);
return "redirect:/index.jsp";
}
@RequestMapping("/test2/{id}/{name}")
public String test2(@PathVariable("id") Integer id ,@PathVariable("name") String name){
System.out.println("name : " + name + "id : " + id);
return "forward:/index.jsp";
}
数据绑定
基本数据类型
这里的请求id不能为空
http://localhost:8080/hello/baseType?id=12
@RequestMapping("/baseType")
@ResponseBody
public String test5(int id){
return "id:"+id;
}
http://localhost:8080/hello/baseType
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aVICy4s7-1628511898167)(D:\app\Typora\img/image-20210511101041935.png)]
http://localhost:8080/hello/baseType?id=a
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e2XRnxpY-1628511898170)(D:\app\Typora\img/sffsf)]
包装类
@RequestMapping("/packageType")
@ResponseBody
public String test6(Integer id){
return "id:"+id;
}
请求参数可以为空显示为null
@RequestMapping("/paramrequire")
@ResponseBody
public String test7(@RequestParam(value = "id",required = true,defaultValue = "0") Integer id){
return "id:"+id;
}
设置requestParam注解参数,设置其为必须,默认值为0
数组绑定
把请求参数中的names属性都添加到数组中去
@RequestMapping("/arrayType")
@ResponseBody
public String test8(String[] names){
StringBuffer buffer = new StringBuffer();
for(String name : names)
{
buffer.append(name+" ");
}
return buffer.toString();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-suOnD5IF-1628511898171)(D:\app\Typora\img/image-20210511104800464-1620701287165.png)]
绑定对象
@Data
public class User {
private Integer id ;
private String name ;
private Address address;
}
import lombok.Data;
@Data
public class Address {
private Integer code ;
private String value;
}
@RequestMapping("/adduser")
@ResponseBody
public String test4(User user){
System.out.println(user);
return user.toString();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OUZSmMov-1628511898173)(D:\app\Typora\img/image-20210511110316359-1620702199116.png)]
解决乱码问题:
添加一个类似于response中的Encoding的方法,这是是在mvc命名空间中的注解驱动里加一个消息转换器
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" id="converter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yCwcZnPf-1628511898174)(D:\app\Typora\img/image-20210511110834595.png)]
<filter>
<filter-name>EncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这里是添加一个过滤器,来防止接受请求时候乱码,而以上消息转换器是在返回给客户端信息时候防止乱码
封装集合
不接受list类型的直接转换,需要建立一个list包装类
import lombok.Data;
import java.util.List;
@Data
public class UserList {
private List<User> users;
}
这里users
@RequestMapping("/listType")
@ResponseBody
public String test9(UserList users){
StringBuffer buffer = new StringBuffer();
for(User user : users.getUsers()){
buffer.append(user.toString());
}
return buffer.toString();
}
这里的users
<form action="/hello/listType" method="post">
<table>
<tr><td>用户1姓名:</td><td><input type="text" name="users[0].name"></td></tr>
<tr><td>用户1id:</td><td><input type="text" name="users[0].id"></td></tr>
<tr><td>用户2姓名:</td><td><input type="text" name="users[1].name"></td></tr>
<tr><td>用户2id:</td><td><input type="text" name="users[1].id"></td></tr>
<tr><td>用户3姓名:</td><td><input type="text" name="users[2].name"></td></tr>
<tr><td>用户3id:</td><td><input type="text" name="users[2].id"></td></tr>
<tr><td></td><td><input type="submit" value="提交"></td></tr>
</table>
</form>
这里的users
要对应,否则无法按名称找到相应集合进行映射
另外User必须要有无参数构造,因为Userlist里的list集合需要无参构造进行对象的创建
JSON格式的封装
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BheQsNUZ-1628511898175)(D:\app\Typora\img/image-20210511210821306-1620738508584.png)]
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
以上两个步骤是让jqury可以使用,否则会因为找不到jq文件导致无法js无法访问api
$(function (){
var user = {"id":1,
"name":"王二马子"};
$.ajax({
type:"POST",
url:"/hello/jasonType",
data:JSON.stringify(user),
contentType:"application/json;charser=UTF-8",
<!--这个注解不能省略,告诉服务器发送的数据类型是json,且用UTF—8解码-->
success:function (data) {
var obj = eval("("+data+")");
alert(obj.name+obj.id);
},
dataType:"text"
})
});
$(function (){
var user = {"id":1,
"name":"王二马子"};
$.ajax({
type:"POST",
url:"/hello/jasonType",
data:JSON.stringify(user),
contentType:"application/json;charser=UTF-8",
success:function (data) {
alert(data.name+data.id);
},
dataType:"json"
})
});
前端传输需要的代码
另外需要配置转换器,阿里提供的
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter" id="converter2"/>
否则无法进入方法,因为发送过来的数据是json格式,所以需要转换器来转换成对象。还需要@RequestBody对参数进行注解
@RequestMapping("/jasonType")
@ResponseBody
public User test10(@RequestBody User user){
System.out.println(user+"经过了");
return user;
}
- 小结:
@RequestBody是把请求域中数据转化为对象
@ResponseBody是把方法结果转化为数据返回给客户端
即这两者是用来标记传输数据的
视图层解析
- Map
- Model
- ModelAndView
- @SessionAttribute
- @ModelAttribute
- Servlet API
@RequestMapping("/map")
public String mapParm(Map<String ,Object> map){
map.put("user", new User(13, "王"));
return "show";
}
@RequestMapping("/model")
public String modelParm(Model model){
model.addAttribute("user",new User(45,"宇文成都"));
return "show";
}
@RequestMapping("/mav1")
public ModelAndView mdvwParm(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user",new User(88,"李云龙"));
modelAndView.setViewName("show");
return modelAndView;
}
@RequestMapping("/mav2")
public ModelAndView mdvwParm2(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setView(new InternalResourceView("/views/show.jsp"));
modelAndView.addObject("user",new User(98,"张飞"));
return modelAndView;
}
@RequestMapping("/mav3")
public ModelAndView mdvwParm3(){
ModelAndView modelAndView = new ModelAndView("show");
modelAndView.addObject("user",new User(33,"柳如海"));
return modelAndView;
}
@RequestMapping("/mav4")
public ModelAndView mdvParm4(){
ModelAndView modelAndView = new ModelAndView(new InternalResourceView("/views/show.jsp"));
modelAndView.addObject("user",new User(56,"理想"));
return modelAndView;
}
@RequestMapping("/mav5")
public ModelAndView mdvParm5(){
Map<String,Object> map = new HashMap<>();
map.put("user",new User(34,"张二蛋"));
ModelAndView modelAndView = new ModelAndView("show",map);
return modelAndView;
}
@RequestMapping("/mav6")
public ModelAndView mdvParm6(){
Map<String,Object> map = new HashMap<>();
map.put("user",new User(44,"李刚"));
View view = new InternalResourceView("/views/show.jsp");
ModelAndView modelAndView = new ModelAndView(view,map);
return modelAndView;
}
@RequestMapping("/mav7")
public ModelAndView mdvParm7(){
ModelAndView modelAndView = new ModelAndView("show","user",new User(65,"马非"));
return modelAndView;
}
@RequestMapping("/mav8")
public ModelAndView mdvParm8(){
ModelAndView modelAndView = new ModelAndView(new InternalResourceView("/views/show.jsp"),
"user",new User(68,"罗翔"));
return modelAndView;
}
页面jq取值方式
${requestScope.user}
HttpServletRequest
直接用原生api
@RequestMapping("/request")
public String reqParm(HttpServletRequest request){
request.setAttribute("user",new User(99,"弯弯"));
return "show";
}
@ModelAttribute
@ModelAttribute
public User getUser(){
User user = new User(55, "npc");
return user;
}
@RequestMapping("/mavget")
public String mavgetdata(){
return "show";
}
课程上说ma注解方法返回值会默认覆盖其他方法的任何返回值,但是实际上实验并没有成功,可能是版本原因,先备注以下
@ModelAttribute
public void getUser(Model model){
User user = new User(55,"孙楠");
model.addAttribute("user",user);
}
这个void返回值的方法也是一样除了能够覆盖request原生方法的user,其他都不行,有待核实!!!
理论上来讲第二种的优先级更高,也就是jsp能够取到最终值
HttpServletSession
@RequestMapping("/session")
public String insertSession(HttpSession session){
session.setAttribute("user",new User(98,"张无忌"));
return "show";
}
第一种方式,通过参数直接注入
第二种:
@Controller
@RequestMapping("/view")
@SessionAttributes(value = {"user","student"})
public class ViewHandler
@Controller
@RequestMapping("/view")
@SessionAttributes(types = {User.class,Student.class})
public class ViewHandler
直接在类上注解SessionAttribute设定key值,那么传入request时候会自动保存一份到sessionscope里
Converter转换器的注册和使用(用于转换,handleradapter无法转换的自定数据)
import lombok.Data;
@Data
public class Student {
private Integer id ;
private String name ;
private Integer age ;
}
<form action="/convert/student" method="post">
学生 : <input type="text" name="student"/>
<input type="submit" value="提交"/>
</form>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FW5YY67Z-1628511898176)(D:\app\Typora\img/image-20210512195602548.png)]
对于特殊格式的数据HandlerAdapter无法自动转化,需要自己定义相应的转换器Converter
首先要根据自己的bean编写一个类来继承springmvc提供的接口org.springframework.core.convert.converter.Converter
import com.zw.entity.Student;
import org.springframework.core.convert.converter.Converter;
public class StudentConverter implements Converter<String, Student> {
@Override
public Student convert(String s) {
String[] strings = s.split("-");
Student student = new Student();
student.setId(Integer.parseInt(strings[0]));
student.setName(strings[1]);
student.setAge(Integer.parseInt(strings[2]));
return student;
}
}
在springmvc中注册
记住无法直接注册,必须先注册一个org.springframework.context.support.ConversionServiceFactoryBean,这个类将会把所有的实现的Conerter集中管理
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.zw.convert.DateConverter">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg>
</bean>
<bean class="com.zw.convert.StudentConverter"></bean>
</list>
</property>
</bean>
然后把covertsionService注册到mvc中
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" id="converter">
<property name="supportedMediaTypes" value="text/html;charset=UTF-8"/>
</bean>
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter" id="converter2"/>
</mvc:message-converters>
</mvc:annotation-driven>
package com.zw.controller;
import com.zw.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Date;
@Controller
@RequestMapping("/convert")
public class ConvertData {
@RequestMapping("/date")
@ResponseBody
public String getDate(Date date){
System.out.println(date);
return date.toString() ;
}
@RequestMapping("/student")
@ResponseBody
public String getStudent(Student student){
return student.toString();
}
}
后端逻辑代码
注意:
<mvc:annotation-driven>
</mvc:annotation-driven>
不能重复配置多个driven否则第二个会覆盖第一个
另:
@RequestMapping("/student")
@ResponseBody
public Student getStudent(Student student, HttpServletResponse resp){
resp.setContentType("text/json; charset=UTF-8");
return student;
}
想要返回的jason数据,不乱码必须在resp里设置编码方式(springboot里会解决这个问题)
springmvc 与 restful的集成
Representational State Transfer restful
- Resoucres
URI统一资源定位符,资源全网唯一地址
- Pepresentation
资源的表现形式
- State Transfer
资源不同存在形式的转换
传统url :http://localhost:8080/action?id=1
restful:http://localhost:8080/action/id/1 配合POST GET DELETE PUT进行相应操作
需要注意必须先配置filter,否则方法无法解析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yZjcyQUb-1628511898176)(D:\app\Typora\img/image-20210513100716294.png)]
<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>
@Controller
@RequestMapping("/restful")
public class RestHandler {
@ModelAttribute
public Student getByid(Student student){
student.setAge(15);
student.setName("王八大");
return student;
}
@RequestMapping(value = "/get",method = RequestMethod.GET)
@ResponseBody
public Student getS(Student student){
System.out.println(student);
return student;
}
@PostMapping (value = "/post")
@ResponseBody