springMVC笔记

导入依赖

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.22</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>

第一个springMVC

这里主要是为了探究原理,使用配置版,在实际开发工作中sprinmvc会使用注解开发

1.配置web.xml,注册DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">


    <!--注册dispatcherServlet-->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--关联springmvc配置文件,因为这个servlet要从配置文件中拿到-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!--设置启动级别为1-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--匹配所有的请求:/ (不包含请求到 XX.jsp)
                     /*  (包含请求到  XX.jsp)   -->
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

2.配置springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--处理映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--视图解析器,这个解析器是将响应给前端的方法中加上对应的前后缀拼接成一个完整的路径,这样代码层面我们可以专注写方法名字而不用管路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

3.操作业务controller,这里要么实现接口controller,要么增加注解。该类返回一个ModalAndView封装数据和视图

package com.zhong.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //new一个模型和视图对象
        ModelAndView mv = new ModelAndView();
        //封装对象
        mv.addObject("msg","helloSpringMVC!");
        //封装要跳转的视图
        mv.setViewName("hello");//由于配置了视图解析器,这个名字会被加上前缀后后缀,再通过转发或者重定向
        return mv;//返回这个模型和视图对象
    }
}

4.将这个类托管给spring的IOC容器

<!--Handelr-->
<bean id="/hello" class="com.zhong.controller.HelloController"/>

springMVC执行流程

springMVC中有一个核心控制器DispatcherServlet,它负责分发调度各种外部或者内部的请求。它本身不需要我们在applicationContext中注册,本质是是一个spring内部封装好的servlet,只需要在web.xml中注册拦截所有的请求。它的内部有三个重要的引用对象,分别是处理映射器(BeanNameUrlHandlerMapping)、处理适配器(SimpleControllerHandlerAdapter)、视图解析器(InternalResourceViewResolver),因为是Java的类,所以需要交给springIOC容器托管,在applicationContext中注册。

1.首先DispatcherServlet会把拦截到的请求交给处理映射器(BeanNameUrlHandlerMapping),它会解析请求,拿到请求中最后一个字段例如(/hello)。然后通过这个字段去匹配name或者id寻找一个控制器(handler),找到这个控制器之后通过HandlerExecution解析它的信息,再把解析后的信息返回给DispatcherServlet。

2.DispatcherServlet拿到HandlerExecution解析之后的信息后传递给处理适配器(SimpleControllerHandlerAdapter),由于可能是通过name解析的信息,所以可能接收的信息中不止一个handler,处理适配器会根据这些信息去适配一个合适handler,适配成功之后调用里面的方法去执行业务层代码。执行完毕会封装成一个ModelAndView返回给处理适配器,处理适配器将这个ModelAndView返回给DispatcherServlet。

3.DispatcherServlet拿到ModelAndView之后,传递给视图解析器(InternalResourceViewResolver)解析ModelAndView里面的信息。视图解析器把解析过后的逻辑视图名(也就是完整的路径)拿到之后,把ModelAndView中的数据渲染到视图中(也就是把数据set进request中或者session中让jsp能够拿到数据)然后把逻辑视图名传递给DispatcherServlet

4.DispatcherServlet拿到逻辑视图名之后,响应给用户。

注解开发

springmvc-servlet.xml

<?xml ve	rsion="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--包扫描,让包底下的类中的注解生效-->
    <context:component-scan base-package="com.zhong.controller"/>
    <!--让springMVC不处理静态资源,过滤掉css、js等文件-->
    <mvc:default-servlet-handler />

    <!--
        支持mvc注解驱动
        自动完成处理映射器和处理适配器的实例注入
        类中使用@RequestMappering
    -->

    <mvc:annotation-driven />

    <!--视图解析器,这个解析器是将响应给前端的方法中加上对应的前后缀拼接成一个完整的路径,这样代码层面我们可以专注写方法名字而不用管路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

HelloController.java

package com.zhong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/123")//这里会出现多级目录首先进入/123
public class HelloController {

    @RequestMapping("/hello")//从/123中请求hello才能请求到这个方法(一般只使用方法上的注解而不使用类上的注解)
    public String hello(Model model) {
        //封装数据
        model.addAttribute("msg", "helloController");
        return "hello";//会被视图解析器处理,就是拼接的路径
    }
}

RestFul风格

这是一种改变我们传参风格的方式,在传统前端传递参数中,参数会跟着地址栏后边以英文问好的形式进行传递(?a=2)。看起来不够美观。RestFul风格就改变了这一种传递参数的形式,使其变成了以/来传递参数的形式。

要使用RestFul风格,要在Controller类的方法下的参数中添加注解@PathVariabl。然后将@RequestMapping(/add/{a})设置成这样(a为参数名)即可从url中取出参数。

我们可以在@RequestMapping中设置请求的方式,@RequestMapping(value=“/add/{a}, method=RequestMethod.GET”),但一般不使用这种方式,而是使用一种衍生的注解@GetMapping(“/add/{a}”)来实现

重定向和转发

springMVC中有两种方式进行请求转发和重定向,当然,servletAPI的重定向和转发也可以使用,但需要在方法参数中加上request和respond

方式一

就是使用视图解析器,return一个页面的名字,使用视图解析器的前缀后后缀来拼接上完整的路径。默认都是转发,重定向需要加上redirect:,重定向是不会走视图解析器的

方式二

不需要视图解析器,只使用return “/index.jsp”,默认就是转发,重定向return "redirect:/index.jsp "

数据处理

当前后端传递参数名不一致的情况下,在方法参数前使用@RequestParam(“前端提交参数名”)一般用于表单更多,它不能和RestFul风格混用

当前端的参数名和实体类的属性名一致的时候,参数会自动的注入到对象中

携带参数返回前端,ModelAndView、ModelMap、Model

ModelAndView

返回的是该变量本身,视图名是在保存在该变量中的。

ModelMap

也是Model的父类,可以说Model是该类的精简版

Model

直接返回需要转发的视图名,或者使用重定向

乱码问题

在传统的web开发中使用request中的setcharacterEncoding设置为utf-8即可解决乱码问题,这是因为所有的参数都是从request中拿到的。但是在springmvc开发中,参数是直接从前端拿到的,在方法的参数中拿到,那么setcharacterEncoding设置为utf-8就无法改变参数编码问题了,这种传统的方法失效了。

于是我们使用过滤器的方式解决乱码问题

<!--过滤器-->
<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>com.zhong.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
package com.zhong.filter;

import javax.servlet.*;
import java.io.IOException;

public class CharacterEncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");

        filterChain.doFilter(servletRequest, servletResponse);

    }

    public void destroy() {

    }
}

spring MVC中也给我们写好了一个过滤器来解决乱码问题,我们可以在web。xml中配置上即可使用

<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

JSON

js对象,是一种轻量级的数据交换格式,是一种纯文本格式

jackson

导入依赖

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.4</version>
</dependency>

固定配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--包扫描,让包底下的类中的注解生效-->
    <context:component-scan base-package="com.zhong.controller"/>
    <!--让springMVC不处理静态资源,过滤掉css、js等文件-->
    <mvc:default-servlet-handler />

    <!--
        支持mvc注解驱动
        自动完成处理映射器和处理适配器的实例注入
        类中使用@RequestMappering
    -->

    <mvc:annotation-driven />

    <!--视图解析器,这个解析器是将响应给前端的方法中加上对应的前后缀拼接成一个完整的路径,这样代码层面我们可以专注写方法名字而不用管路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>
package com.zhong.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhong.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {

    //响应体注解不会进入视图解析器
    @ResponseBody
    //@RequestMapping("/j1")但是这样返回去的json中文是乱码的
    //我们可以这样使用,用原生是spring的方式解决json乱码问题
    @RequestMapping(value = "j1", produces = "application/json;charset=utf-8")//但是每次都要配置乱码会比较麻烦,spring配置文件中可以配置来解决乱码问题
    public String json1() throws JsonProcessingException {
        //创建一个对象
        User user = new User("中", 3, "1");

        //jackson里有一个objectmap类型
        ObjectMapper mapper = new ObjectMapper();
        String s = mapper.writeValueAsString(user);
        return s;
    }
}

在spring-servlet中的mvc注解驱动配置上json乱码解决

<!--json乱码配置-->
<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8"></constructor-arg>
        </bean>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="failOnEmptyBeans" value="false"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

使用@RestController可以不用每个方法上都加上响应体注解,加上了这个注解的类中的所有方法都只会返回字符串。

封装时间json

@ResponseBody
@RequestMapping("/j2")
public String json2() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    Date date = new Date();

    //自定义日期格式
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String format = simpleDateFormat.format(date);
    String s = mapper.writeValueAsString(format);
    return s;
}

还有一种方式关闭mapper中的时间戳

@ResponseBody
@RequestMapping("/j2")
public String json2() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    //关闭时间戳方式
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    //自定义日期格式
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    mapper.setDateFormat(simpleDateFormat);
    Date date = new Date();
    String s = mapper.writeValueAsString(date);
    return s;
}

此外,我们还可以自己封装我们的json,让controller方法中直接拿到一个json

package com.zhong.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.text.SimpleDateFormat;

public class JsonUtil {

    public static String getJson(Object object) {
        String json = getJson(object, null);
        return json;
    }

    public static String getJson(Object object, String simpleDateFormat) {
        ObjectMapper mapper = new ObjectMapper();

        /*针对日期json的优化*/
        if (simpleDateFormat != null) {
            mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            SimpleDateFormat sdf = new SimpleDateFormat(simpleDateFormat);
            mapper.setDateFormat(sdf);
        }
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

