SpringMVC全面复习

Javaweb

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

SpringMVC

Spring MVC是Spring框架的一个模块,专门用于构建Web应用程序的模型-视图-控制器(MVC)架构。它通过清晰的分离关注点,简化了Web应用各部分的开发。Spring MVC提供了强大的绑定机制,能够将请求参数绑定到控制器方法的参数上,支持灵活的验证和数据转换。它还内置了对RESTful API的支持,使得开发者可以轻松构建REST风格的Web服务。Spring MVC的分发器DispatcherServlet负责将请求路由到相应的控制器,而视图解析器则负责渲染响应的视图。此外,Spring MVC与Spring的其他模块如Spring Security和Spring Data无缝集成,提供了全面的安全、数据访问和事务管理功能,使得构建健壮、可维护的Web应用程序变得更加容易。

在这里插入图片描述
在这里插入图片描述
导入Spring整合SpringMVC的坐标

<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.7</version>
</dependency>

创建Spring的配置文件applicationContext.xml,配置Spring包扫描

<context:component-scan base-package="com.mem.service"/>

在web.xml中配置SpringMVC的前端控制器ServletDispatcher

<!-- 创建Servlet WebApplicationContext容器的配置 -->
<servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!--加载Spring MVC的配置文件--><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value></init-param><!--可以设置该servlet在加载时的优先级以及是否在容器中加载该servletTomcat依次执行的是DispatcherServlet中的静态代码块,构造方法,init()方法--><load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>DispatcherServlet</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

这里的/表示这是一个根路径模式,意味着DispatcherServlet将映射到应用的根路径,并且可以处理进入应用的所有HTTP请求。
编写一个控制器Controller,配置映射信息,并交给SpringMVC容器管理

@Controller//交给spring容器进行管理
public class QuickController {@RequestMapping("/show")//配置映射路径public void show(){System.out.println("show ...");}
}

在这里插入图片描述
控制台正常打印show …
报错原因:show()方法应该返回视图名字
改进: 将controller层中的show()方法返回值改为String,并添加上相应的页面

