SpringMVC
SpringMVC
简介
SpringMVC技术与Servlet技术功能等同,均属于web层开发技术,作用于表现层(Controller)。
是一种基于Java实现MVC模型的轻量级Web框架。
所需依赖与插件
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<build>
<finalName>Stu_SpringMVC</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port> <!-- Tomcat服务器端口号 -->
<path>/</path> <!-- 项目部署的上下文路径 -->
</configuration>
</plugin>
</plugins>
</build>
入门案例
1.导入相关依赖坐标
2.创建SpringMVC控制器类(等同于servlet功能)
3.初始化SpringMVC环境设定SpringMVC加载对应的Bean
4.写配置类,让Tomcat识别
package com.tensoflow.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月20日 10:30
*/
// 使用@Controller定义Bean
@Controller
public class UserController
{
// 设置请求路径
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save()
{
System.out.println("user save...");
return "{'username':'TenSoFlow'}";
}
}
package com.tensoflow.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月22日 9:42
*/
@Configuration
@ComponentScan("com.tensoflow.controller")
public class SpringMvcConfig
{
}
package com.tensoflow.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月22日 9:48
*/
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer
{
// 加载SpringMVC容器配置
@Override
protected WebApplicationContext createServletApplicationContext()
{
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
// 设置哪些请求路径归属SpringMVC处理
@Override
protected String[] getServletMappings()
{
return new String[]{"/"};
}
// 加载Spring容器配置
@Override
protected WebApplicationContext createRootApplicationContext()
{
return null;
}
}
包扫描问题
Spring需要扫描service、dao、domain层的包而SpringMVC需要扫描controller层的包。SpringConfig配置类中就需要使用数组的方式扫描。不能使用com.tensoflow的方式扫描,因为这会扫描到controller。
配置请求路径的前缀
package com.tensoflow.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月20日 10:30
*/
// 使用@Controller定义Bean
@Controller
// 请求路径的前缀
@RequestMapping("/user")
public class UserController
{
// 设置请求路径
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save()
{
System.out.println("user save...");
return "{'username':'TenSoFlow'}";
}
}
Get和Post请求传递参数
传递单个参数
GET请求(一个参数):http://localhost:8080/user/save?name=tensoflow
接收 地址参数名与形参变量名要相同
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(String name)
{
System.out.println(name);
return "{'username':'TenSoFlow'}";
}
传递多个参数
GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&age=18
接收 地址参数名与形参变量名要相同
@Controller
@RequestMapping("/user")
public class UserController
{
// 设置请求路径
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(String name,int age)
{
System.out.println(name);
System.out.println(age);
return "{'username':'TenSoFlow'}";
}
}
Post请求与Get请求差不多,Post请求参数不是写在地址上而是写在Body中。
指定传递多个参数
GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&age=18
接收 使用@RequestParam注解指定地址中的name赋值给username
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@RequestParam("name") String username, int age)
{
System.out.println(username);
System.out.println(age);
return "{'username':'TenSoFlow'}";
}
实体类接收参数
GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&age=18
接收 用实体类接收,实体类中的属性要与地址中的名称对应
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(User user)
{
System.out.println(user.getName());
System.out.println(user.getAge());
return "{'username':'TenSoFlow'}";
}
嵌套实体类接收参数
GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&address.name=18
接收 如果实体类中有另一个实体类,如User类中有private Address address属性,如果想为address中的name属性赋值,则地址中的参数为address.name
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(User user)
{
System.out.println(user.getAddress().getName());
return "{'username':'TenSoFlow'}";
}
数组接收参数
GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&name=18&name=Star
接收 如果需要接收数组则地址中的参数一样即可
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(String[] name)
{
for(String username : name)
{
System.out.println(username);
}
return "{'username':'TenSoFlow'}";
}
集合接收参数
GET请求(多个参数):http://localhost:8080/user/save?name=tensoflow&name=18&name=Star
接收 如果需要接收集合则地址中的参数名一样并且加上@RequestParam注解
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@RequestParam List<String> name)
{
for(String username : name)
{
System.out.println(username);
}
return "{'username':'TenSoFlow'}";
}
Json数据传递参数
所需依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
首先导入依赖然后在SpringMvcConfig上加上@EnableWebMvc注解,并在参数前加上@RequestBody注解(用于接收JSON数据格式),此时的请求应该是在Boby中选用raw下的JSON数据发送。
@Configuration
@ComponentScan("com.tensoflow.controller")
@EnableWebMvc
public class SpringMvcConfig
{
}
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@RequestBody List<String> name)
{
System.out.println(name);
return "{'username':'TenSoFlow'}";
}
传递日期参数
默认格式传递日期
GET请求:http://localhost:8080/user/save?date=2002/8/9
接收
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(Date date)
{
System.out.println(date);
return "{'username':'TenSoFlow'}";
}
指定格式传递日期
GET请求:http://localhost:8080/user/save?date=2002-10-9
接收
@RequestMapping("/save")
// 设置当前操作的返回值类型
@ResponseBody
public String save(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date)
{
System.out.println(date);
return "{'username':'TenSoFlow'}";
}
响应
响应页面
@RequestMapping("/toJumpPage")
public String save()
{
System.out.println("to ...");
return "index.jsp";
}
响应字符串
@RequestMapping("/toText")
@ResponseBody
public String save()
{
System.out.println("to ...");
return "TenSoFlow";
}
响应JSON数据
@RequestMapping("/toJSON")
@ResponseBody
public User save()
{
User user = new User();
user.setName("TenSoFlow");
user.setAge(21);
return user;
}
REST风格
REST(Representational State Transfer)表现形式状态转换。能隐藏资源的访问行为,无法通过地址得知对资源是何种操作。书写简化。