FastJson

阿里巴巴开发的json工具,它可以做到Javabean和json之间的转换

导入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

开箱即用,非常简单

AJAX

ajax是一种局部刷新网页的技术,这里使用jquery里的ajax

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
    <script>

      function a() {
        $.post({
          url:"${pageContext.request.contextPath}/a1",//请求后后端地址
          data:{"name":$("#userName").val()},//传递参数json键值对
          success:function (data) {//成功回调函数,拿到后端返回数据
            alert(data);
          }
        })
      }

    </script>
  </head>
  <body>
  $END$
<%--onblur失去焦点事件--%>
  用户名:<input type="text" id="userName" onblur="a()">
  </body>
</html>
package com.zhong.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@RestController
public class AjaxController {
    @RequestMapping("/a1")
    public void a1(String name, HttpServletResponse httpServletResponse) throws IOException {
        if ("123".equals(name)) {
            httpServletResponse.getWriter().print("true");
        }else {
            httpServletResponse.getWriter().print("false");
        }
    }
}

局部刷新数据

@RequestMapping("/a2")
public List<User> a2() throws IOException {
    List<User> list = new ArrayList<User>();
    list.add(new User("1", 1, "1"));
    list.add(new User("2", 1, "1"));
    list.add(new User("3", 1, "1"));

    return list;
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
    <script>
        $(function () {
            $("#btn").click(function (){
                /*简写方式*/
                $.post("${pageContext.request.contextPath}/a2",function (data) {
                    // console.log(data);
                    var html;
                    for (let i = 0; i < data.length; i++) {
                        html += "<tr>" +
                            "<td>" + data[i].name + "</td>" +
                            "<td>" + data[i].age + "</td>" +
                            "<td>" + data[i].sex + "</td>" +
                            "</tr>"
                    }
                    /*jquery取标签元素,并插入html标签*/
                    $("#contend").html(html);
                })
            })
        });
    </script>
</head>
<body>
<input type="button" value="加载数据" id="btn">
<table>
    <tr>
        <td>姓名</td>
        <td>年龄</td>
        <td>性别</td>
    </tr>
    <tbody class="container" id="contend">
        
    </tbody>
</table>

</body>
</html>

ajax验证登陆

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.js"></script>
    <script>
        function a1() {
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{
                    "name":$("#name").val()
                },
                success:function (data) {
                    if (data.toString()==='ok') {
                        $("#userInfo").css("color", "green");
                    }else {
                        $("#userInfo").css("color", "red");
                    }
                    $("#userInfo").html(data)
                },
                error:function () {

                }
            })
        };
        function a2() {
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{
                    "pwd":$("#pwd").val()
                },
                success:function (data) {
                    if (data.toString()==='ok') {
                        $("#pwdInfo").css("color", "green");
                    }else {
                        $("#pwdInfo").css("color", "red");
                    }
                    $("#pwdInfo").html(data)
                },
                error:function () {

                }
            })
        }
    </script>