@Controller
public class QuickController {@RequestMapping("/show")public String show(){System.out.println("show ...");return "/show.jsp";}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title></title>
</head>
<body><h1>show</h1>
</body>
</html>

Controller中访问容器中的Bean
创建service层

public interface QuickService {
}@Service
public class QuickServiceImpl implements QuickService {
}

创建Spring的配置文件applicationContext.xml,配置Spring包扫描

<!--组件扫描-->
<context:component-scan base-package="com.mem.service"/>

在web.xml中配置ContextLoadListener及初始参数

<!-- 创建Root WebApplicationContext容器的配置 -->
<!--加载Spring的配置文件-->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置ContextLoaderListener(官方提供的)-->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

在Controller层注入QuickService对象

@Controller
public class QuickController {@Autowiredprivate QuickService quickService;@RequestMapping("/show")public String show(){System.out.println("show ...");System.out.println("quickService:"+quickService);return "/show.jsp";}
}

测试:控制台打印出quickService的地址quickService:com.mem.service.impl.QuickServiceImpl@5f87226c
Spring笔记(四)(黑马)(web层解决方案-SpringMVC)
在这里插入图片描述
SpringMVC关键组件浅析
在这里插入图片描述
在这里插入图片描述
SpringMVC的默认组件,SpringMVC 在前端控制器 DispatcherServlet加载时,就会进行初始化操作,在进行初始化时,就会加载SpringMVC默认指定的一些组件,这些默认组件配置在 DispatcherServlet.properties 文件中,该文件存在与spring-webmvc-5.3.7.jar包下的 org\springframework\web\servlet\DispatcherServlet.properties
在这里插入图片描述
这些默认的组件是在DispatcherServlet中进行初始化加载的,在DispatcherServlet中存在集合存储着这些组件, SpringMVC的默认组件会在 DispatcherServlet 中进行维护,但是并没有存储在与SpringMVC的容器中

public class DispatcherServlet extends FrameworkServlet {//存储处理器映射器private List<HandlerMapping> handlerMappings;//存储处理器适配器private List<HandlerAdapter> handlerAdapters;//存储视图解析器private List<ViewResolver> viewResolvers;// ... 省略其他代码 ...protected void initStrategies(ApplicationContext context) {this.initMultipartResolver(context);this.initLocaleResolver(context);this.initThemeResolver(context);this.initHandlerMappings(context); // 以这个为例this.initHandlerAdapters(context);this.initHandlerExceptionResolvers(context);this.initRequestToViewNameTranslator(context);this.initViewResolvers(context);this.initFlashMapManager(context);}private void initHandlerMappings(ApplicationContext context) {// 获取DispatcherServlet.properties文件中的三个类this.handlerMappings = this.getDefaultStrategies(context, HandlerMapping.class);}
}

配置组件代替默认组件,如果不想使用默认组件,可以将替代方案使用Spring Bean的方式进行配置,例如,在 spring-mvc.xml中配置RequestMappingHandlerMapping

<!--使用自定义的HandlerMapping,替代默认的HandlerMapping-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

当我们在Spring容器中配置了HandlerMapping,则就不会在加载默认的HandlerMapping策略了,原理比较简单, DispatcherServlet 在进行HandlerMapping初始化时,先从SpringMVC容器中找是否存在HandlerMapping,如果 存在直接取出容器中的HandlerMapping,在存储到 DispatcherServlet 中的handlerMappings集合中去。

Spring MVC 的请求处理
在这里插入图片描述
@RequestMapping注解,主要使用在控制器的方法上,用于标识客户端访问资源路径,常用的属性有value、path 、method、headers、params等。当@RequestMapping只有一个访问路径需要指定时,使用value属性、path属 性或省略value和path,当有多个属性时,value和path不能省略

@RequestMapping(value = "/show")//使用value属性指定一个访问路径
public String show(){}
@RequestMapping(value = {"/show","/haohao","/abc"})//使用value属性指定多个访问路径
public String show(){}
@RequestMapping(path = "/show")//使用path属性指定一个访问路径
public String show(){}
@RequestMapping(path = {"/show","/haohao","/abc"})//使用path属性指定多个访问路径
public String show(){}
@RequestMapping("/show")//如果只设置访问路径时,value和path可以省略
public String show(){}
@RequestMapping({"/show","/haohao","/abc"})
public String show(){}

当@RequestMapping 需要限定访问方式时,可以通过method属性设置

//请求地址是/show,且请求方式必须是POST才能匹配成功
@RequestMapping(value = "/show",method = RequestMethod.POST)
public String show(){}

@GetMapping
当请求方式是GET时,我们可以使用@GetMapping替代@RequestMapping
@PostMapping
当请求方式是POST时,我们可以使用@PostMapping替代@RequestMapping
@RequestMapping 在类上使用,@RequestMapping 、@GetMapping、@PostMapping还可以使用在 Controller类上,使用在类上后,该类所有方法都公用该@RequestMapping设置的属性,访问路径则为类上的映射 地址+方法上的映射地址,例如:

@Controller
@RequestMapping("/xxx")
public class UserController implements ApplicationContextAware, ServletContextAware {@GetMapping("/aaa")public ModelAndView aaa(HttpServletResponse response) throws IOException, ModelAndViewDefiningException {return null;}
}

请求数据的接收
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
客户端传递多个同名参数时,也可以使用单列集合接收,但是需要使用@RequestParam告知框架传递的参数是要同名设置的,不是对象属性设置的
在这里插入图片描述
在这里插入图片描述
收实体JavaBean属性数据
接收实体JavaBean属性数据,单个JavaBean数据:提交的参数名称只要与Java的属性名一致,就可以进行自动封装

public class User {private String username;private Integer age;private String[] hobbies;private Date birthday;private Address address;//... 省略get和set方法 ... 
}
public class Address {private String city;private String area;
}@GetMapping("/show")
public String show(User user){System.out.println(user);return "/index.jsp";
}

接收Json数据格式数据
接收Json数据格式数据,Json数据都是以请求体的方式提交的,且不是原始的键值对格式的,所以我们要使用 @RequestBody注解整体接收该数据。

@PostMapping("/show")
public String show((@RequestBody String body){System.out.println(body);return "/index.jsp";
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用Rest风格:
接收Restful风格数据,Restful请求数据一般会在URL地址上携带,可以使用注解 @PathVariable(占位符参数名称)
http://localhost:8080/user/100

@PostMapping("/user/{id}")
public String findUserById(@PathVariable("id") Integer id){System.out.println(id);return "/index.jsp";
}

请求URL资源地址包含多个参数情况:http://localhost:8080/user/haohao/18

@PostMapping("/user/{username}/{age}")
public String findUserByUsernameAndAge(@PathVariable("username") String username,@PathVariable("age") Integer age){System.out.println(username+"=="+age);return "/index.jsp";
}

在这里插入图片描述
服务器端,由于映射器适配器需要文件上传解析器,而该解析器默认未被注册,所以手动注册

<!--配置文件上传解析器,注意:id的名字是固定写法-->
<bean id="multipartResolver" 
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="defaultEncoding" value="UTF-8"/><!--文件的编码格式 默认是ISO8859-1--><property name="maxUploadSizePerFile" value="1048576"/><!--上传的每个文件限制的大小 单位字节--><property name="maxUploadSize" value="3145728"/><!--上传文件的总大小--><property name="maxInMemorySize" value="1048576"/><!--上传文件的缓存大小-->
</bean>

而CommonsMultipartResolver底层使用的Apache的是Common-fileuplad等工具API进行的文件上传

<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version>
</dependency>

使用MultipartFile类型接收上传文件

@PostMapping("/fileUpload")
public String fileUpload(@RequestBody MultipartFile myFile) throws IOException {System.out.println(myFile);//获得上传的文件的流对象InputStream inputStream = myFile.getInputStream();//使用commons-io存储到C:\haohao\abc.txt位置FileOutputStream outputStream = new FileOutputStream("C:\\Users\\haohao\\"+myFile.getOriginalFilename());IOUtils.copy(inputStream,outputStream);//关闭资源inputStream.close();outputStream.close();
return "/index.jsp";
}

若接收多个文件,变为数组即可

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Javaweb常用对象的获取
获得Javaweb常见原生对象,有时在我们的Controller方法中需要用到Javaweb的原生对象,例如:Request、 Response等,我们只需要将需要的对象以形参的形式写在方法上,SpringMVC框架在调用Controller方法时,会自动传递实参:

@GetMapping("/javawebObject")
public String javawebObject(HttpServletRequest request, HttpServletResponse response, 
HttpSession session){System.out.println(request);System.out.println(response);System.out.println(session);return "/index.jsp";
}

请求静态资源
静态资源请求失效的原因,当DispatcherServlet的映射路径配置为 / 的时候,那么就覆盖的Tomcat容器默认的缺省 Servlet在Tomcat的config目录下有一个web.xml 是对所有的web项目的全局配置,其中有如下配置
在这里插入图片描述

url-pattern配置为 / 的Servlet我们称其为缺省的Servlet,作用是:当其他Servlet都匹配不成功时,就找缺省的Servlet ,静态资源由于没有匹配成功的Servlet,所以会找缺省的DefaultServlet,该DefaultServlet具备二次去匹配静态资源的功能。但是我们配置DispatcherServlet后就将其覆盖掉了,而DispatcherServlet会将请求的静态资源的名称当成Controller的映射路径去匹配,即静态资源访问不成功了!
第一种方案:
在web.xml中,可以再次激活Tomcat的DefaultServlet,Servlet的url-pattern的匹配优先级是:精确匹配>目录匹配> 扩展名匹配>缺省匹配,所以可以指定某个目录下或某个扩展名的资源使用DefaultServlet进行解析:
在这里插入图片描述
在这里插入图片描述
注解驱动mvc:annotation-driven标签
静态资源配置的第二第三种方式我们可以正常访问静态资源了,但是Controller又无法访问了,报错404,即找不到对应的资源
在这里插入图片描述
又结合组件浅析知识点,一旦SpringMVC容器中存在 HandlerMapping 类型的组件时,前端控制器 DispatcherServlet在进行初始化时,就会从容器中获得HandlerMapping ,不在加载 dispatcherServlet.properties 中默认处理器映射器策略,那也就意味着RequestMappingHandlerMapping不会被加载到了。

RequestMappingHandlerMapping的作用是:解析@RequestMapping(“”)注解的,最后容器中没有RequestMappingHandlerMapping的bean 也就没办法识别里面的内容了

解决方法:
手动将RequestMappingHandlerMapping也注册到SpringMVC容器中就可以了,这样DispatcherServlet在进行初始化时,就会从容器中同时获得RequestMappingHandlerMapping存储到DispatcherServlet中名为 handlerMappings的List集合中,对@RequestMapping 注解进行解析。

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

根据上面的讲解,可以总结一下,要想使用@RequestMapping正常映射到资源方法,同时静态资源还能正常访问, 还可以将请求json格式字符串和JavaBean之间自由转换,我们就需要在spring-mvc.xml中进行如下配置:

<!--使用RequestMappingHandlerAdapter,内部添加messageConverters: 实现遇到json格式自动转换为对象格式-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"><property name="messageConverters"><list><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/></list></property>
</bean>

在这里插入图片描述

PS: mvc:annotation-driven/ 标签在不同的版本中,帮我们注册的组件不同。
Spring 3.0.X 版本注册是 DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter,由于框架的发展,从Spring 3.1.X 开始注册组件变为 RequestMappingHandlerMapping和RequestMappingHandlerAdapter

Spring MVC 的响应处理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
响应模型数据,响应模型数据本质也是转发,在转发时可以准备模型数据

@RequestMapping("/resp3")
public ModelAndView resp3(ModelAndView modelAndView){// ModelAndView封装模型数据和视图名// 设置模型数据User user = new User();user.setUsername("haohao");user.setAge(18);modelAndView.addObject("user",user);// 设置试图名,在页面中展示模型数据modelAndView.setViewName("/show.jsp");return modelAndView;
}

直接回写数据,直接通过方法的返回值返回给客户端的字符串,但是SpringMVC默认的方法返回值是视图,可以通过 @ResponseBody 注解显示的告知此处的返回值不要进行视图处理,是要以响应体的方式处理的

@RequestMapping("/resp4")
@ResponseBody
public String resp4(){return "hello world!";
}

前后端分类异步业务数据响应
在这里插入图片描述
回写Json格式的字符串,即将直接拼接Json格式的字符串或使用工具将JavaBean转换成Json格式的字符串回写

@GetMapping("/ajax/resp1")
@ResponseBody
public String resp1(){return "{\"username\":\"haohao\",\"age\":18}";
}@GetMapping("/ajax/resp2")
@ResponseBody
public String resp2() throws JsonProcessingException {//创建JavaBeanUser user = new User();user.setUsername("haohao");user.setAge(19);//使用Jackson转换成json格式的字符串String json = new ObjectMapper().writeValueAsString(user);return json;
}

在讲解SringMVC接收请求数据时,客户端提交的Json格式的字符串,也是使用Jackson进行的手动转换成JavaBean ,可以当我们使用了@RequestBody时,直接用JavaBean就接收了Json格式的数据,原理其实就是SpringMVC底层 帮我们做了转换,此处@ResponseBody也可以将JavaBean自动给我们转换成Json格式字符串回响应

@GetMapping("/ajax/resp3")
@ResponseBody
public User resp3() throws JsonProcessingException {//创建JavaBeanUser user = new User();user.setUsername("haohao");user.setAge(20);//直接返回User对象return user;
}

进一步优化,可以使用@RestController替代@Controller和@ResponseBody,@RestController内部具备的这两个 注解的功能

@RestController
public class ResponseController2 {@GetMapping("/ajax/resp1")//    @ResponseBodypublic String resp1(){return "{\"username\":\"haohao\",\"age\":18}";}@GetMapping("/ajax/resp2")//    @ResponseBodypublic String resp2() throws JsonProcessingException {//创建JavaBeanUser user = new User();user.setUsername("haohao");user.setAge(19);//使用Jackson转换成json格式的字符串String json = new ObjectMapper().writeValueAsString(user);return json;}
}

Spring MVC 的拦截器
在这里插入图片描述
在这里插入图片描述
实现了HandlerInterceptor接口,且被Spring管理的Bean都是拦截器,接口定义如下:

public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}
}

在这里插入图片描述
拦截器快速入门

public class MyInterceptor1 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Controller方法执行之前...");return true; // 放行}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Controller方法执行之后...");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("渲染视图结束,整个流程完毕...");}
}

