09.SpringMVC_处理JSON&国际化&文件上传&拦截器&异常处理

1.处理JSON
  • @RequestBody和@ResposeBody
    • @RequestBody
      • 用来将请求报文转换为方法入参中的某个类型的对象
      • 注解只能添加到方法的入参前面
      • 例如:将上传文件的流转换为方法入参中的一个字符串类型
        • 表单
< form action = " ${pageContext.request.contextPath } /testRequestBody" method = "post" enctype = "multipart/form-data" >
         描述: < input type = "text" name = "desp" >< br >
         文件: < input type = "file" name = "wj" >< br >
          < input type = "submit" >
  </ form >
  • 测试方法
@RequestMapping ( "/testRequestBody" )
     public String testRequestBody( @RequestBody String body ){
         System. out .println( "请求报文中的信息是:" + body );
          return "success" ;
    }
这里如果是要显示保文信息就不用写
  < bean id = "multipartResolver"
         class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" >
       设置字符集
        < property name = "defaultEncoding" value = "UTF-8" ></ property >
       设置文件的大小
        < property name = "maxUploadSize" value = "102400" ></ property >
     </ bean >
  • 也可以通过在方法的入参中传入HttpEntity<T>对象来实现类似的功能
  • @ResposeBody
    • 用来将Handler的方法的返回值以某种格式响应给前端
    • 该注解可以添加到类上,也可以添加到方法上
      • 如果添加到类上,Handler中的所有方法的返回值将直接响应给页面
@ResponseBody //如果该注解添加到类上, 类中所有的方法的返回值 将直接响应给浏览器
@Controller
public class SpringMVCHandler {
  • 如果添加到方法上,只有添加了该注解的方法的返回值会直接响应給页面
@ResponseBody
     @RequestMapping ( "/testResponseBody" )
     public String testResponseBody(){
         System. out .println( "测试ResponseBody" );
          return "success" ; //当Handler的方法上添加了@ResponseBody注解之后返回值将直接响应给浏览器 
      JSP页面显示的是success
    }
     @ResponseBody
     @RequestMapping ( "/testResponseBody2" )
     public String testResponseBody2(){
         System. out .println( "测试ResponseBody2" );
          return "page" ; //当Handler的方法上添加了@ResponseBody注解之后返回值将直接响应给浏览器
    }
  • 也可以通过将方法的返回值设置为ResponseEntity<T>来实现类似的功能
    • 实现文件下载的功能
//实现文件下载的效果
     @RequestMapping ( "/testResponseEntity" )
     public ResponseEntity< byte []> testResponseEntity(HttpSession session ) throws IOException{
          //获取ServletContext对象
         ServletContext servletContext = session .getServletContext();
          //获取输入流
         InputStream is = servletContext .getResourceAsStream( "/download/meinv.jpg" );
          //创建byte数组
          byte [] body = new byte [ is .available()];
          //将流读到数组中
          is .read( body );
          //设置响应头
         HttpHeaders headers = new HttpHeaders();
          //告诉浏览器如果处理文件
          headers .add( "Content-Disposition" , "attachment; filename=mn.jpg" );
          //设置 Http 的状态码为OK
         HttpStatus statusCode = HttpStatus. OK ;
          //创建ResponseEntity
         ResponseEntity< byte []> responseBody = new ResponseEntity< byte []>( body , headers , statusCode );
          return responseBody ;
    }
  • 实现文件上传功能
//文件上传
@RequestMapping("/testFileUpload")
    public String testFileUpload(@RequestParam("desp") String desp ,
            @RequestParam("wj") MultipartFile file , HttpSession session) throws IllegalStateException, IOException{
        System.out.println("文件的描述性信息是:"+desp);
        //获取文件名
        String fileName = file.getOriginalFilename();
        //获取文件的类型
        String contentType = file.getContentType();
        //获取文件的大小
        long size = file.getSize();
        System.out.println("文件名是:"+fileName);
        System.out.println("文件的类型是:"+contentType);
        System.out.println("文件的大小是:"+size+"字节");
        //获取ServletContext对象
        ServletContext servletContext = session.getServletContext();
        //获取upload目录在服务器端的真实路径
        String realPath = servletContext.getRealPath("/upload");
        //判断服务端是否有upload目录,如果没人,让它自动创建
        File upload = new File(realPath);
        if(!upload.exists()){
            //创建该目录
            upload.mkdirs();
        }
        //将文件上传到upload目录中
        file.transferTo(new File(realPath+"/"+fileName));
        return "success";
    }

在springmvc.xml中需要配置以下
< bean id = "multipartResolver"
         class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" >
        <!-- //设置字符集 -->
        < property name = "defaultEncoding" value = "UTF-8" ></ property >
        <!-- 设置文件的大小 -->
        < property name = "maxUploadSize" value = "102400" ></ property >
     </ bean >

  • 处理JSON
    • 导入以下jar包
    jackson-annotations-2.1.5.jar
    jackson-core-2.1.5.jar
    jackson-databind-2.1.5.jar

