Springday05 SpringMVC访问静态资源操作请求域控制器方法返回值JSON数据交互RESTful风格文件上传异常处理拦截器

Posted halulu.me

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springday05 SpringMVC访问静态资源操作请求域控制器方法返回值JSON数据交互RESTful风格文件上传异常处理拦截器相关的知识,希望对你有一定的参考价值。

静态资源访问

前端静态资源的访问 —》 后端直接获取静态资源进行响应, 不走springmvc

前端访问jsp资源 —》 后端直接执行jsp, 不走springmvc

其他请求后端资源 —》 后端执行springmvc

映射路径设置为: “/”
"/“的作用:不拦截以”.jsp"的结尾路径, 其他所有请求路径全都拦截(通过其他设置实现静态资源不拦截)


	<!--1.配置springmvc前端控制器(核心控制器)DispathcerServlet-->
	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!--配置价值springMVC.xml文件-->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springMVC.xml</param-value>
		</init-param>
		<!--启动时创建servlet-->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<!--
		映射路径设置为: “/”
		"/"的作用:不拦截以".jsp"的结尾路径, 其他所有请求路径全都拦截(通过其他设置实现静态资源不拦截)
	-->
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

springMVC中拦截请求路径是“/”,导致静态资源index.html访问不了。

原因:
在这里插入图片描述

2、自己项目配置的DispatcherServlet拦截的路径也是/, 会覆盖DefaultServlet。

3、DefaultServlet的作用: tomcat提供的默认servlet,专门用于处理静态资源。

方法一:(不推荐使用)

重新映射

	<!--静态资源处理方案1:web.xml中将静态资源的处理交换给全局配置的默认的Servlet-->
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.html</url-pattern>
		<url-pattern>*.js</url-pattern>
		<url-pattern>*.css</url-pattern>
		<url-pattern>*.jpg</url-pattern>
	</servlet-mapping>

方法二:

SpringMVC也提供了解决方案用来解决上述静态资源访问不了的问题。

在这里插入图片描述

    <!--
    解决静态资源直接访问的方案2:通过标签<mvc:resources>解决
    注意点:
        1.mapping属性:配置映射的任何静态资源,注意必须是2个*号
        2.location:配置直接访问的资源路径
              第一个"/",代表直接访问webapp目录下的静态资源文件
              第二个"classpath:static/",代表直接访问resources/static目录下的静态资源文件
              第三个“/WEB-INF/”,代表访问webapp/WEB-INF/目录下的静态资源文件,转发跳转
              由于
              多个路径之间使用逗号隔开,路径必须以“/”结束
    -->
    <mvc:resources mapping="/**" location="/,classpath:static/,/WEB-INF/"></mvc:resources>

方法三:
在这里插入图片描述

    <!--
    解决静态资源直接访问的方案3:通过标签<mvc:default-servlet-handler/>交给tomcat默认的DefaultServlet处理
      注意:
        1.所有的静态资源都必须放在webapp目录下
        2.不同的服务器,默认的Servlet名字都不一样,所以当前默认名字不是default的时候
          default-servlet-name="default" ,如果是default可以不写,否则必须指明具体的名字
          例如:webLogic服务器,就需要设置default-servlet-name="FileServlet"
    -->
    <mvc:default-servlet-handler default-servlet-name="default"></mvc:default-servlet-handler>

注意:

不同服务器的默认servlet的名字是不一样的。

在这里插入图片描述

SpringMVC操作请求域

  • 方式1:原生servlet的api操作request对象
  • 方式2:jdk的Map集合对象
  • 方式3:springMVC提供的Model对象
  • 方式4:springMVC提供的ModelMap对象
  • 方式5:springMVC提供的ModelAndView对象【用的最多】
@Controller
@RequestMapping("/model")
public class ModeLController {