</head>
<body>
<p>
    用户名: <input type="text" id="name" οnblur="a1()">
    <span id="userInfo"></span>
</p>
<p>
    密码:<input type="password" id="pwd" οnblur="a2()">
    <span id="pwdInfo"></span>
</p>

</body>
</html>
package com.zhong.controller;

import com.zhong.pojo.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class AjaxController {

    @RequestMapping("/a3")
    public String a3(String name, String pwd) {
        String msg = "";
        if (name != null) {
            if ("admin".equals(name)) {
                msg = "ok";
            }else {
                msg = "用户名不为admin";
            }
        }
        if (pwd != null) {
            if ("123456".equals(pwd)) {
                msg = "ok";
            }else {
                msg = "密码不为123456";
            }
        }
        return msg;
    }
}

springMVC拦截器

springmvc拦截器和servlet中的过滤器类似,不同的是,过滤器过滤所有请求,拦截器只会拦截控制器中的方法。拦截器是AOP思想的具体实现

package com.zhong.controller;


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("t1")
    public String test() {
        return "OK";
    }
}
package com.zhong.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 MyInterceptor implements HandlerInterceptor {

    //return true就是放行的意思,要么进入下一个拦截器,要么直接进入应用本身
    //return false会把请求拦截到这里
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入方法前,拦截");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("方法调用后");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("清理");
    }
}