在spring-mvc.xml中, 配置Interceptor

<!--配置拦截器-->
<mvc:interceptors><mvc:interceptor><!--配置对哪些资源进行拦截操作--><mvc:mapping path="/**"/><bean class="com.mem.interceptor.MyInterceptor1"></bean></mvc:interceptor>
</mvc:interceptors>

controller层,业务代码

// 测试拦截器
@RequestMapping("/interceptor_req")
public String interceptor_req(){System.out.println("interceptor_req ...");return "/show.jsp";
}
Controller方法执行之前...
interceptor_req ...
Controller方法执行之后...
渲染视图结束,整个流程完毕...

拦截器执行顺序
在这里插入图片描述
在这里插入图片描述
Spring MVC 的全注解开发
跟之前全注解开发思路一致, xml配置文件使用核心配置类替代,xml中的标签使用对应的注解替代

<!--1. 组件扫描 -->
<!--组件扫描web层-->
<context:component-scan base-package="com.mem.controller"/><!--2. 非自定义的Bean -->
<!--配置文件上传解析器,注意:id的名字是固定写法-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="defaultEncoding" value="UTF-8"/><!--文件的编码格式 默认是ISO8859-1--><property name="maxUploadSizePerFile" value="1048576"/><!--上传的每个文件限制的大小 单位字节--><property name="maxUploadSize" value="3145728"/><!--上传文件的总大小--><property name="maxInMemorySize" value="1048576"/><!--上传文件的缓存大小-->
</bean><!--3.Bean的配置 -->
<!--访问静态资源的方式3:底层注册一个DefaultServletHttpRequestHandler 来处理静态资源-->
<mvc:default-servlet-handler/>
<!--mvc的注解驱动-->
<mvc:annotation-driven/>
<!--配置拦截器-->
<mvc:interceptors><mvc:interceptor><!--配置对哪些资源进行拦截操作--><mvc:mapping path="/**"/><bean class="com.mem.interceptor.MyInterceptor1"></bean></mvc:interceptor>
</mvc:interceptors>

