目录
5.2 创建SpringConfig配置类,代替spring的配置文件
5.3 创建WebConfig配置类,代替SpringMVC的配置文件
- <form th:action="@{/test/requestBody}" method="post">
- 用户名:<input type="text" name="username"><br>
- 密码:<input type="password" name="password"><br>
- <input type="submit" value="登录">
- form>
- @RequestMapping(value = "/test/requestBody",method = RequestMethod.POST)
- public String testRequesttBody(@RequestBody String requestBody){
- System.out.println("requestBody:"+requestBody);
- return "success";
- }
一个注解就能获得请求体的信息非常的方便。不过这里使用中文会发生乱码,暂时不知道啥情况
在使用了axios发送ajax请求之后,浏览器发送到服务器的请求参数有两种格式:
(1)name=value&name=value...,此时的请求参数可以通过request.getParameter()获取,对应 SpringMVC中,可以直接通过控制器方法的形参获取此类请求参数
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-databindartifactId>
- <version>2.12.1version>
- dependency>
第二步:SpringMVC的配置文件中设置开启mvc的注解驱动
<mvc:annotation-driven/>
第三步:在控制器方法的形参位置,设置json格式的请求参数要转换成的java类型(实体类或map)的参数,并使用@RequestBody注解标识
- html>
- <html lang="en" xmlns:th="http://www.thymeleaf.org">
- <head>
- <meta charset="UTF-8">
- <title>首页title>
- head>
- <body>
- <div id="app">
- <h1>index.htmlh1>
- <input type="button" value="使用@RequestBody注解处理json格式的请求参数" @click="testRequestBody()"><br>
- <a th:href="@{/test/ResponseBody}">测试@ResponseBody注解响应浏览器数据a><br>
- <input type="button" value="使用@ResponseBody注解响应json格式的数据" @click="testResponseBody()"><br>
- div>
-
- <script type="text/javascript" th:src="@{/js/vue.js}">script>
- <script type="text/javascript" th:src="@{/js/axios.min.js}">script>
- <script type="text/javascript">
-
- /**
- * axios({
- url:"",//请求路径
- method:"",//请求方式
- //以name=value&name=value的方式发送的请求参数
- //不管使用的请求方式是get或post,请求参数都会被拼接到请求地址后
- //此种方式的请求参数可以通过request.getParameter()获取
- params:{},
- //以json格式发送的请求参数
- //请求参数会被保存到请求报文的请求体传输到服务器
- //此种方式的请求参数不可以通过request.getParameter()获取
- data:{}
- }).then(response=>{
- console.log(response.data);
- });
- */
-
- var vue = new Vue({
- el:"#app",
- methods:{
- testRequestBody(){
- axios.post(
- "/springmvc/test/RequestBody/json",
- {username:"admin",password:"123456",age:23,gender:"男"}
- ).then(response=>{
- console.log(response.data);
- });
- },
- testResponseBody(){
- axios.post("/springmvc/test/ResponseBody/json").then(response=>{
- console.log(response.data);
- });
- }
- }
- });
- script>
- body>
- html>
需要注意的是要想访问我们复制过来的js等静态文件需要在springmvc配置文件假如配置:
- <mvc:default-servlet-handler />
-
- <mvc:annotation-driven/>
因为:配置默认的servlet处理静态资源,当前工程的web.xml配置的前端控制器DispatcherServlet的url-pattern是/。tomcat的web.xml配置的DefaultServlet的url-pattern也是/ 。此时,浏览器发送的请求会优先被DispatcherServlet进行处理,但是DispatcherServlet无法处理静态资源。若配置了
- @RequestMapping(value = "/test/RequestBody/json")
- public void testRequestBody(@RequestBody String requestBody, HttpServletResponse response) throws IOException {
- System.out.println(requestBody);
- response.getWriter().write("hello,ajax");
- }