    @RequestMapping("/requestData")
    public ModelAndView requestData(HttpServletRequest request,
                                    Map map,
                                    Model model,
                                    ModelMap modelMap
                                    ModelAndView modelAndView){

        /*
         * 目标:操作请求域存储数据的5种方式
         *   方式1:原生servlet的api操作request对象
         *   方式2:jdk的Map集合对象
         *   方式3:springMVC提供的Model对象
         *   方式4:springMVC提供的ModelMap对象
         *   方式5:springMVC提供的ModelAndView对象【用的最多】
         *
         * 5种方案的相同点:
         *   都是可以写入请求域数据,数据格式都是键值对,本质都是Map
         * 不同点
         *   Model是一个接口
         *   ModelMap是一个类
         *   ModelAndView: 不仅可以写入请求域数据还可以设置返回的视图名字
         *   Map是jdk,其他都是springMvc提供
         *
         * 小结:
         *   任意一个就可以
         *
         * 如果想操作会话域或上下文域对象:必须使用servlet原生api操作
         *     会话域: request.getSession()
         *     上下文域: reqeust.getServletContext()
         * */

        /*方式1:原生servlet的api操作request对象*/
        request.setAttribute("request_data","播仔");

        /*方式2:jdk提供的Map对象*/
        map.put("map_data","itheima");

        /*方式3:springMVC提供的Model对象*/
        //语法:model.addAttribute(String key,Object value);
        model.addAttribute("mode_data","播妞");

        /*方式4:springMVC提供的ModelMap对象*/
        //语法:modelMap.addAttribute(String key,Object value);
        modelMap.addAttribute("modelmap_data","狗娃");

        /*方式5:springMVC提供的ModelAndView对象
         *       ModelAndView 既可以写入请求域数据又可以设置返回视图的名字,并且可以作为控制器方法返回值
         *  写入请求域数据语法:modelAndView.addObject(String key,Object value);
         *  设置返回视图的名字语法:modelAndView.setViewName("视图名字");
         * */
        //实例
        ModelAndView modelAndView = new ModelAndView();
        //写入请求域数据
        modelAndView.addObject("modelAndView_data","itcast");
        //设置视图名字
        modelAndView.setViewName("success");
        return modelAndView;
    }
}

SpringMVC控制器方法返回值

控制器方法返回值类型:

1、返回String字符串
a、 返回页面名称字符串(视图名字)
b、返回转发字符串
c、 返回重定向字符串

2、返回void
3、返回ModelAndView对象
4、 返回任意对象。(配置@ResponseBody注解实现转换为json字符串返回)

@Controller
@RequestMapping("/return")
public class ReturnController {

    @RequestMapping("/string")
    public String returnString(){

        /* 1. 返回页面名称字符串(视图名字)*/
        //return "success";

        /*
        * 2. 返回转发字符串
        * 介绍:如果想不受视图前缀与后缀的约束,可以使用返回转发字符串跳转到任意位置资源
        * 格式: "forward:/转发的路径"
        * 注意:转发的路径是完整的路径,必须带有前缀与后缀
        * 转发跳转特点:跳转前后url不变
         * */
        //return "forward:/index.jsp";

        /*
         * 3. 返回重定向字符串
         * 介绍:如果想不受视图前缀与后缀的约束,可以使用返回重定向字符串重定向跳转到任意位置资源
         * 格式: "redirect:/重定向的路径"
         * 注意:重定向的路径,不可以写项目路径,因为springmvc会自动加上项目路径
         * 重定向跳转特点:跳转前后url会变
         * */
        return "redirect:/index.jsp";

    }

    @RequestMapping("/void")
    public void returnVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{
        //应用场景:操作会话域、上下文域、响应头设置、响应行设置、cookie操作等原生api

        //应用1:原生转发
        //request.getRequestDispatcher("/index.jsp").forward(request,response);

        //应用2:原生重定向
        //response.sendRedirect(request.getContextPath()+"/index.jsp");

        //应用3【重要】:附件下载
        response.setHeader("content-disposition","attachment;filename=6.jpg");
        //获取img/6.jpg的输入流
        InputStream inputStream = request.getServletContext().getResourceAsStream("/img/6.jpg");
        //输出
        IOUtils.copy(inputStream,response.getOutputStream());

    }
}

交互JSON数据:@RequestBody与@ResponseBody

SpringMVC交互JSON数据需要依赖于jackson