第一步,第二步,可以利用之前所学的spring的配置类来搞定
组件扫描,可以通过@ComponentScan注解完成;
文件上传解析器multipartResolver可以通过非自定义Bean的注解配置方式,即@Bean注解完成

@Configuration
// <context:component-scan base-package="com.mem.controller"/>
@ComponentScan("com.mem.controller")
public class SpringMVCConfig {/*** <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">*     <property name="defaultEncoding" value="UTF-8"/><!--文件的编码格式 默认是ISO8859-1-->*     <property name="maxUploadSizePerFile" value="1048576"/><!--上传的每个文件限制的大小 单位字节-->*     <property name="maxUploadSize" value="3145728"/><!--上传文件的总大小-->*     <property name="maxInMemorySize" value="1048576"/><!--上传文件的缓存大小-->* </bean>*/@Beanpublic CommonsMultipartResolver multipartResolver(){CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();multipartResolver.setDefaultEncoding("UTF-8");multipartResolver.setMaxUploadSizePerFile(1048576);multipartResolver.setMaxUploadSize(3145728);multipartResolver.setMaxInMemorySize(1048576);return multipartResolver;}
}

第三步,非Bean的配置(mvc:default-servlet-handler/、mvc:annotation-driven/、mvc:interceptors) 该怎么办呢?
SpringMVC 提供了一个注解@EnableWebMvc,我们看一下源码,内部通过@Import导入了DelegatingWebMvcConfiguration类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();// 从容器中注入 WebMvcConfigurer 类型的Bean@Autowired(required = false)public void setConfigurers(List<WebMvcConfigurer> configurers) {if (!CollectionUtils.isEmpty(configurers)) {this.configurers.addWebMvcConfigurers(configurers);}}
}

