SpringMVC-02

1 响应数据和结果视图

响应数据和结果视图

字符串
controller方法返回字符串可以指定逻辑视图名字,通过视图解析器,解析为一个jsp的物理视图地址。
比如:

@RequestMapping("/testReturnString")
 public String testReturnString() {
    System.out.println("AccountController 的 testReturnString 方法执行了。。。。"); 
     return "success";
 } 

结果:


仔细看截图红框和代码直接的关系。

void
页面跳转,可以把原生的 HttpServletRequest 跟 HttpServletResponse 做入参数注入到目标方法中。servlet怎么用,现在就怎么用
适用场景:异步请求
返回的不是一个纯页面,可能就是一些简单数据。
代码:

jsp代码:

 testVoid


java代码:
@Controller
@RequestMapping("/user")
public class userController{

    @RequestMapping("/testVoid")
      public void testVoid(HttpServletRequest request,HttpServletRsponse response) throws Exception{
          System.out.println("testVoid 方法执行");
          //编写请求转发的程序 (手动写转发时 程序不会调用视图解析器 所以写路径要写全)
           request.getRequstDispatcher("/WEB-INF/pages/success.jsp ").forward(request,response);  


          //如果是重定向
        response.sendRedirect(request.getContextPath()+" /index.jsp ");

        //如果是直接响应
      
       //1 首先设置中文乱码
      response.setCharaterEncoding("UTF-8");
      response.setContenType("test/html;charset=UTF-8");
  
      //2 直接响应的数据
      response.getWriter().print("直接响应成功");
    return;
    }
}

ModelAndView
ModelAndView 是 SpringMVC 为我们提供的一个对象,无论返回值是什么,springmvc 都会把结果封装成一个 ModelAndView对象。该对象也可以用作控制器方法的返回值。也可以通过视图解析器跳转到某个页面。
ModelAndView 中有两个方法
addObject(String,Object); 封装数据,底层是把数据封装到了 request 域中
setViewName(String); 指定视图名称

适用场景:当Handler 执行完后,即有模型数据时,又有响应视图信息。

代码:

jsp代码:

 testVoid


java代码:
@Controller
@RequestMapping("/user")
public class userController{

    @RequestMapping("/testModelAndView")
      public ModelAndView  testModelAndView(){
          ModelAndView mv = new ModelAndView();
      
          User user =  new User();
        user.setUsername("小凤");
        user.setPassword("456");
        user.setAge(30);

         //把user对象存入到mv对象中,底层也会把user这个对象存到request域对象当中。
        mv.addObject("user",user);
        //想跳转到哪个页面。
        mv.setViewName("success");
        return mv;
    }
}
success.jsp


    

执行成功

${user.username} ${user.password}

输出结果为:


如果用了关键字forwardredirect进行页面跳转,那么视图解析器会失效,路径需要自己注意写全。

//请求转发
 return "forward:/WEB-INF/pages/success.jsp";
需要注意的是,如果用了 formward:则路径必须写成实际视图 url,
不能写逻辑视图。 它相当于“request.getRequestDispatcher("url").forward(request,response)”。
使用请求 转发,既可以转发到 jsp,也可以转发到其他的控制器方法。


//重定向
return "redirect:/index.jsp";
它相当于“response.sendRedirect(url)”。需要注意的是,
如果是重定向到 jsp 页面,则 jsp 页面不 能写在 WEB-INF 目录中,否则无法找到。 

@ResponseBody 响应 json 数据

作用: 该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的 数据如:json,xml 等,通过 Response 响应给客户端。

  1. DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而 不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
  2. mvc:resources标签配置不过滤
    1. location元素表示webapp目录下的包下的所有文件
    2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
 
      
      
      

1 创建一个js的文件夹 然后引入一个jQuery.min.js文件。
2 在页面当中引入这个文件,新建一个请求按钮 ,绑定单击事件:

