目录
一、Spring MVC概述
二、实现用户和程序映射
使用@RequestMapping注解
使用@PostMapping注解
使用@ GetMapping注解
三、获取用户的请求参数
传递单个参数
传递多个参数
传递一个对象
接收Json格式的数据
URL地址中获取参数
上传文件
获取Cookie信息
获取请求头Header信息
编辑 存储和获取Session信息
三、返回数据
返回静态页面
返回非静态页面的数据
请求转发
请求重定向
四、案例演示
1、利用form表单实现两数相加
2、利用ajax实现页面登录
Spring MVC是基于Servlet和MVC设计模式下实现的web项目,同时也是Spring框架中的web模块,Spring MVC是随着Spring产生而存在的一个框架。
那么什么又是MVC设计模式?
MVC的设计模式包含三层:Model、View以及Controller(模型、视图和控制器),如下为三者的关系图:
Spring MVC与MVC的区别就是MVC是设计思想,而Spring MVC是针对该思想进行的实现。
在idea中创建一个Spring MVC的项目的步骤如下:
1、点击新建一个项目:
2、选择版本号和添加相关依赖
通过使用@RequestMapping注解设置路由地址的方式来实现映射。
@RequestMapping("/hello")
public String hello(){
return "Hello!";
}
在浏览器通过url访问一般都是GET方法,但@RequestMapping注解同样支持POST方法。
指定方法的形式,使用method属性进行指定方法,value来设置路由地址:
@RequestMapping(method = RequestMethod.GET,value = "/hello")
并且@RequestMapping注解不仅可以修饰方法也能修饰类,在类之前添加的@RequestMapping注解通常可以省略。
使用@PostMapping("/xx")注解来设置路由地址来实现映射,但是该注解只支持POST方法。
使用@GetMapping("/xx")注解通过设置路由地址实现映射,但只支持GET方法。
@GetMapping("/hi")
public String hi(){
return "Hi World!";
}
可以传递单个参数来实现,此处传递的参数名一定要和前端保持一致,例如想获取User对象就可以通过传id来进行获取信息:
@RequestMapping("/getuser")
public User getUser(Integer id){
User user = new User();
user.setId(id);
user.setName("小风");
user.setAge(18);
return user;
}
通过fiddler抓包工具可以发现此处响应的是json格式,不用像使用Servlet那样需要设置返回格式,而是会根据获取的数据类型自动选择。
传递多个参数来获取信息:
@RequestMapping("/login")
public String login(String name,String password){
return "user:"+name+",password:"+password;
}
此处的参数如果和前端命名不一致,但项目已经完成,全部重命名不方便时就可以使用@RequestParam("xx")注解来设置与前端一致的命名,但是这也有缺陷,如果传入参数为空就会报错,所以就需要再给该注解的required属性设置为false。
@RequestMapping("/login")
public String login(@RequestParam(value = "user",required = false) String name, String password){
return "user:"+name+",password:"+password;
}
可以直接传递一个对象,并且 Spring MVC 可以⾃动实现参数对象的赋值。
@RequestMapping("/getinfo")
public String getUserInfo(User user){
return "用户:"+user;
}
服务器端实现Json格式的数据接收就需要使用@RequestBody注解。
通过postman模拟实现如下:
上述获取对象的方法是从URL中的请求字符串来获取参数对象,但这样优先级较低,还有一种方法就直接是在url地址中获取参数,但是需要使用@PathVariable注解,并且在@ResponseMapping注解中也要利用{}加上参数,参数之间使用“/”分割。
@RequestMapping("/user/{name}/{age}")
public String getInfo(@PathVariable String name,@PathVariable Integer age){
return "姓名:"+name+",年龄:"+age;
}
在上传文件时应该使用@RequestPart注解,其中@RequestPart中传入的参数是前端代码的文件名,为了避免上传文件的文件名重读就使用UUID来产生全球唯一的字符串进行命名,并且上传的文件的路径写在配置文件中,在不同的环境下使用不同的配置文件,但是配置文件都需以application开头,如下文件分别代表了开发环境下的配置文件信息以及生产环境下的配置文件信息:
然后在主配置文件中指明当前用的那个配置文件:
spring.profiles.active=dev
@RequestMapping("/file")
public boolean getFile(Integer id, @RequestPart("file")MultipartFile file){
boolean result = false;
String fileName = file.getOriginalFilename();
fileName = fileName.substring(fileName.lastIndexOf("."));
fileName = UUID.randomUUID()+fileName;
try {
//保存文件到本地
file.transferTo(new File(impath+fileName));
result = true;
} catch (IOException e) {
log.error("上传文件失败:"+e.getMessage());
}
return result;
}
使用postman进行模拟上传:
在本地文件中可以看到上传的文件:
在之前使用Servlet来获取Cookie信息时,首先就需要利用HttpServletRequest对象来获取所有的cookie信息,然后进行遍历。
@RequestMapping("/cookie")
public String getCookie(HttpServletRequest req){
Cookie[] cookies = req.getCookies();
StringBuilder stringBuilder = new StringBuilder();
for(Cookie item : cookies){
stringBuilder.append("CookieName:"+item.getName()+
"cookieValue:"+item.getValue()+" \n");
}
return stringBuilder.toString();
}
使用@CookieValue注解来实现Cookie信息的读取,但是使用该注解只能获取一个参数信息,若要获得多个参数的注解就需要在之后继续使用该注解来进行获取。
我们可以在前端页面的控制台先添加几个cookie信息,方便进行测试。
还想要获取age信息的话,就再使用@CookieValue注解:
@RequestMapping("/getcookie")
public String getcookie(@CookieValue("name") String namevalue,@CookieValue("age") String age){
return "nameValue:"+namevalue+",ageValue:"+age;
}
使用Servlet在进行获取时,同样要从HttpServletRequest对象中来进行获取,但是在Spring MVC项目中就可以使用@RequestHeader注解来进行获取:
@RequestMapping("header")
public String getHeader(@RequestHeader("User-Agent") String value){
return "User-Agent:"+value;
}
在获取Session信息之前先要存储Session信息,可以使用代码现将Session信息进行存储:
@RequestMapping("/setsession")
public boolean setSession(HttpServletRequest req){
boolean flag = false;
HttpSession session = req.getSession(true);//没有Session对象就先进行创建
session.setAttribute("userinfo","user");
flag = true;
return flag;
}
Session信息存储完成之后就要进行信息的获取,需要使用@SessionAttribute注解,设置value属性为要获取的Session对象,required属性设置为false,表示要获取的Session对象即使为空程序也不会进行报错。
@RequestMapping("/getsession")
public String getSession(@SessionAttribute(value = "userinfo",required = false) String info){
return "userinfo:"+info;
}
在没加任何注解的情况默认返回的是静态页面,当返回的不是静态页面就会报错:
@RequestMapping("/test")
public String get(){
return "test";
}
当修改返回的是一个html静态页面时,程序就能正确运行:
@RequestMapping("/test")
public String get(){
return "test.html";
}
当我们要返回的是非静态页面的数据时就需要用到@ResponseBody注解,该注解既能修饰类,也能修饰方法。
@Controller
@ResponseBody
public class ReceiveController {
@RequestMapping("/test")
public String get(){
return "test.html";
}
}
也能直接在类之前使用 @RestController注解来代替@Controller注解和@ResponseBody注解,来返回非静态页面的数据。
请求转发:客户端向服务器端发送请求,服务器收到请求之后会现将请求转发给目标地址,然后将目标地址的结果返回给客户端。
请求转发有两种实现方式:
方式一:在forward之后加请求转发的内容地址:
@RequestMapping("/fw")
public String fw(){
return "forward:/test.html";
}
此处若要跳转到test.html页面,切忌加@ ResponseBody注解。
方式二:使用http请求的getRequestDispatcher方法获取到要转发的对象,然后利用forwad进行转发:
@RequestMapping("fw2")
public void fw2(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/test.html").forward(req,resp);
}
请求重定向:客户端向服务端发送一个请求,然后服务器端会给客户端发送一个临时响应头,这个响应头中包含客户端需再次访问的url地址,客户端收到地址之后就需要将请求再次转发给新的目标地址。
方式一: 在redirect之后加上请求重定向的地址:
@RequestMapping("/rd")
public String rd(){
return "redirect:/test.html";
}
虽然 输入的是rd路由地址,但是会重定向到test.html。
方式二:使用HttpServletResponse对象的sendRedirect进行重定向:
@RequestMapping("/rd2")
public void rd2(HttpServletResponse resp) throws IOException {
resp.sendRedirect("/test.html");
}
请求转发 VS 请求重定向
- 定义不同:请求转发是客户端给服务器端发送请求,服务器端收到请求后会将请求转发给目标地址,然后将目标地址的结果返回给客户端;请求重定向是客户端给服务器端发送请求,服务器端收到请求之后会给客户端返回一个临时响应头,里面包含了客户端需再次访问的url地址,客户端就需要将请求再次发送新的目标url地址。
- 请求方不同:请求转发是服务器端的行为,服务器代替客户端发送请求给目标地址;请求重定向是客户端行为,客户端需将请求转发给新的目标地址。
- 数据共享不同:请求转发的客户端只发送一次请求整个交互过程就只有一个HttpRequest对象和一个HttpResponse对象,整个过程请求和返回的数据可以共享;但是请求重定向发送了两次请求,HttpResponse对象和HttpRequest对象不唯一,整个过程数据不可共享。
- 最终的url地址不同:请求转发的url地址就是请求的url地址,但是请求重定向的最终的url地址是第一次请求之后服务端返回的临时响应头中的目标url地址。
- 代码实现不同:上文已进行说明。
前端页面使用form表单实现:
后端将前端获取的两数进行相加,并将结果打印,并添加了一个可以返回的超链接:
@RequestMapping("/cal")
@ResponseBody
public String cal(Integer num1,Integer num2){
return "" + (num1+num2) +"
"+"" +
"返回";
}
效果展示:
点击add按钮之后:
前端使用ajax:
login
登录
用户名:
密 码:
后端使用返回Json格式的数据给前端:
@Controller
public class Login {
@ResponseBody
@RequestMapping("/login")
public HashMap login(@RequestBody Userinfo userinfo){
HashMap result = new HashMap<>();
int state = 200;
if(userinfo.getUsername()!= null && userinfo.getPassword() != null
&& userinfo.getUsername().equals("user") && userinfo.getPassword().equals("user")){
result.put("msg","登录成功");
}else{
result.put("msg","登录失败");
}
result.put("state",state);
return result;
}
}