首先先看下父类WebMvcConfigurationSupport:

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {// 将 RequestMappingHandlerMapping 放入容器@Beanpublic RequestMappingHandlerMapping requestMappingHandlerMapping(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, @Qualifier("mvcConversionService") FormattingConversionService conversionService, @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {RequestMappingHandlerMapping mapping = this.createRequestMappingHandlerMapping();// 中间省略return mapping;}// 将 RequestMappingHandlerAdapter 放入容器@Beanpublic RequestMappingHandlerAdapter requestMappingHandlerAdapter(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager, @Qualifier("mvcConversionService") FormattingConversionService conversionService, @Qualifier("mvcValidator") Validator validator) {RequestMappingHandlerAdapter adapter = this.createRequestMappingHandlerAdapter();return adapter;}
}

这一步的效果等同于mvc:annotation-driven/注解驱动
实现:
创建MyWebMvcConfigurer实现WebMvcConfigurer接口,实现addInterceptors 和 configureDefaultServletHandling方法

@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {// 替代 <mvc:interceptors>@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 创建拦截器对象,进行注册// Interceptor 的执行顺序也取决于添加顺序registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");}// 替代 <mvc:default-servlet-handler/>@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {// 开启DefaultServlet,就可以处理静态资源了configurer.enable();}
}

最后,在SpringMVC核心配置类上添加@EnableWebMvc注解

@Configuration
// <context:component-scan base-package="com.mem.controller"/>
@ComponentScan("com.mem.controller")
@EnableWebMvc
public class SpringMVCConfig {/*** <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">*     <property name="defaultEncoding" value="UTF-8"/><!--文件的编码格式 默认是ISO8859-1-->*     <property name="maxUploadSizePerFile" value="1048576"/><!--上传的每个文件限制的大小 单位字节-->*     <property name="maxUploadSize" value="3145728"/><!--上传文件的总大小-->*     <property name="maxInMemorySize" value="1048576"/><!--上传文件的缓存大小-->* </bean>*/@Beanpublic CommonsMultipartResolver multipartResolver(){CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();multipartResolver.setDefaultEncoding("UTF-8");multipartResolver.setMaxUploadSizePerFile(1048576);multipartResolver.setMaxUploadSize(3145728);multipartResolver.setMaxInMemorySize(1048576);return multipartResolver;}
}

DispatcherServlet 加载核心配置类
现在是使用SpringMVCConfig核心配置类替代了spring-mvc.xml,怎么加载呢?