使用
无参
POST请求:http://localhost:8080/users
此时只能Post请求才行
@RequestMapping(value = "/users", method = RequestMethod.POST)
@ResponseBody
public String save()
{
System.out.println("save...");
return "{'name':'TenSoFlow'}";
}
有参
Delete请求:http://localhost:8080/users/1
@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id)
{
System.out.println(id);
return "{'name':'TenSoFlow'}";
}
最终简化形式
package com.tensoflow.controller;
import com.tensoflow.domain.User;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月20日 10:30
*/
@RequestMapping("/users")
// 是@Controller和@ResponseBody的结合
@RestController
public class UserController
{
// 设置请求路径
@PostMapping
public String save()
{
System.out.println("save...");
return "{'name':'TenSoFlow'}";
}
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id)
{
System.out.println(id);
return "{'name':'TenSoFlow'}";
}
}
表现层数据封装(Result)
package com.tensoflow.util;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月23日 9:15
*/
public class Result
{
private String message;
private Integer code;
private Object data;
public Result()
{
}
public Result(Integer code, Object data)
{
this.code = code;
this.data = data;
}
public Result(String message, Integer code, Object data)
{
this.message = message;
this.code = code;
this.data = data;
}
}
异常处理器
所有的异常均抛到表现层处理
package com.tensoflow.controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月23日 9:34
*/
@RestControllerAdvice
public class ProjectExceptionAdvice
{
// 填你希望处理的异常种类
@ExceptionHandler(Exception.class)
public void doException(Exception ex)
{
System.out.println("嘿嘿,异常你哪里跑!");
}
}
这个类的位置要让SpringMVC扫描到
拦截器
概念

拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行。
作用
1.在指定的方法调用前后执行预先设定的代码
2.阻止原始方法的执行
拦截器与过滤器

package com.tensoflow.controller.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 1. @ClassDescription:
* 2. @author: TenSoFlow
* 3. @date: 2023年10月23日 10:40
*/
@Component
public class ProjectInterceptor implements HandlerInterceptor
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
{
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

多拦截器工作流程