<%@page cintentType = "text/html;charset=UTF-8 " language="java"%>

  
      Title
                    //引入jQuery文件
      
                
      
              //页面加载 绑定单击事件
            $(function(){
                  $("#btn").clinck(function(){
                       //发送ajax请求
                        $.ajax({
                            //编写json格式:设置属性和值。
                             //url :请求路径
                            //contentType:指定发送至服务器内容的编码格式。
                            //data:发送到服务器的数据。
                            //dataType:预期服务器返回的数据类型。
                            //type:请求方式
                          //success:请求成功后回调函数

                              url:"user/testAjax",
                              contentType:"application/json;charset:utf-8",
                               data:'{" username":"hehe ","password":"123"}',
                              dataType:"json",
                              type:"post",
                              success:function(data){
                              //这里的data是服务器响应的json数据 
                              }
                            });
                     });
            });


      
  

                //新建请求按钮
    


3 在springmvc.xml中配置上方的拦截器。
4 模拟异步请求响应

@RequstMapping("/testAjax")
public @RequestBody user testAjax(@RequestBody User user){
    System.out.println("testAjax执行");
//客户端发送ajax的请求 传的是json字符串 后端把json字符串封装到user对象中,作相应,模拟查询数据库
    user.setUsername("haha");
    user.setAge(40); 

  //作相应
return user;
  }

响应数据(json数据)
@ResponseBody 响应 json 数据
@ResponseBody 修饰目标 Handler 方法
springmvc 会把返回的对象或者集合转换成 json 串
如果返回的是普通字符串,那么就是字符串
前提:必须导入 jackson 的三个 jar 包(版本要求在 2.7.0 以上)
如果报 415 异常,很有可能是没有导入 jackson 依赖。

json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包


           com.fasterxml.jackson.core
           jackson-databind
           2.9.0
       
       
           com.fasterxml.jackson.core
           jackson-core
           2.9.0
       
       
           com.fasterxml.jackson.core
           jackson-annotations
           2.9.0 
      

6、文件上传

文件上传的回顾

  1. 导入文件上传的jar包

           commons-fileupload
           commons-fileupload
           1.3.1
       
       
           commons-io
           commons-io
           2.4
       

  1. 编写文件上传的JSP页面

文件上传

选择文件:
  1. 编写文件上传的Controller控制器
 /**
     * 文件上传
      */
    @RequestMapping(value="/fileupload")
    public String fileupload(HttpServletRequest request) throws Exception {
        // 先获取到要上传的文件目录
      String path = request.getSession().getServletContext().getRealPath("/uploads");
        // 创建File对象,一会向该路径下上传文件
        File file = new File(path);
        // 判断路径是否存在,如果不存在,创建该路径
        if(!file.exists()) {
            file.mkdirs();
        }
        // 创建磁盘文件项工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        // 解析request对象
        List list = fileUpload.parseRequest(request);
        // 遍历
        for (FileItem fileItem : list) {
            // 判断文件项是普通字段,还是上传的文件
            if(fileItem.isFormField()) {
                            }else {
                // 上传文件项
                // 获取到上传文件的名称
                String filename = fileItem.getName();
                // 上传文件
                fileItem.write(new File(file, filename)); 
               // 删除临时文件
                fileItem.delete();
            }
        }
                return "success";
   }

2. SpringMVC传统方式文件上传

  1. SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。

  2. 代码如下

/**
*  SpringMVC方式的文件上传
*/
    @RequestMapping(value="/fileupload2")
    public String fileupload2(HttpServletRequest request,MultipartFile upload) throws Exception {
        System.out.println("SpringMVC方式的文件上传...");
        // 先获取到要上传的文件目录
      String path = request.getSession().getServletContext().getRealPath("/uploads");
        // 创建File对象,一会向该路径下上传文件
        File file = new File(path);
        // 判断路径是否存在,如果不存在,创建该路径 
       if(!file.exists()) {
            file.mkdirs();
        }
        // 获取到上传文件的名称
        String filename = upload.getOriginalFilename();
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
        // 把文件的名称唯一化
        filename = uuid+"_"+filename;
       // 上传文件
        upload.transferTo(new File(file,filename));
        return "success";
    }
  1. 配置文件解析器对象

    

        
    