<!--添加jackson支持包: springMVC框架操作json数据时调用的技术-->
<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
</dependency>
@Controller
@RequestMapping("/json")
public class JsonController {

    /*
     * 注解@RequestBody
     *   介绍:实现将前端传递过来的json字符串转换为java对象
     *   使用的位置: 控制器方法的参数上,将请求体中json字符串转换为java对象赋值给参数
     *   技术原理:使用jackson实现json字符串转换为java对象
     *   注意:如果前端传递的不是json字符串,会发生415错误
     * 注解@ResponseBody
     *   介绍:实现将控制器方法返回值的java对象转换为json字符串
     *   注意:如果控制器返回值的类型是String字符串,默认含有中文会乱码,需要设置
     *         @RequestMapping(value="/data",produces = "application/json;charset=utf-8")
     *        解决中文乱码
     * */
    @RequestMapping(value="/data")
    @ResponseBody
    public User jsonData(@RequestBody User user){
        System.out.println("name:"+user.getName());
        System.out.println("id:"+user.getId());
        return user;
    }

    //返回类型为字符串
    @RequestMapping(value="/data2",produces = "application/json;charset=utf-8")
    @ResponseBody
    public String jsonData2(){
        return "小一";  //这种直接返回字符串含有中文,如果不设置produces就会乱码
    }
}

直接返回中文字符串乱码的问题
使用: @RequestMapping(produces = “application/json;charset=utf-8”)

ajax传递json数据

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<input type="button" value="发送异步请求(请求数据为json格式)" id="b1">
<%--导入jquery--%>
<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
<script>

    /*目标1:发送异步请求通过post请求传递json字符串给服务器端*/
    /*
    * 异步传递数据格式:
    *   格式1:"key1=value1&key2=value2..." 不是json字符串格式
    *   格式2:{key1:value1,key2:value2} 这是json对象,不是json字符串,底层传递的格式与格式1是一样的
    *   格式3【符合要求】: json字符串格式
    *       第一步:拼接一个json字符串再发送
    *              手动拼接:'{"id":100,"name":"播仔"}'
    *              自动生成:JSON.stringify(json对象)  得到 json字符串
    *       第二步:设置提交数据的类型, contentType:"application/json;charset=utf-8"
    * */


    //1.给按钮注册点击事件
    $("#b1").click(function (){
        //2.发送异步请求
        $.ajax({
            url:"${pageContext.request.contextPath}/json/data",
            method:"post",
            data:'{"id":100,"name":"播仔"}',
            contentType:"application/json;charset=utf-8",
            success:function(user){
                //服务器返回的json字符串,jquery默认会将其转换为json对象,接收到的数据:{id:xx,name:xx}
                alert(`id:\\${user.id},name:\\${user.name}`);
            },
            error:function(obj){
                    console.log(obj);
                    alert("服务器忙。。。");
                }
        });
    });

</script>
</body>
</html>

注意:

data:’{“id”:100,“name”:“播仔”}’,
contentType:“application/json;charset=utf-8”,
使用单引号

RESTful风格编程

在这里插入图片描述

web.xml配置HiddenHttpMethodFilter 过滤器,让页面支持put、delete请求。

<!--配置HiddenHttpMethodFilter 过滤器-->
<filter>
   <filter-name>hiddenHttpMethodFilter</filter-name>
   <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>hiddenHttpMethodFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

通过post请求修改为put何delete

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--
目标:使用RestFul风格提交请求,一个路径实现增删改查
请求路径:http://localhost:8080/项目路径/user
分别提交不同的请求类型:
    get请求类型:查询数据
    post请求类型:添加数据
    put请求类型:修改数据
    delete请求类型:删除数据
--%>
<h2>Get请求</h2>
<form action="${pageContext.request.contextPath}/user" method="get">
    <input type="submit" value="Get查询用户列表请求">
</form>

<h2>Post请求</h2>
<form action="${pageContext.request.contextPath}/user" method="post">
    <input type="submit" value="Post添加用户数据请求">
</form>