这是使用一个字符串类型参数接收请求体,我们可以使用类来接收。
- public void testRequestBody(@RequestBody User user, HttpServletResponse response) throws IOException {
- System.out.println(user);
- response.getWriter().write("hello,RequestBody");
- }

我们之前控制器方法返回值是会跳转到一个页面如下:
<a th:href="@{/test/ResponseBody}">测试@ResponseBody注解响应浏览器数据a><br>
- @RequestMapping("/test/ResponseBody")
- public String testResponseBody(){
- //此时会跳转到逻辑视图success所对应的页面
- return "success";
- }



- public User testResponseBodyJson(){
- User user = new User(1001, "admin", "123456", 20, "男");
- return user;
- }

我们可以响应实体类,也可以响应list集合和map集合:
- public List
testResponseBodyJson(){ - User user1 = new User(1001, "admin1", "123456", 20, "男");
- User user2 = new User(1002, "admin2", "123456", 20, "男");
- User user3 = new User(1003, "admin3", "123456", 20, "男");
- List
list = Arrays.asList(user1, user2, user3); - return list;
- }

- public Map
testResponseBodyJson(){ - User user1 = new User(1001, "admin1", "123456", 20, "男");
- User user2 = new User(1002, "admin2", "123456", 20, "男");
- User user3 = new User(1003, "admin3", "123456", 20, "男");
- Map
map = new HashMap<>(); - map.put("1001", user1);
- map.put("1002", user2);
- map.put("1003", user3);
- return map;
- }


<a th:href="@{/test/down}">下载图片a>
- @RequestMapping("/test/down")
- public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws
- IOException {
- //获取ServletContext对象
- ServletContext servletContext = session.getServletContext();
- //获取服务器中文件的真实路径
- String realPath = servletContext.getRealPath("img");
- realPath = realPath + File.separator + "1.jpg";
- //创建输入流
- InputStream is = new FileInputStream(realPath);
- //创建字节数组
- byte[] bytes = new byte[is.available()];
- //将流读到字节数组中
- is.read(bytes);
- //创建HttpHeaders对象设置响应头信息
- MultiValueMap
headers = new HttpHeaders(); - //设置要下载方式以及下载文件的名字
- headers.add("Content-Disposition", "attachment;filename=1.jpg");
- //设置响应状态码
- HttpStatus statusCode = HttpStatus.OK;
- //创建ResponseEntity对象
- ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
- //关闭输入流
- is.close();
- return responseEntity;
- }
以上代码可以当做一个模板,需要下载别的文件时,我们只要改一下路径即可。
- <dependency>
- <groupId>commons-fileuploadgroupId>
- <artifactId>commons-fileuploadartifactId>
- <version>1.3.1version>
- dependency>
第二步:在SpringMVC的配置文件中添加配置:
这里一定要配置id名称而且必须是这个名称
-
- <bean id="multipartResolver"
- class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
- bean>
第三步:控制器方法和前端页面
- <form th:action="@{/test/up}" method="post" enctype="multipart/form-data">
- 头像:<input type="file" name="photo"><br>
- <input type="submit" value="上传">
- form>
- @RequestMapping("/test/up")
- public String testUp(MultipartFile photo, HttpSession session) throws IOException {
- //获取上传的文件的文件名
- String fileName = photo.getOriginalFilename();
- //获取上传的文件的后缀名
- String hzName = fileName.substring(fileName.lastIndexOf("."));
- //获取uuid
- String uuid = UUID.randomUUID().toString();
- //拼接一个新的文件名
- fileName = uuid + hzName;
- //获取ServletContext对象
- ServletContext servletContext = session.getServletContext();
- //获取当前工程下photo目录的真实路径
- String photoPath = servletContext.getRealPath("photo");
- //创建photoPath所对应的File对象
- File file = new File(photoPath);
- //判断file所对应目录是否存在
- if(!file.exists()){
- file.mkdir();
- }
- String finalPath = photoPath + File.separator + fileName;
- //上传文件
- photo.transferTo(new File(finalPath));
- return "success";
- }
注意我们用以下代码拼接一个新的文件名,因为假如我们上传的文件名相同的文件,它会覆盖前面的文件,我们可以手动将文件名修改:

