springmvc(3)https://developer.aliyun.com/article/1530455
9.4、@ResponseBody响应浏览器json数据
服务器处理ajax请求之后,大多数情况都需要向浏览器响应一个java对象,此时必须将java对象转换为
json字符串才可以响应到浏览器,之前我们使用操作json数据的jar包gson或jackson将java对象转换为
json字符串。在SpringMVC中,我们可以直接使用@ResponseBody注解实现此功能
@ResponseBody响应浏览器json数据的条件:
1、导入jackson的依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.1</version> </dependency>
2、SpringMVC的配置文件中设置开启mvc的注解驱动
<!--开启mvc的注解驱动--> <mvc:annotation-driven />
3、使用@ResponseBody注解标识控制器方法,在方法中,将需要转换为json字符串并响应到浏览器
的java对象作为控制器方法的返回值,此时SpringMVC就可以将此对象直接转换为json字符串并响应到浏览器
<input type="button" value="测试@ResponseBody响应浏览器json格式的数据"@click="testResponseBody()"><br> <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"> var vue = new Vue({ el:"#app", methods:{ testResponseBody(){ axios.post("/SpringMVC/test/ResponseBody/json").then(response=>{ console.log(response.data); }); } } }); </script>
//响应浏览器list集合 @RequestMapping("/test/ResponseBody/json") @ResponseBody public List<User> testResponseBody(){ User user1 = new User(1001,"admin1","123456",23,"男"); User user2 = new User(1002,"admin2","123456",23,"男"); User user3 = new User(1003,"admin3","123456",23,"男"); List<User> list = Arrays.asList(user1, user2, user3); return list; } //响应浏览器map集合 @RequestMapping("/test/ResponseBody/json") @ResponseBody public Map<String, Object> testResponseBody(){ User user1 = new User(1001,"admin1","123456",23,"男"); User user2 = new User(1002,"admin2","123456",23,"男"); User user3 = new User(1003,"admin3","123456",23,"男"); Map<String, Object> map = new HashMap<>(); map.put("1001", user1); map.put("1002", user2); map.put("1003", user3); return map; } //响应浏览器实体类对象 @RequestMapping("/test/ResponseBody/json") @ResponseBody public User testResponseBody(){ return user; }
常用的Java对象转换为json的结果:
实体类–>json对象
map–>json对象
list–>json数组(方括号包裹的)
9.5、@RestController注解
@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了
@Controller注解,并且为其中的每个方法添加了@ResponseBody注解
10、文件上传和下载
10.1、文件下载
ResponseEntity:可以作为控制器方法的返回值,表示响应到浏览器的完整的响感报文
ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文
使用ResponseEntity实现下载文件的功能
真实地址的样子
文件分隔符的表示File.separator
is.available()
获取流的字节数
@RequestMapping("/testDown") public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException { //通过session获取ServletContext对象 ServletContext servletContext = session.getServletContext(); //获取服务器中文件的真实路径 String realPath = servletContext.getRealPath("/static/img/1.jpg"); //创建输入流 InputStream is = new FileInputStream(realPath); //创建字节数组 byte[] bytes = new byte[is.available()]; //将流读到字节数组中 is.read(bytes); //创建HttpHeaders对象设置响应头信息 MultiValueMap<String, String> headers = new HttpHeaders(); //Content-Disposition设置要下载方式 //attachment以附件的方式进行下载 //设置下载文件的名字 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; }
10.2、文件上传
文件上传要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data"
SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息
上传步骤:
①添加依赖:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
②在SpringMVC的配置文件中添加配置:
<!--配置文件上传解析器 id必须配置为固定值,因为springmvc是靠id来获取这个解析器的--> <!-- 单例的情况下,他的实例化过程是在获取ioc容器的时候执行--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> </bean>
③控制器方法:
@RequestMapping("/testUp") public String testUp(MultipartFile photo, HttpSession session) throws IOException { //获取上传的文件的文件名 String fileName = photo.getOriginalFilename(); //处理文件重名问题 String hzName = fileName.substring(fileName.lastIndexOf(".")); fileName = UUID.randomUUID().toString() + hzName; //获取服务器中photo目录的路径 ServletContext servletContext = session.getServletContext(); String photoPath = servletContext.getRealPath("photo"); File file = new File(photoPath); if(!file.exists()){ file.mkdir(); } String finalPath = photoPath + File.separator + fileName; //实现上传功能 photo.transferTo(new File(finalPath)); return "success"; }
11、拦截器
过滤器是在浏览器和目标资源之间过滤
11.1、拦截器的配置
SpringMVC中的拦截器用于拦截控制器方法的执行
SpringMVC中的拦截器需要实现HandlerInterceptor
SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:
<mvc:interceptors> <bean class="com.atguigu.interceptor.FirstInterceptor"></bean> </mvc:interceptors>
<bean class="com.atguigu.interceptor.FirstInterceptor"></bean> <!-- 以上两种配置方式都是对DispatcherServlet所处理的所有的请求进行拦截 --> <mvc:interceptors> <mvc:interceptor> <!-- /*是处理一层目录的请求 /**是所有请求--> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/testRequestEntity"/> <ref bean="firstInterceptor"></ref> </mvc:interceptor> </mvc:interceptors> <!-- 以上配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求, 通过mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求 -->
11.2、拦截器的三个抽象方法
这三个方法不管控制器方法有没有都会执行
SpringMVC中的拦截器有三个抽象方法:
preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
postHandle:控制器方法执行之后执行postHandle()
afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()
11.3、多个拦截器的执行顺序
①若每个拦截器的preHandle()都返回true
此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:preHandle()会按照配置的顺序执行,而postHandle()和afterCompletion()会按照配置的反序执行
②若某个拦截器的preHandle()返回了false
preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterCompletion()会执行
12、异常处理器
控制器方法执行的过程中如果出现了异常,那么就可以通过springmvc给我们提供的一个接口来处理异常
12.1、基于配置的异常处理
SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver
HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和
SimpleMappingExceptionResolver
SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- properties的键表示处理器方法执行过程中出现的异常 properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面 --> <prop key="java.lang.ArithmeticException">error</prop> </props> </property> <!-- exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享 这里的ex就是异常信息在请求域中的属性名 --> <property name="exceptionAttribute" value="ex"></property> </bean>
出现了异常就会往我们设置好的页面去跳
获取请求域中共享的异常信息
<p th:text="${ex}"></p>
12.2、基于注解的异常处理
//@ControllerAdvice将当前类标识为异常处理的组件 @ControllerAdvice public class ExceptionController { //@ExceptionHandler用于设置所标识方法处理的异常 @ExceptionHandler(ArithmeticException.class) //ex表示当前请求处理中出现的异常对象 public String handleArithmeticException(Exception ex, Model model){ model.addAttribute("ex", ex); return "error"; } }
13、注解配置SpringMVC
使用配置类和注解代替web.xml和SpringMVC配置文件的功能
13.1、创建初始化类,代替web.xml
在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器。 Spring提供了这–…+个接口的实现,名为
SpringServletContainerInitializer,这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。Spring3.2引入了一个便利的WebApplicationInitializer基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer,当我们的类扩展了
AbstractAnnotationConfigDispatcherServletInitializer并将其部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。用来代替web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer { //设置一个配置类代替spring配置文件 @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } @Override //设置一个配置类代替springmvc的配置文件 protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } @Override //设置springMVC的前端控制器Dispatcherservlet的url-pattern protected String[] getServletMappings() { return new String[]{"/"}; } @Override //来设置当前的过滤器 protected Filter[] getServletFilters() { //创建编码过滤器 CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter(); encodingFilter.setEncoding("UTF-8"); encodingFilter.setForceRequestEncoding(true); //创建处理请求方式的过滤器 HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[]{encodingFilter, hiddenHttpMethodFilter}; } }
13.2、创建SpringConfig配置类,代替spring的配置文件
//@Configuration将当前类表示为配置类 @Configuration public class SpringConfig { //ssm整合之后,spring的配置信息写在此类中 }
13.3、创建WebConfig配置类,代替SpringMVC的配置文件
//代替springmvc的配置文件 @Configuration //扫描主件 @ComponentScan("com.atguigu.controller") //开启注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { //使用默认的servlet处理静态资源 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } //配置文件上传解析器,@Bean注解可以将标识的方法的返回值作为bean进行管理,bean的id为方法的方法名 @Bean public CommonsMultipartResolver multipartResolver(){ return new CommonsMultipartResolver(); } //配置拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { FirstInterceptor firstInterceptor = new FirstInterceptor(); registry.addInterceptor(firstInterceptor).addPathPatterns("/**"); } //配置视图控制 @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); } //配置异常映射 @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> 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 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; } }
13.4、测试功能
@RequestMapping("/") public String index(){ return "index"; }
springmvc(5)https://developer.aliyun.com/article/1530460