  • 发送一个Ajax请求并在处理请求的方法上添加@RequestBody注解
    • 发送Ajax请求
< button id = "btn" > Test JSON </ button >< br >

$( function (){
          //给按钮绑定单击事件
         $( "#btn" ).click( function (){
              //发送Ajax请求
              //设置请求地址
              var url = "${pageContext.request.contextPath }/testJSON"
             $.post(url, function (data){
                  for ( var i = 0; i < data.length; i++){
                     alert(data[i].id+ "-" +data[i].username);
                 }
             });
         });
    });


  • 处理请求
@ResponseBody
     @RequestMapping ( "/testJSON" )
     public List<User> testJSON(){
         System. out .println( "通过发送Ajax请求处理JSON数据" );
          //创建一个List<User>
         List<User> list = new ArrayList<>();
          //向list中添加User对象
          list .add( new User(1, "虚刚" , "123456" , " yyyxxx@mmm.com " ));
          list .add( new User(2, "许刚" , "222222" , " jsx@xsl.com " ));
          list .add( new User(3, "虚虚刚" , "444444" , " sbll@wys.com " ));
          return list ;
    }
  • 能实现上述功能是通过HttpMessageConverter<T>接口的具体实现类来实现的
2.国际化
  • SpringMVC通过LocaleResolver解析器获取本地化信息,默认使用的解析器是AcceptHeaderLocaleResolver,这时发请求时会自动获取浏览器中的Accept-Language的属性值来实现国际化
  • 实现国际化需要在SpringMVC的配置文件中配置国际化资源文件
<!-- 设置国际化资源文件 -->
     < bean id = "messageSource" class = "org.springframework.context.support.ResourceBundleMessageSource" >
          <!-- 设置国际化资源文件的基础名 -->
          < property name = "basename" value = "i18n" ></ property >
     </ bean >
  • 我们可以通过超链接的形式来实现中英文的切换
    • 1)在SPringMVC的配置文件中配置SessionLocaleResolver解析器和LocaleChangeInterceptor拦截器
<!-- 配置SessionLocaleResolver -->
     < bean id = "localeResolver" class = "org.springframework.web.servlet.i18n.SessionLocaleResolver" ></ bean >
    
     <!-- 配置LocaleChangeInterceptor -->
     <!-- 拦截器额执行顺序由配置的先后顺序决定 -->
     < mvc:interceptors >
          < bean class = "org.springframework.web.servlet.i18n.LocaleChangeInterceptor" >
              <!-- 通过paramName属性设置超链接中传入的语言及国家信息的请求参数 -->
              < property name = "paramName" value = " language " ></ property >
          </ bean >
     </ mvc:interceptors >
  • 2)前端的超链接发送请求时需要携带一个请求参数,参数的默认的名字是locale,我们可以在LocaleChangeIntercepto中设置这个参数名
< a href = " ${pageContext.request.contextPath } /testCutomerI18N? language =zh_CN" > 中文 </ a > |
     < a href = " ${pageContext.request.contextPath } /testCutomerI18N? language =en_US" > ENGLISH </ a >
<!-- 设置不经过Handler的方法直接响应的页面 -->
    <mvc:view-controller path="/testCutomerI18N" view-name="success"/>
  • 通过1)和2)的设置之后,当我们点击超链接时,会将语言及国家的信息设置到session域中,以后在发送请求会直接从session域中获取语言及国家的信息,以此来实现国际化的操作
3.文件的上传
  • 1)需要导入以下jar包
     commons-fileupload- 1.3 .1. jar
    commons-io-2.5. jar
  • 2)在SpringMVC的配置文件中配置CommonsMultipartResovler解析器
<!-- 配置CommonsMultipartResovler -->
     < bean id = "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" >
          <!-- 设置字符集 -->
          < property name = "defaultEncoding" value = "UTF-8" ></ property >
          <!-- 设置文件的大小 -->
          < property name = "maxUploadSize" value = "102400" ></ property >
     </ bean >
  • 3)上传文件的表单
< form action = " ${pageContext.request.contextPath } /testFileUpload" method = "post" enctype = "multipart/form-data" >
         描述: < input type = "text" name = "desp" >< br >
         文件: < input type = "file" name = "wj" >< br >
          < input type = "submit" >
     </ form >
  • 4)处理文件上传的方法,该方法中需要传入一个MultipartFile类型的一个参数
@RequestMapping ( "/testFileUpload" )
     public String testFileUpload( @RequestParam ( "desp" ) String desp ,
              @RequestParam ( "wj" ) MultipartFile file , HttpSession session ) throws IllegalStateException, IOException{
         System. out .println( "文件的描述性信息是:" + desp );
          //获取文件名
         String fileName = file .getOriginalFilename();
          //获取文件的类型
         String contentType = file .getContentType();
          //获取文件的大小
          long size = file .getSize();
         System. out .println( "文件名是:" + fileName );
         System. out .println( "文件的类型是:" + contentType );
         System. out .println( "文件的大小是:" + size + "字节" );
          //获取ServletContext对象
         ServletContext servletContext = session .getServletContext();
          //获取upload目录在服务器端的真实路径
         String realPath = servletContext .getRealPath( "/upload" );
          //判断服务端是否有upload目录,如果没人,让它自动创建
         File upload = new File( realPath );
          if (! upload .exists()){
              //创建该目录
              upload .mkdirs();
         }
          //将文件上传到upload目录中
          file .transferTo( new File( realPath + "/" + fileName ));
          return "success" ;
    }