3. SpringMVC跨服务器方式文件上传

  1. 搭建图片服务器
    1. 根据文档配置tomcat9的服务器,现在是2个服务器
    2. 导入资料中day02_springmvc5_02image项目,作为图片服务器使
  2. 实现SpringMVC跨服务器方式文件上传

1 导入开发需要的jar包

        
            com.sun.jersey
            jersey-core
            1.18.1
        

        
            com.sun.jersey
            jersey-client
            1.18.1
        

2 编写文件上传的JSP页面

跨服务器的文件上传

选择文件:

3 编写控制器

/**
 * SpringMVC跨服务器方式的文件上
 */
 @RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception {
       System.out.println("SpringMVC跨服务器方式的文件上传..."); 
              // 定义图片服务器的请求路径
       String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
               // 获取到上传文件的名称
       String filename = upload.getOriginalFilename();
       String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
       // 把文件的名称唯一化
       filename = uuid+"_"+filename;
       // 向图片服务器上传文件
               // 创建客户端对象
       Client client = Client.create();
       // 连接图片服务器
       WebResource webResource = client.resource(path+filename); 
      // 上传文件
       webResource.put(upload.getBytes());
       return "success";
   }

注意:跨服务器上传文件时,会抛出一个异常,状态码为403
解决方案如下:在 tomcat/conf/web.xml 找到 default 节点


    default
    org.apache.catalina.servlets.DefaultServlet
    
        debug
        0
    
    
        listings
        false
    
    
    
    
        readonly
        false
    
    
    1

异常处理机制


当程序出现错误的时候,会一层层的向上抛出,最后到前端控制器这里反馈给浏览器,此时如果不在前端控制器上做处理,那么错误就会原封不动的返回给浏览器,这样用户感受很不好,所以我们的异常处理指的是:在前端控制器里配置一个异常处理组件来处理异常,只要有异常,被它捕获以后会给浏览器返回一个友好的提示错误页面。

编辑自定义异常类和错误页面

/**
* 自定义异常类
*/
public class CustomException extends Exception { 
 
 private String message; 
 
 public CustomException(String message) {
   this.message = message;
  } 
 
 public String getMessage() {
   return message; 
   }
 } 
jsp 页面:
 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 

 
 
  
执行失败
 
  
执行失败! 
 
${message } 
 

定义一个异常处理类实现 HandlerExceptionResolver 接口,重写抽象方法

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, 
                                     Object handler, Exception ex) {
    // 获取到异常对象
    SysException e = null;
    if(ex instanceof SysException){
        e = (SysException)ex;
    }else{
        e = new SysException("系统正在维护....");
    }
    // 创建ModelAndView对象
    ModelAndView mv = new ModelAndView();
    mv.addObject("errorMsg",e.getMessage());
    mv.setViewName("error");
    return mv;
}

在 springmvc.xml 配置文件中配置异常处理器bean



例如:

 

8、拦截器

过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦 截的。

它也是 AOP 思想的具体应用。

自定义拦截器 实现 HandlerInterceptor 接口

/**
 * 自定义拦截器
 */
public class MyInterceptor1 implements HandlerInterceptor {

    /**
     * 预处理,controller方法执行前   执行
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false 不放行,不会执行controller的方法
     *  通常用来做 权限拦截
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了...前1111");
        return true;//放行
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp 执行之前  执行
     *  通常用来 改变响应视图
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1执行了...后1111");  
    }

    /**
     * success.jsp页面执行后,该方法会执行
     *  通常用来 释放资源
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最后1111");
    }

}

​ 在 springmvc.xml 配置文件中配置拦截器



    
    
        
        
        
        
        
        
    

你可能感兴趣的:(SpringMVC-02)