spring-mvc.xml

<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.zhong.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

登陆拦截

package com.zhong.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        if (request.getRequestURI().contains("toLogin")) {
            return true;
        }
        if (request.getRequestURI().contains("login")) {
            return true;
        }
        if (session.getAttribute("userName")!=null) {
            return true;
        }
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
}
package com.zhong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

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

    @RequestMapping("/main")
    public String main() {
        return "main";
    }

    @RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

    @RequestMapping("/login")
    public String login(HttpSession session, String userName, String password) {

        session.setAttribute("userName", userName);

        return "main";
    }
}
<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>
        <bean class="com.zhong.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

文件上传

我们可以使用文件上传来显示一些文件的图片等

依赖

<!--文件上传,需要高版本servlet-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

同样的文件上传在spring中也有支持

spring-mvc.xml

<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--请求的编码格式, 必须和jsp的encoding编码一致才可以正确读取表单内容-->
    <property name="defaultEncoding" value="utf-8"/>
    <!--设置文件上传的大小上限,单位为字节 10485760=10m-->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>

两种方式任选其一

package com.zhong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

@RestController
public class FileController {

    /*方式一*/
    //@RequestParam("file")这个注解是将表单提交的数据中的name为“file”的数据封装成一个CommonsMultipartFile对象
    //如果过批量上传则把CommonsMultipartFile类型改为CommonsMultipartFile[]
    @RequestMapping("upload")
    public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

        //获取上传的文件名
        String uploadFileName = file.getOriginalFilename();

        //如果上传的文件名为空,返回首页
        if ("".equals(uploadFileName)) {
            return "redirect:index.jsp";
        }
        System.out.println("上传文件名:"+uploadFileName);

        //上传保存路径设置
        String Path = request.getServletContext().getRealPath("/upload");
        //如果路径不存在,则创建该路径
        File realPath = new File(Path);
        if (!realPath.exists()) {
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);

        InputStream inputStream = file.getInputStream();//文件输入流
        FileOutputStream fileOutputStream = new FileOutputStream(new File(realPath, uploadFileName));//文件输出流

        //读取写出
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len=inputStream.read(buffer))!=-1) {
            fileOutputStream.write(buffer, 0, len);
            fileOutputStream.flush();
        }
        fileOutputStream.close();
        inputStream.close();
        return "redirect:/index.jsp";

    }

    /*方式二*/
    @RequestMapping("/upload2")
    public String upload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

        //上传保存路径设置
        String Path = request.getServletContext().getRealPath("/upload");
        //如果路径不存在,则创建该路径
        File realPath = new File(Path);
        if (!realPath.exists()) {
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);

        //通过CommonsMultipartFile内部封装好的方法直接写文件
        file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));

        return "redirect:/index.jsp";
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" name="upload">
  </form>
  </body>
</html>

文件下载

package com.zhong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

@RestController
public class FileController {
    /*文件下载*/
    @RequestMapping(value = "/download")
    public String download(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //要下载的图片地址
        String path = request.getServletContext().getRealPath("/upload");
        String fileName = "image-20220904090444409.png";

        //设置响应头
        response.reset();//设置页面不缓存,清空buffer
        response.setCharacterEncoding("UTF-8");//设置编码
        response.setContentType("multipart/form-data");//二进制传输数据

        response.setHeader("Content-Disposition", "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));

        File file = new File(path, fileName);
        //读取文件
        FileInputStream fileInputStream = new FileInputStream(file);
        //写出文件
        ServletOutputStream outputStream = response.getOutputStream();

        //读取写出
        int index = 0;
        byte[] buffer = new byte[1024];
        while ((index=fileInputStream.read(buffer))!=-1) {
            outputStream.write(buffer, 0, index);
            outputStream.flush();
        }
        outputStream.close();
        fileInputStream.close();
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值