4.拦截器
  • 自定义拦截器需要实现HandlerInterceptor接口
public class FirstInterceptor implements HandlerInterceptor {
     /**
     * 在调用目标方法之前执行
     *
     * 可以用来设置权限、日志、事务
     */
     @Override
     public boolean preHandle(HttpServletRequest request , HttpServletResponse response , Object handler )
              throws Exception {
         System. out .println( "FirstInterceptor的preHandle方法被调用" );
          return true ;
    }
     /**
     * 调用目标之后渲染视图之前执行
     *
     * 可以修改ModelAndView中模型数据及视图
     */
     @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方法被调用" );
    }
}
  • 在SpringMVC中配置拦截器
<!-- 配置LocaleChangeInterceptor -->
     <!-- 拦截器额执行顺序由配置的先后顺序决定 -->
     < mvc:interceptors >
          < bean class = "org.springframework.web.servlet.i18n.LocaleChangeInterceptor" >
              <!-- 通过paramName属性设置超链接中传入的语言及国家信息的请求参数 -->
              < property name = "paramName" value = "language" ></ property >
          </ bean >
          <!-- 通过以下这种方式配置的拦截器会拦截所有的请求 -->
           < bean class = "com.atguigu.springmvc.interceptor.FirstInterceptor" ></ bean >
          <!-- 也可以通过以下方式配置拦截器,通过这种方式可以配置拦截和不拦截那些请求 -->
           < mvc:interceptor >
              <!-- 设置拦截的请求 -->
              < mvc:mapping path = "/testInterceptor" />
              <!-- 设置不拦截那些请求 -->
<!--             <mvc:exclude-mapping path=""/> -->
              < bean class = "com.atguigu.springmvc.interceptor.SecondInterceptor" ></ bean >
          </ mvc:interceptor >
     </ mvc:interceptors >
  • 具体多个拦截器的执行顺序请参照源码



5.异常处理
  • Spring MVC 通过 HandlerExceptionResolver  处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常
  • Spring MVC 提供的 HandlerExceptionResolver的实现类(打红色方框的)

  • @ExceptionHandler注解
    • 通过该注解标识一个处理异常的方法
@ExceptionHandler (value=ArithmeticException. class )
     //定义一个处理异常的方法
     public String resoveException(Exception e ){
         System. out .println( "异常信息是:" + e );
          return "error" ;
    }
     //异常匹配的优先级: 根据继承关系优先匹配
     @ExceptionHandler (value=RuntimeException. class )
     //定义一个处理异常的方法
     public String resoveException2(Exception e ){
         System. out .println( "[异常信息是]:" + e );
          return "error" ;
    }
     @ExceptionHandler (value=Exception. class )
     //定义一个处理异常的方法
     public String resoveException3(Exception e ){
         System. out .println( "【异常信息是】:" + e );
          return "error" ;
    }
  • 在方法上添加了@ExceptionHandler注解之后,该方法只能处理当前Handler的方法执行时出现的异常,如果想定义一个全局的处理异常的方法,我们可以使用@ControllerAdvice注解标识一个处理异常的类
@ControllerAdvice
// 如果当前Handler中没有处理异常的方法,会去标识了@ControllerAdvice注解的类中去寻找处理异常的方法
public class ResolveExceptionClass {
     //定义一个处理异常的方法
     @ExceptionHandler (value=Exception. class )
     public String resoveException3(Exception e ){
         System. out .println( "{异常信息是}:" + e );
          return "error" ;
    }
}

实例:
JSP:
< h2 > 出错信息 </ h2 > ${requestScope.exception }
类中
package exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class ResolveExceptionClass {
     //定义一个处理异常的方法
    @ExceptionHandler (value=Exception. class )
    public ModelAndView resoveException3(Exception e ){
         System. out .println( "{异常信息是}:" + e );
         ModelAndView mv = new ModelAndView( "error" );
         mv .addObject( "exception" , e );
         mv .setViewName( "error" );
         return mv ;
    }
}
异常对象不能通过 Map 集合方式传递给成功页面, 可以通过ModelAndView将异常对象传递给成功页面上
  • @ResponseStatus
    • 通过该注解可以标识一个异常类,当出现该异常时会去指定的异常页面
@ResponseStatus (value= HttpStatus. UNAUTHORIZED ,reason= "滚犊子!你没有此权限!!!" )
public class UnAuthorizedException extends RuntimeException {
     /**
     *
     */
     private static final long serialVersionUID = 1L;
}
  • 测试方法
@RequestMapping ( "/testResponseStatus" )
     public String testResponseStatus( @RequestParam ( "username" ) String username ){
          if (! "superAdmin" .equals( username )){
              //抛出没有权限的异常
              throw new UnAuthorizedException();
         }
          return "success" ;
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值