我们创建一个类实现这三个方法
- package com.itzw.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- @Controller
- public class FirstInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("FirstInterceptor-->preHandle");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("FirstInterceptor-->postHandle");
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("FirstInterceptor-->afterCompletion");
- }
- }
- <mvc:interceptors>
- <bean class="com.itzw.interceptor.FirstInterceptor"/>
- mvc:interceptors>

第二种方式:在外面配置bean然后再引入
- <bean id="interceptor" class="com.itzw.interceptor.FirstInterceptor"/>
- <mvc:interceptors>
-
- <ref bean="interceptor"/>
- mvc:interceptors>
第三种方式:不在外面配置bean,直接使用注解,控制加扫描的方式
- <mvc:interceptors>
-
- <ref bean="firstInterceptor"/>
- mvc:interceptors>

值得注意的是:bean和ref标签所配置的拦截器默认对DIspatcherServlet处理的所有的请求进行拦截,即使是不存在路径也会拦截,那我要是不想拦截某个路径呢?

进行如上配置,如果配置的是“/*”则表示拦截所有一层目录比如“/x”,但是“/x/y”就不会拦截了。
编写异常处理器:

其中key的值表示处理器方法执行过程中出现的异常,而它的值表示出现异常时跳转到指定视图
我们还可以通过配置输出异常信息:
<property name="exceptionAttribute" value="ex">property>
"${ex}">

我们需要单独写一个类来代替配置:
- package com.itzw.controller;
-
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.bind.annotation.ExceptionHandler;
-
- @ControllerAdvice
- public class ExceptionTest {
-
- @ExceptionHandler(ArithmeticException.class)
- public String test(Model model, Exception ex){
- model.addAttribute("ex",ex);
- return "error";
- }
- }
@ControllerAdvice将当前类标识为异常处理器的组件;@ExceptionHandler用于设置所表示方法处理的异常;ex表示当前请求处理中出现的异常对象
- package com.itzw.config;
-
- import org.springframework.web.filter.CharacterEncodingFilter;
- import org.springframework.web.filter.HiddenHttpMethodFilter;
- import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
-
- import javax.servlet.Filter;
-
- public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
-
- /**
- * 指定Spring的配置类
- * @return
- */
- @Override
- protected Class>[] getRootConfigClasses() {
- return new Class[]{SpringConfig.class};
- }
-
- /**
- * 指定SpringMVC的配置类
- * @return
- */
- @Override
- protected Class>[] getServletConfigClasses() {
- return new Class[]{WebConfig.class};
- }
-
- /**
- * 指定DispatcherServlet的映射规则,即url-pattern
- * @return
- */
- @Override
- protected String[] getServletMappings() {
- return new String[]{"/"};
- }
-
- /**
- * 设置当前的过滤器
- * @return
- */
- @Override
- protected Filter[] getServletFilters() {
- //创建编码过滤器
- CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
- characterEncodingFilter.setEncoding("UTF-8");
- characterEncodingFilter.setForceEncoding(true);
- //创建处理请求方式的过滤器
- HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
- return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
- }
- }
- package com.itzw.config;
-
- import org.springframework.context.annotation.Configuration;
-
- @Configuration
- public class SpringConfig {
- }
这个以后需要我们再详细配置,之前我们学spring的时候就使用过这个。@Configuration的作用是将类标识为配置类
SpringMVC配置文件配置的内容包括:扫描组件、视图解析器、默认的servlet、mvc的注解驱动 、视图控制器、文件上传解析器、拦截器、异常解析器
我们一个个配置:
首先我们实现接口WebMvcConfigurer
注解@EnableWebMvc用来开启mvc注解驱动,对应配置文件的
注解@ComponentScan用来扫描组件,对应配置文件的
- package com.itzw.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
- import org.springframework.web.servlet.config.annotation.EnableWebMvc;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
- @Configuration
- //扫描组件
- @ComponentScan("com.itzw.controller")
- //开启mvc注解驱动
- @EnableWebMvc
- public class WebConfig implements WebMvcConfigurer {
-
- }
我们再重写这个接口的方法实现其它功能:
配置默认的servlet处理静态资源(css、js等资源),固定配置如下:
- @Override
- public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- configurer.enable();
- }
对应配置文件的:
配置视图解析器:
- @Override
- public void addViewControllers(ViewControllerRegistry registry) {
- registry.addViewController("/").setViewName("index");
- }
对应配置文件的:
配置文件上传解析器:固定写法
- @Bean
- public CommonsMultipartResolver multipartResolver(){
- return new CommonsMultipartResolver();
- }
这个方法需要我们自己写,其中@Bean注解可以将表示的方法的返回值作为bean进行管理,bean的id为方法的方法名。对应配置文件中的:
-
- <bean id="multipartResolver"
- class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
- bean>
配置拦截器:
配置拦截器首先我们要有个拦截器,还记得拦截器怎么创建吗?
- package com.itzw.interceptor;
-
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- public class FirstInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- }
- }
然后配置拦截器:
- public void addInterceptors(InterceptorRegistry registry) {
- FirstInterceptor firstInterceptor = new FirstInterceptor();
- //拦截所有路径
- registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
- }
对应的配置文件为:
- <mvc:interceptors>
-
- <ref bean="firstInterceptor"/>
- <mvc:interceptor>
- <mvc:mapping path="/**"/>
- <mvc:exclude-mapping path="/a/b"/>
- <ref bean="firstInterceptor"/>
- mvc:interceptor>
- mvc:interceptors>
配置异常解析器:
- @Override
- public void configureHandlerExceptionResolvers(List
resolvers) { - SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
- Properties prop = new Properties();
- prop.setProperty("java.lang.ArithmeticException","error");
- exceptionResolver.setExceptionMappings(prop);
- exceptionResolver.setExceptionAttribute("ex");
- resolvers.add(exceptionResolver);
- }
对应配置文件:
- <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
- <property name="exceptionMappings">
- <props>
- <prop key="java.lang.ArithmeticException">errorprop>
- props>
- property>
- <property name="exceptionAttribute" value="ex">property>
- bean>
配置视图解析器:
- //配置生成模板解析器
- @Bean
- public ITemplateResolver templateResolver() {
- WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
- // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
- ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(
- webApplicationContext.getServletContext());
- templateResolver.setPrefix("/WEB-INF/templates/");
- templateResolver.setSuffix(".html");
- templateResolver.setCharacterEncoding("UTF-8");
- templateResolver.setTemplateMode(TemplateMode.HTML);
- return templateResolver;
- }
-
- //生成模板引擎并为模板引擎注入模板解析器
- @Bean
- public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
- SpringTemplateEngine templateEngine = new SpringTemplateEngine();
- templateEngine.setTemplateResolver(templateResolver);
- return templateEngine;
- }
-
- //生成视图解析器并未解析器注入模板引擎
- @Bean
- public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
- ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
- viewResolver.setCharacterEncoding("UTF-8");
- viewResolver.setTemplateEngine(templateEngine);
- return viewResolver;
- }
对应的配置文件是:
-
- <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
- <property name="order" value="1"/>
- <property name="characterEncoding" value="UTF-8"/>
- <property name="templateEngine">
- <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
- <property name="templateResolver">
- <bean
- class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
-
- <property name="prefix" value="/WEB-INF/templates/"/>
-
- <property name="suffix" value=".html"/>
- <property name="templateMode" value="HTML5"/>
- <property name="characterEncoding" value="UTF-8" />
- bean>
- property>
- bean>
- property>
- bean>
这样就配置完成了,之前我们遇到的需要配置的东西都用注解的方式实现了。
下面我们就可以将SSM三个框架整合在一起了。