<h2>Put请求</h2>
<!--发送put请求注意:-->
<!--1. 表单的提交方式都是post-->
<!--2. 表单中要有一个隐藏域,名称是_method, 其值就是真正的请求方式。-->
<form action="${pageContext.request.contextPath}/user" method="post">
    <input type="hidden" name="_method" value="put"/>
    爱好:<input type="text" name="hobby" value="爱编程">
    <input type="submit" value="Put修改用户数据请求">
</form>

<h2>Delete请求</h2>
<form action="${pageContext.request.contextPath}/user" method="post">
    <input type="hidden" name="_method" value="delete"/>
    <input type="submit" value="Delete删除用户数据请求">
</form>
</body>
</html>

@GetMapping("/{id}/{name}"),(@PathVariable(“id”) Integer id2,@PathVariable String name)
映射参数

@Controller
@RequestMapping("/user")
public class UserController {

    //处理get查询请求
    //@RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String findAll(){
        System.out.println("处理了用户列表查询请求");
        return "success";
    }

    //处理get查询id=100查询一个用户的请求
    //@RequestMapping(method = RequestMethod.GET)
    //路径模板映射配置:@GetMapping("/{名字1}/{名字2}")
    //接收路径中模板占位符传递的数据注解:@PathVariable("名字") 获取占位符路径传递过来的值并赋值给控制器方法参数
    // 注意:@PathVariable不设置名字的时候要去模板配置的名字要与方法参数变量名一样
    @GetMapping("/{id}/{name}")
    public String findById(@PathVariable("id") Integer id2,@PathVariable String name){
        System.out.println("处理了用户列表查询请求");
        System.out.println("路径中的id:"+id2+",路径中的name:"+name);
        return "success";
    }


    //处理post添加请求
    //@RequestMapping(method = RequestMethod.POST)
    @PostMapping
    public String add(){
        System.out.println("处理了用户添加请求");
        return "success";
    }


    /*
     * 处理put和delete请求注意事项
     *   后端处理这样的请求,控制器方法不可以转发跳转页面,否则正式服务器运行会报错, tomcat7的插件不会报错
     *        控制器方法返回视图名字也是转发跳转,正式服务器会报错
     *        错误信息:HTTP Status 405 – Method Not Allowed
     *            含义:不支持的请求类型,
     *   解决方案:只要不转发跳转就可以
     *       方案1: 重定向跳转,浏览器会发出新的默认get请求,就不会报错
     *       方案2: 不进行跳转,直接输出数据
     *               例如:@ResponseBody,  就是直接输出数据,将控制器方法返回值的java对象转换为json字符串输出
     *
     * */

    //处理put修改请求
    //@RequestMapping(method = RequestMethod.PUT)
    @PutMapping
    public String update(String hobby){
        System.out.println("处理了用户修改请求");
        System.out.println("参数数据hobby:"+hobby);
        return "redirect:/pages/success.jsp";
    }

    //处理delete删除请求
    //@RequestMapping(method = RequestMethod.DELETE)
    @DeleteMapping
    @ResponseBody
    public String delete(){
        System.out.println("处理了用户删除请求");
        return "hello";
    }
}

正式服务器转发跳转put和delete会报错,这是因为转发跳转会有2次检查,第一次检查将post变成deltete,第二次再次检查的时候会报错

SpringMVC 实现文件上传

SpringMVC实现文件上传借用了apache的fileupload

<!--添加Apache文件上传支持包-->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
  <head>
      <title>Title</title>
  </head>
  <body>
  <h2>文件上传</h2>
  <%--
  文件上传客户端要求三要素
    1.必须使用form表单的post提交请求
    2.form表单属性enctype="multipart/form-data"必须设置这样的值
    3.form表单里面必须有文件域表单项元素
  --%>
  <form action="${pageContext.request.contextPath}/upload/uploadFile" method="post" enctype="multipart/form-data">
      我在springMVC里配置了 静态资源访问 为啥还是访问不到

关于springMVC中静态文件路径问题

SpringMVC静态资源访问问题

springMVC如何访问静态文件

SpringMVC访问静态资源的三种方式

springMVC 下访问静态资源