<!-- 创建Servlet WebApplicationContext容器的配置 -->
<servlet><servlet-name>DispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--加载Spring MVC的核心配置文件--><!--        <init-param>--><!--            <param-name>contextConfigLocation</param-name>--><!--            <param-value>classpath:spring-mvc.xml</param-value>--><!--        </init-param>--><!--加载Spring MVC的核心配置类--><init-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></init-param><init-param><param-name>contextConfigLocation</param-name><param-value>com.mem.config.SpringMVCConfig</param-value></init-param><!--可以设置该servlet在加载时的优先级以及是否在容器中加载该servletTomcat依次执行的是DispatcherServlet中的静态代码块,构造方法,init()方法--><load-on-startup>2</load-on-startup>
</servlet>

方法2: 参照Spring的 ContextLoaderListener加载核心配置类的做法,定义了一个AnnotationConfigWebApplicationContext,通过 代码注册核心配置类
在这里插入图片描述
Spring MVC 的组件原理刨析
前端控制初始化
在这里插入图片描述
在这里插入图片描述
结论:SpringMVC 的ApplicationContext容器创建时机,Servlet 规范的 init(ServletConfig config) 方法经过子类重写 ,最终会调用 FrameworkServlet 抽象类的initWebApplicationContext() 方法,该方法中最终获得 一个根 Spring容器(Spring产生的),一个子Spring容器(SpringMVC产生的)。
Spring MVC 的异常处理机制
在这里插入图片描述
在这里插入图片描述
SpringMVC的异常处理方式
在这里插入图片描述
初始化:
新建一个异常测试Controller:

@RestController
public class ExceptionController {/*** 模拟运行时异常* @return*/@RequestMapping("/exception1")public String exceptionMethod1(){int i = 1/0;return "Hello Exception";}/*** 模拟编译异常* @return*/@RequestMapping("/exception2")public String exceptionMethod2() throws FileNotFoundException {FileInputStream inputStream = new FileInputStream("C:/xx/xx/xx.xx");return "Hello Exception";}
}

改善1:加上简单异常处理器(SimpleMappingExceptionResolver),对不同的异常进行不同的跳转友好页面,操作如下
在配置类上加一个SimpleMappingExceptionResolver类型的Bean

@Configuration
@ComponentScan("com.mem.controller")
@EnableWebMvc
public class SpringMVCConfig {// 配置简单的异常处理器类@Beanpublic SimpleMappingExceptionResolver simpleMappingExceptionResolver(){SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();// 不管是什么异常,统一的响应一个友好页面//        simpleMappingExceptionResolver.setDefaultErrorView("/error1.html");// 区分异常类型,根据不同的异常类型,跳转不同的视图Properties properties = new Properties();// 键值对,key:异常的全限定名,value:跳转的视图名properties.setProperty("java.lang.RuntimeException","/error1.html");properties.setProperty("java.io.FileNotFoundException","/error2.html");simpleMappingExceptionResolver.setExceptionMappings(properties);return simpleMappingExceptionResolver;}
}

添加错误页面
在这里插入图片描述

改善2:自定义异常处理器,实现HandlerExceptionResolver接口,操作如下:
添加自定义异常处理器类

