SpringMVC快速上手
便利之处
springMVC在web项目中主要的作用就是对请求和响应的处理;
处理请求
原先我们需要获取前端发送的简单参数需要通过httpServletRequest.getParameter来获取
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Integer pageNumber = Integer.valueOf(req.getParameter("pageNumber"));
Integer pageSize = Integer.valueOf(req.getParameter("pageSize"));
String keyword = req.getParameter("keyword");
ResponseResult<List<Owner>> result = ownerService.pages(pageNumber, pageSize, keyword);
asyResponse(result, resp);
}
对于复杂的数据类型比如json数据需要通过ObjectMapper对象进行获取
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
Owner owner = objectMapper.readValue(req.getInputStream(), Owner.class);
ResponseResult responseResult = ownerService.add(owner);
asyResponse(responseResult, resp);
}
以上原始的方法太过于复杂,springMVC提供了更为简单的方式。
简单的get请求可以直接和方法的形参直接映射,只需要形参名字和请求带的参数名字一致;
甚至可以直接通过 @PathVariable来接收多个参数
对于json数据也可以通过 @RequestBody轻松解决
处理响应
原始的javaweb处理响应十分不便
1)需要通过response.setContentType来设置数据格式类型
2)需要通过ObjectMapper将数据转成string形式才能发送,这一步也需要我们手动完成
@SneakyThrows
protected void asyResponse(ResponseResult result, HttpServletResponse response) {
response.setContentType("application/json;charset=utf-8");
objectMapper.registerModule(new JavaTimeModule());
PrintWriter writer = response.getWriter();
writer.write(objectMapper.writeValueAsString(result));
}
springMVC对于以上步骤都进行了封装处理
当我们需要将数据传回前端时,只需要直接return,不需要关心数据类型的转换
@RequestMapping("/list")
private ResponseResult list() {
ResponseResult result = studentService.list();
return result;
}
配置文件
pom.xml文件————各种依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>J10_Project02</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.wngz</groupId>
<artifactId>SpringMvc_Case</artifactId>
<packaging>war</packaging>
<name>SpringMvc_Case Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!--scope范围,表示这个jar只能在测试环境中使用,即只能在test文件夹中使用-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<!-- springMVC的框架支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.25</version>
</dependency>
<!-- javaWeb的基础支持,
为了防止在其他环境运行时和tomcat自带的servlet冲突,scope设置为只有在开发环境适用-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<!--表示所使用的jar仅仅只是在开发环境中使用,发布时不使用-->
<scope>provided</scope>
</dependency>
<!-- 页面渲染api-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<!-- 读取和返回json格式的依赖支持-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.14.2</version>
</dependency>
</dependencies>
<build>
<finalName>SpringMvc_Case</finalName>
</build>
</project>
web.xml
<?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_4_0.xsd"
version="4.0">
<!-- 编码过滤器,过滤器要在DispatcherServlet前面配置,不然不生效-->
<!-- 过滤器本质也是servlet,配置方法和servlet一样-->
<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>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- <url-pattern>/</url-pattern>
当配置 / 的时候,会匹配到路径型的如:/login,而不会匹配到后缀型的,如:/login.jsp
当经过视图解析器返回jsp视图的时候,就不会进入到DispatcherServlet
为什么jsp的请求不会命中到DispatcherServlet呢?
因为servlet容器内的jsp的servlet将会被调用,此servlet已经默认映射在了*.jsp上,这样就不会经过DispatcherServlet,但是DispatcherServlet它能拦截到静态的资源
/* 会匹配到所有的url,路径型和后缀型,包括静态资源,当经过视图解析器返回jsp视图的时候,就会进入到DispatcherServlet
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
所以在过滤的时候就要处理返回的.jsp-->
<!-- DispatcherServlet是springmvc的核心部分,
负责请求的接收,model and view 的各种分配和调度,控制各种handle来完成请求和响应-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- springmvc依附于spring容器,因此需要告诉DispatcherServlet配置的spring容器的路径-->
<!-- 如果spring配置容器在web.xml同路径下就不需要配置-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- DispatcherServlet需要配置成tomcat启动时就加载完成,否则接收不到请求-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
resources/springmvc.xml
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.wngz.springmvc.controller"></context:component-scan>
<!-- 表示静态资源有默认的servlet调用-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!-- 若没有该标签@Controller @RequestMapping("/hello")等标签不会生效-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
特性
配置类WebMvcConfigurer
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyWrapHandler;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Properties;
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
// 配置路径匹配选项
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// 默认情况下,使用后缀模式匹配(例如.html)和尾部斜杠匹配(/)。
// 设置是否使用后缀模式匹配
configurer.setUseSuffixPatternMatch(false);
// 设置是否使用前缀模式匹配
configurer.setUseTrailingSlashMatch(true);
}
// 配置内容协商选项
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
// 默认不启用参数内容协商,只根据请求的文件扩展名进行内容协商。
// 启用参数内容协商
configurer.favorParameter(true);
// 设置参数名称
configurer.parameterName("mediaType");
// 启用扩展名内容协商
configurer.favorPathExtension(true);
}
// 配置异步请求支持选项
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
//默认超时时间为30秒。
//使用默认的SimpleAsyncTaskExecutor作为异步任务执行器。
// 设置默认的超时时间
configurer.setDefaultTimeout(5000);
// 添加自定义的异步任务执行器
configurer.setTaskExecutor(new SimpleAsyncTaskExecutor());
}
// 配置默认Servlet处理选项
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
//默认情况下启用,映射所有不被@RequestMapping或其他处理器显式处理的请求到Servlet容器的默认Servlet。
// 启用默认的Servlet处理
configurer.enable();
}
// 添加格式化器和转换器
@Override
public void addFormatters(FormatterRegistry registry) {
// 添加自定义的格式化器
registry.addFormatter(new DateFormatter("yyyy-MM-dd"));
}
// 添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加自定义的拦截器
registry.addInterceptor(new MyCustomInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login");
}
// 添加资源处理器,用于静态资源的处理
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//默认情况下,没有显式添加静态资源处理器。静态资源通常直接由Servlet容器处理,例如Tomcat或Jetty。
// 将所有 /static/** 的请求映射到 classpath:/static/ 目录下的资源
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
// 添加跨域资源共享(CORS)映射
@Override
public void addCorsMappings(CorsRegistry registry) {
//默认情况下不启用任何跨域资源共享配置,即不允许跨域请求。
// 允许来自任意源的跨域请求
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowCredentials(true)
.maxAge(3600);
}
// 添加视图控制器
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//默认情况下,没有添加任何视图控制器或视图解析器,因此所有视图解析工作交给视图解析链中的默认解析器处理。
// 将 / 请求映射到 home.html 视图
registry.addViewController("/").setViewName("home.html");
}
// 配置视图解析器
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// 配置JSP视图解析器
registry.jsp("/WEB-INF/views/", ".jsp");
}
// 添加自定义的参数解析器
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// 添加自定义的参数解析器
resolvers.add(new MyCustomArgumentResolver());
}
// 添加自定义的返回值处理器
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
// 添加自定义的返回值处理器
handlers.add(new ResponseBodyWrapHandler());
}
// 配置消息转换器
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// 添加自定义的消息转换器
converters.add(new MappingJackson2HttpMessageConverter());
}
// 扩展消息转换器
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 在现有转换器之前添加自定义的消息转换器
converters.add(0, new MyCustomMessageConverter());
}
// 配置异常解析器
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
// 添加简单的映射异常解析器
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty("org.springframework.web.servlet.PageNotFound", "error-404");
mappings.setProperty("org.springframework.dao.DataAccessException", "error-database");
exceptionResolver.setExceptionMappings(mappings);
resolvers.add(exceptionResolver);
}
// 扩展异常解析器
@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
// 在现有解析器之前添加自定义的异常解析器
resolvers.add(0, new MyCustomExceptionResolver());
}
// 获取验证器
@Nullable
@Override
public Validator getValidator() {
// 返回自定义的验证器
return new LocalValidatorFactoryBean();
}
// 获取消息码解析器
@Nullable
@Override
public MessageCodesResolver getMessageCodesResolver() {
// 返回自定义的消息码解析器
return new DefaultMessageCodesResolver();
}
}
拦截器 HandlerInterceptor
Filter和HandlerInterceptor的区别
Filter 定义:
Filter是Java Servlet规范的一部分,定义在javax.servlet.Filter接口中,用于对请求和响应进行过滤。
作用范围:
Filter可以对几乎所有的请求进行拦截,包括静态资源(如HTML、CSS、JavaScript文件)和动态资源(如Servlet、JSP)。
生命周期:
Filter在整个应用程序启动时被初始化,并在应用程序关闭时销毁。每个请求都会调用Filter的doFilter方法。
用途:
-
认证和授权:检查用户是否登录,或者判断用户是否有权限访问某些资源。
-
日志记录:记录请求的详细信息,例如IP地址、请求时间、请求参数等。
-
压缩响应:在将响应发送回客户端之前对其进行压缩。
-
字符编码:设置请求和响应的字符编码,确保正确处理不同的字符集。
-
跨域资源共享(CORS):处理跨域请求,设置CORS相关的头信息。
示例:
public class MyFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 预处理代码
System.out.println("Request received at MyFilter");
chain.doFilter(request, response); // 将请求传递给下一个过滤器或目标资源
// 后处理代码
System.out.println("Response processed at MyFilter");
}
public void destroy() {
// 销毁代码
}
}
Spring MVC HandlerInterceptor 定义:
HandlerInterceptor是Spring框架的一部分,定义在org.springframework.web.servlet.HandlerInterceptor接口中,用于拦截处理器(controller)的执行过程。
作用范围:
HandlerInterceptor主要用于拦截Spring MVC的处理器方法。它不拦截静态资源,除非特别配置。
生命周期:
HandlerInterceptor的生命周期与Spring上下文相关。它们在Spring容器初始化时创建,并在容器关闭时销毁。
用途:
-
预处理和后处理:在处理请求之前执行逻辑(例如身份验证),在处理请求之后但在生成视- 图之前执行逻辑(例如日志记录)。
-
修改请求和响应:可以修改请求对象或响应对象中的数据。
-
执行链控制:可以决定是否继续执行处理器链。
方法:
-
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
:在处理器方法执行之前调用。 -
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
:在处理器方法执行之后且在视图渲染之前调用。 -
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
:在整个请求完成之后,即视图渲染之后调用。
示例:
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("Request received at MyInterceptor");
return true; // 返回true表示继续处理,返回false表示中断处理
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Handler executed at MyInterceptor");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("Request completed at MyInterceptor");
}
}
配置拦截器
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
JwtTokenTemplate jwtTokenTemplate;
@Override
public void addInterceptors(InterceptorRegistry registry) {
List<String> whiteList = new ArrayList<>();
//白名单
whiteList.add("/**/*.html");
whiteList.add("/js/**/*");
whiteList.add("/");
whiteList.add("/user/login");
whiteList.add("/code/generate");
registry.addInterceptor(new TokenInterceptor(jwtTokenTemplate))
.excludePathPatterns(whiteList);//添加白名单
}
}
@Controller,@Service,@Reposity
作用和javaweb的@WebServlet一样
标记为一个webServlet
注意:若用该三种注解标注Servlet,需要有返回值的方法必须用@ResponseBody标注
@Controller
@RequestMapping("/hello")
public class HelloController {
public HelloController() {
System.out.println("HelloController~~~");
}
//@RequestMapping默认为Get,Post请求都匹配
@RequestMapping("/demo1")
@ResponseBody
//当需要返回值时,如果该Controller没有标记为RestController则需要加上@ResponseBody注解
public String demo1() {
return "woniu school";
}
@RequestMapping("/student")
@ResponseBody
public Student getStudent() {
Student student = new Student();
student.setName("张三");
student.setAge(19);
return student;
}
}
@RestController
作用同样是标记为一个webServlet
不同的是使用该注解标记的Servlet类不需要在方法上标注 @ResponseBody
相当于 @Controller+@ResponseBody
@RestController
@RequestMapping("/subject")
public class SubjectController {
@Autowired
private SubjectService subjectService;
@RequestMapping("/list")
private ResponseResult list() {
ResponseResult result = subjectService.list();
return result;
}
}
@RequestMapping(请求路径匹配)
用作请求路径的匹配;
作用在类上标记该servlet映射的路径;
作用在方法上同样道理,
需要注意的是如果要访问servlet的具体方法时,url需要包含Servlet类上@RequestMapping("/exam")的路径和方法上@RequestMapping("/add")的路径
@RequestMapping("/exam")
public class ExamController {
@Autowired
private ExamService examService;
@RequestMapping("/add")
protected ResponseResult add(@RequestBody Exam exam) {
ResponseResult result=examService.add(exam);
return result;
}
}
元注解:
@Target({ElementType.TYPE, ElementType.METHOD})=>可以作用在类和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
}
@GetMapping
作用和@RequestMapping一样,不过只能标注在方法上
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.GET}
)
public @interface GetMapping {
}
@PostMapping
作用和@RequestMapping一样,不过只能标注在方法上
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.GET}
public @interface PostMapping {
}
@PutMapping
作用和@RequestMapping一样,不过只能标注在方法上
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.GET}
public @interface PutMapping {
}
@DeleteMapping
作用和@RequestMapping一样,不过只能标注在方法上
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.GET}
public @interface DeleteMapping {
}
接收前端发送的参数!!!
普通get请求(参数在url上)
单个参数
后端获取方式:在方法的参数列表中写上参数,当请求匹配到时可自动映射
注意:方法列表中的参数名要和get请求带的参数名要一一对应
前端:
axios.get("/exam/remove?id=" + exam.id)
controller:
@RequestMapping("/remove")
protected ResponseResult remove(Integer id) {
ResponseResult result=examService.remove(id);
return result;
}
多个参数 @PathVariable
当通过get发送多个参数数据时,需要使用@PathVariable来指定
注意:@PathVariable指定的参数名要和路径的参数名保持一致
前端:
axios.get(`/owner/page/${this.pageNumber}/${this.pageSize}` )
controller:
@GetMapping("/page/{pageNumber}/{pageSize}")
public ResponseResult page(@PathVariable Integer pageNumber,
@PathVariable Integer pageSize) {
PageHelper.startPage(pageNumber, pageSize);
List<Owner> owners = ownerMapper.selectAll();
PageInfo pageInfo = new PageInfo(owners);
ResponseResult result = ResponseResult.success(pageInfo);
return result;
}
post发送复杂数据类型@RequestBody
前端:直接将json对象放在请求体中
axios.post("/owner/add", this.owner4Add)
controller:
在方法参数列表中通过@RequestBody注解来标注接收复杂类型对象
//接收单个JSON对象
@PostMapping("/add")
protected ResponseResult add(@RequestBody Owner owner) {
ResponseResult responseResult = ownerService.add(owner);
return responseResult;
}
//接收前端数组对象
@PostMapping("/batchDelete")
protected ResponseResult batchDelete(@RequestBody Integer[] ids) {
ResponseResult responseResult = ownerService.batchDelete(ids);
return responseResult;
}
原文地址:https://blog.csdn.net/wyh2943455568/article/details/143465735
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!