@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {/**** @param request 请求* @param response 响应* @param handler Controller层的方法的封装* @param e 异常,可以用于判断* @return*/@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {System.out.println("request:"+request);System.out.println("response:"+response);System.out.println("handler:"+handler);System.out.println("e:"+e);// 1. 可以简单的响应一个友好的提示页面ModelAndView modelAndView = new ModelAndView();if(e instanceof RuntimeException ){modelAndView.setViewName("/error1.html");}else{modelAndView.setViewName("/error2.html");}return modelAndView;}
}

自定义异常处理器还可以以json形式返回:
修改MyHandlerExceptionResolver的resolveException方法:

@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {/**** @param request 请求* @param response 响应* @param handler Controller层的方法的封装* @param e 异常,可以用于判断* @return*/@Overridepublic ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {System.out.println("request:"+request);System.out.println("response:"+response);System.out.println("handler:"+handler);System.out.println("e:"+e);// 1. 可以简单的响应一个友好的提示页面//        ModelAndView modelAndView = new ModelAndView();//        if(e instanceof RuntimeException ){//            modelAndView.setViewName("/error1.html");//        }else{//            modelAndView.setViewName("/error2.html");//        }// 2. 前后端分离开发,响应json格式的字符串 {"code": 200,"message":"","data":{"username":"haohao","age":18}}String resultJson = "{\"code\": 500,\"message\":\"异常\",\"data\":{\"username\":\"haohao\",\"age\":18}}";try {response.getWriter().write(resultJson);} catch (IOException ex) {ex.printStackTrace();}return null;}
}

改善3:使用注解的方式,更加灵活(常用)
新建类(ExceptionByAnno):

@ControllerAdvice
public class ExceptionByAnno {@ExceptionHandler(RuntimeException.class)public ModelAndView RuntimeExceptionResolverMethod(Exception exception){System.out.println("exception:"+exception); // exception:java.lang.ArithmeticException: / by zeroModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("/error1.html");return modelAndView;}@ExceptionHandler(IOException.class)@ResponseBodypublic Result IOExceptionResolverMethod(Exception exception){System.out.println("exception:"+exception); // exception:java.io.FileNotFoundException: C:\xx\xx\xx.xx (系统找不到指定的路径。)Result result = new Result(500,"","");return result;}@ExceptionHandler(FileNotFoundException.class)public ModelAndView FileNotFoundExceptionResolverMethod(Exception exception){System.out.println("exception:"+exception); // exception:java.io.FileNotFoundException: C:\xx\xx\xx.xx (系统找不到指定的路径。)ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("/error2.html");return modelAndView;}
}

SpringMVC 常用的异常解析器
在这里插入图片描述
HandlerExceptionResolverComposite 是一个组合体,内部包含了ExceptionHandlerExceptionResolver + DefaultHandlerExceptionResolver + ResponseStatusExceptionResolver三个解析器
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/60356.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python基础大杂烩

命令提示符程序&#xff0c;输入python&#xff0c;运行python程序 代码通过解释器程序翻译给计算机去执行 命令提示符输入的python本质上就是调用D:/dev/python/python3.12.5/python.exe这个解释器程序 有python程序将输入的代码翻译成二进制的0和1&#xff0c;去向计算机去运…

MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下MathGPT的原理介绍&#xff0c;在中小学数学教学的应用场景&#xff0c;以及代码样例实现。MathGPT的核心架构是一个精心设计的多层次系统&#xff0c;旨在有效处理复杂的数学问题。其主要组成部分包括 数学知识图谱…

算法演练----24点游戏

给定4个整数&#xff0c;数字范围在1~13之间任意使用-*/&#xff08;&#xff09;&#xff0c;构造出一个表达式&#xff0c;使得最终结果为24&#xff0c; 方法一 算法分析&#xff1a;加括号和取出重复表达式 # 导入精确除法模块&#xff0c;使得在Python2中除法运算的行为更…

关于指针p有关的3个值

1&#xff0c;他的类型是int*; 2,*p是解用&#xff0c;指向的是对象 3&#xff0c;&p指向的是p的地址&#xff0c;是指针的地址

《JavaEE进阶》----20.<基于Spring图书管理系统①(登录+添加图书)>

PS&#xff1a;关于接口定义 接口定义&#xff0c;通常由服务器提供方来定义。 1.路径&#xff1a;自己定义 2.参数&#xff1a;根据需求考虑&#xff0c;我们这个接口功能完成需要哪些信息。 3.返回结果&#xff1a;考虑我们能为对方提供什么。站在对方角度考虑。 我们使用到的…

Linux服务管理-iSCSI

iSCSI 基础知识 iSCSI&#xff08;Internet Small Computer System Interface&#xff09;协议是一种基于IP网络的存储协议&#xff0c;它允许主机&#xff08;计算机或服务器&#xff09;通过TCP/IP网络访问远程存储设备。该协议具有以下主要特点&#xff1a; 灵活性&#xf…

快速掌握——python类 封装[私有属性方法]、继承【python进阶】(内附代码)

1.类的定义 与 实例化对象 在python中使用class关键字创建一个类。 举例子 class Stu(object):id 1001name 张三def __init__(self):passdef fun1(self):pass# 实例化对象 s1 Stu() s2 Stu() print(s1.name) print(s2.name) 第一个方法 __init__是一种特殊的方法&#x…

HarmonyOS 如何实现传输中的数据加密

文章目录 摘要引言数据传输加密概述选择加密算法和传输协议加密实现方案与 Demo 代码配置 HTTPS/TLSAES 加密的实现代码详解RSA加密的实现代码详解 QA环节总结参考资料 摘要 本文将介绍在 HarmonyOS 应用中如何实现数据传输的加密策略。我们将讨论常见的加密算法&#xff08;如…

Bilibili-超能用户榜入口优化-技术方案反思与总结

目录 客户端实现&#xff1a; 高能用户入口实现逻辑&#xff1a; 接口服务信息&#xff08;服务端下发&#xff09;&#xff1a; 执行方案&#xff1a; (1)数据类新增服务端下发字段 ​编辑 (2) UI添加 寻找思路&#xff1a; &#xff08;3&#xff09;超能用户icon显示…

vue实现图片无限滚动播放

本人vue新手菜鸡&#xff0c;文章为自己在项目中遇到问题的记录&#xff0c;如有不足还请大佬指正 文章目录 实现效果代码展示总结 因为刚接触vue&#xff0c;本想着看看能不能用一些element的组件实现图片的轮播效果&#xff0c;尝试使用过element-UI里的走马灯Carouse&#x…

MySQL缓存使用率超过80%的解决方法

MySQL缓存使用率超过80%的解决方法 一、识别缓存使用率过高的问题1.1 使用SHOW GLOBAL STATUS命令监控1.2 监控其他相关指标二、分析缓存使用率过高的原因2.1 数据量增长2.2 查询模式变化2.3 配置不当三、解决缓存使用率过高的方法3.1 调整Buffer Pool大小3.1.1 计算合理的Buff…

LeetCode【0036】有效的数独

本文目录 1 中文题目2 求解方法&#xff1a;python内置函数set2.1 方法思路2.2 Python代码2.3 复杂度分析 3 题目总结 1 中文题目 请根据以下规则判断一个 9 x 9 的数独是否有效。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线…

UNIAPP发布小程序调用讯飞在线语音合成+实时播报

语音合成能够将文字转化为自然流畅的人声&#xff0c;提供100发音人供您选择&#xff0c;支持多语种、多方言和中英混合&#xff0c;可灵活配置音频参数。广泛应用于新闻阅读、出行导航、智能硬件和通知播报等场景。 在当下大模型火爆的今日&#xff0c;语音交互页离不开语音合…

成都睿明智科技有限公司解锁抖音电商新玩法

在这个短视频风起云涌的时代&#xff0c;抖音电商以其独特的魅力迅速崛起&#xff0c;成为众多商家争夺的流量高地。而在这片充满机遇与挑战的蓝海中&#xff0c;成都睿明智科技有限公司犹如一颗璀璨的新星&#xff0c;以其专业的抖音电商服务&#xff0c;助力无数品牌实现从零…

Llama旋转位置编码代码实现及详解

旋转位置编码RoPE 在旋转位置编码与Transformer和BERT之间的区别中介绍了旋转位置编码&#xff08;RoPE&#xff09;的特点和优势&#xff0c;这种输入长度动态可变的优势使得在Llama编码时&#xff0c;不需要掩码将多余的嵌入掩住。为了详细了解RoPE是如何实现的&#xff0c;…

遇到“msvcr120.dll丢失”要怎么解决?详解msvcr120.dll的解决方法

遇到“msvcr120.dll丢失”错误通常表明你的系统缺少一个关键的DLL文件&#xff0c;这是Microsoft Visual C 2013的一部分。这个问题可能导致某些程序无法运行&#xff0c;影响电脑性能。不过&#xff0c;解决这一问题并不复杂。接下来&#xff0c;本文将向你展示几种简单的修复…

【机器学习】平均绝对误差(MAE:Mean Absolute Error)

平均绝对误差 (Mean Absolute Error, MAE) 是一种衡量预测值与实际值之间平均差异的统计指标。它在机器学习、统计学等领域中广泛应用&#xff0c;用于评估模型的预测精度。与均方误差 (MSE) 或均方误差根 (RMSE) 不同&#xff0c;MAE 使用误差的绝对值&#xff0c;因此它在处理…

项目功能--运营数据统计

一、需求分析 通过运营数据统计可以展示出体检机构的运营情况&#xff0c;包括会员数据、预约到诊数据、热门套餐等信息。我们要通过一个表格的形式来展示这些运营数据。如下图&#xff1a; 二、代码实现 实现步骤&#xff1a; 步骤一&#xff1a;定义数据模型&#xff0c;通过…

网络安全技术在能源领域的应用

摘要 随着信息技术的飞速发展&#xff0c;能源领域逐渐实现了数字化、网络化和智能化。然而&#xff0c;这也使得能源系统面临着前所未有的网络安全威胁。本文从技术的角度出发&#xff0c;探讨了网络安全技术在能源领域的应用&#xff0c;分析了能源现状面临的网络安全威胁&a…

wangeditor富文本编辑器以文本的形式展示公式

最终展示的效果 1.首先将要传给后端的富文本值进行转化 //假设workContent是富文本写入的值this.workContent this.escapeHTML(this.workContent)//通过escapeHTML方法转化传给后端 methods:{escapeHTML(str) {return str.replace(/&/g, &amp;) // 将 & 替换为…