SSM: mybatis + Spring + SpringMVC MVC 三层架构
MVC: 模型(Model)、视图(View)、控制器(Contrlooer)的简写,是一种软件设计规范

新建maven 父工程
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.liu</groupId>
    <artifactId>SpringMVC</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>springmvc-01-servlet</module>
    </modules>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
</project>
建立一个Moudle:springmvc-01-servlet , 添加Web app的支持!
导入servlet 和 jsp 的 jar 依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringMVC</artifactId>
        <groupId>com.liu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>springmvc-01-servlet</artifactId>
    <dependencies>
        <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>
    </dependencies>
</project>
HelloServlct
package com.liu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取参数
        String method = req.getParameter("method");
        if (method.equals("add")) {
            req.getSession().setAttribute("msg", "执行了Add方法");
        }
        if (method.equals("delete")) {
            req.getSession().setAttribute("msg", "执行了delete方法");
        }
        //调用业务层
        //视图转发活重定向
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
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>hello</servlet-name>
        <servlet-class>com.liu.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>
MVC框架要做哪些事情
常见服务器端MVC 框架:
常见 前端MVC框架:
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
查看官方文档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web
SpringMVC的特点
Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。 DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的
用户可以采用基于注解形式进行开发,十分简洁;
SpringMVC, 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于 配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦 截器 等等......

SpringMVC的原理如下所示


简要分析执行流程
Controller是一个接口,在org.springframework.web.servlet.mvc包下,接口中只有一个方法;
  //实现该接口的类获得控制器功能 public interface Controller {
  //处理请求且返回一个模型与视图对象
      ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
  }
  @Component   组件
  @Service     service
  @Controller controller
  @Repository  
用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT,PATCH, DELETE, TRACE等
Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以 及 PATCH。
所有的地址栏请求默认都会是 HTTP GET 类型的。
方法级别的注解变体有如下几个: 组合注解
  @GetMapping
  @PostMapping
  @PutMapping
  @DeleteMapping
  @PatchMapping
@GetMapping 是一个组合注解,它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一个快捷方式。
设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀}
  <!-- 视图解析器 -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  id="internalResourceViewResolver">
    <!-- 前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 后缀 -->
    <property name="suffix" value=".jsp" />
  </bean>
  public class ControllerTest1 implements Controller {
      public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
  HttpServletResponse httpServletResponse) throws Exception {
      //返回一个模型视图对象
      ModelAndView mv = new ModelAndView(); 
      mv.addObject("msg","ControllerTest1");
      mv.setViewName("test");
      return mv;
        } 
  }
通过设置ServletAPI , 不需要视图解析器 .
通过HttpServletResponse进行输出
通过HttpServletResponse实现重定向
通过HttpServletResponse实现转发
  @Controller
  public class ResultGoTest {
      @RequestMapping("/result/t1")
      public void test1(HttpServletRequest req, HttpServletResponse rsp)
              throws IOException {
          rsp.getWriter().println("Hello,Spring BY servlet API");
      }
  
      @RequestMapping("/result/t2")
      public void test2(HttpServletRequest req, HttpServletResponse rsp)
              throws IOException {
          rsp.sendRedirect("/index.jsp");
      }
  
      @RequestMapping("/result/t3")
      public void test3(HttpServletRequest req, HttpServletResponse rsp)
              throws Exception {
          //转发
          req.setAttribute("msg", "/result/t3");
          req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, rsp);
      }
  }
通过SpringMVC来实现转发和重定向 - 无需视图解析器;
package com.liu.controller;
public class TestController {
    @Controller
    public class ResultSpringMVC {
        @RequestMapping("/rsm/t1")
        public String test1() {
            //转发
            return "/WEB-INF/jsp/index.jsp";
        }
        @RequestMapping("/rsm/t2")
        public String test2() {
            //转发二
            return "forward:/WEB-INF/jsp/index.jsp";
        }
        @RequestMapping("/rsm/t3")
        public String test3() { 
            //重定向
            return "redirect:/WEB-INF/jsp/index.jsp";
        }
    }
}
提交的域名称和处理方法的参数名一致
处理方法 :
  @RequestMapping("/hello")
  public String hello(String name){
      System.out.println(name);
      return "hello";
  }
  输出 liunian
提交的域名称和处理方法的参数名不一致
处理方法 :
  //@RequestParam("username") : username??交的域的名称 . @RequestMapping("/hello")
  public String hello(@RequestParam("username") String name){
      System.out.println(name);
      return "hello";
  }
  
  输出 liunian
提交的是一个对象
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
实体类
  @Data
  public class User {
      private int id;
  	  private String name; 	
      private int age; //构造
  }
提交数据 : http://localhost:8080/mvc04/user?name=liunian&id=1&age=11
处理方法 :
  @RequestMapping("/user")
  public String user(User user){
      System.out.println(user);
      return "hello";
  }
  
  如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
第一种 : 通过ModelAndView
  package com.liu.controller;
  
  public class TestController {
      public class ControllerTest1 implements Controller {
          public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
                                            HttpServletResponse httpServletResponse) throws Exception {
              
              //返回一个模型视图对象
              ModelAndView mv = new ModelAndView();
              mv.addObject("msg", "ControllerTest1");
              mv.setViewName("test");
              return mv;
          }
      }
  }
第二种 : 通过ModelMap
modelMap 继承了LinkedHashMap,所以拥有了LinkedHashMap 的全部功能
model 是精简版,大部分使用了model
  package com.liu.controller;
  
  public class TestController {
      @RequestMapping("/hello")
      public String hello(@RequestParam("username") String name, ModelMap model) {
  //封装要显示到视图中的数据 //相当于req.setAttribute("name",name); 
          model.addAttribute("name", name);
          System.out.println(name);
          return "hello";
      }
  }
第三种 : 通过Model
  package com.liu.controller;
  
  public class TestController {
      @RequestMapping("/ct2/hello")
      public String hello(@RequestParam("username") String name, Model model) {
          //封装要显示到视图中的数据 
          // 相当于req.setAttribute("name",name); 
          model.addAttribute("msg", name);
          System.out.println(name);
          return "test";
      }
  }
乱码问题是在我们开发中十分常见的问题,也是让我们程序猿比较头大的问题!
以前乱码问题通过过滤器解决 , 而SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置 .
修改了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>
有些极端情况下.这个过滤器对get的支持不好 .
处理方法 :
修改tomcat配置文件 : 设置编码!
  <Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
             connectionTimeout="20000"
  redirectPort="8443" />
自定义过滤器
  package com.liu.controller;
  
  import javax.servlet.*;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletRequestWrapper;
  import javax.servlet.http.HttpServletResponse;
  import java.io.IOException;
  import java.io.UnsupportedEncodingException;
  import java.util.Map;
  
  public class GenericEncodingFilter implements Filter {
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
  
      }
  
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          //处理response的字符编码
          HttpServletResponse myResponse = (HttpServletResponse) response;
          myResponse.setContentType("text/html;charset=UTF-8");
          // 转型为与协议相关对象
          HttpServletRequest httpServletRequest = (HttpServletRequest) request;
          // 对request包装增强
          HttpServletRequest myrequest = new MyRequest(httpServletRequest);
          chain.doFilter(myrequest, response);
      }
  
      @Override
      public void destroy() {
  
      }
  }
  
  //自定义request对象,HttpServletRequest的包装类
  class MyRequest extends HttpServletRequestWrapper {
      private HttpServletRequest request;
      //是否编码的标记
      private boolean hasEncode; //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
  
      public MyRequest(HttpServletRequest request) {
          super(request);// super必须写
          this.request = request;
      }
  
      @Override
      public Map getParameterMap() {
          // 先获得请求方式
          String method = request.getMethod();
          if (method.equalsIgnoreCase("post")) {
              // post请求
              try {
                  // 处理post乱码
                  request.setCharacterEncoding("utf-8");
                  return request.getParameterMap();
              } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
              }
          } else if (method.equalsIgnoreCase("get")) {
              // get请求
              Map<String, String[]> parameterMap = request.getParameterMap();
              if (!hasEncode) { // 确保get手动编码逻辑只运行一次
                  for (String parameterName : parameterMap.keySet()) {
                      String[] values = parameterMap.get(parameterName);
                      if (values != null) {
                          for (int i = 0; i < values.length; i++) {
                              try {
                                  // 处理get乱码
                                  values[i] = new String(values[i].getBytes("ISO-8859-1"), "utf-8");
                              } catch (UnsupportedEncodingException e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                  }
                  hasEncode = true;
              }
              return parameterMap;
          }
          return super.getParameterMap();
      }
  
      @Override
      public String getParameter(String name) {
          Map<String, String[]> parameterMap = getParameterMap();
          String[] values = parameterMap.get(name);
          if (values == null) {
              return null;
          }
          return values[0]; // 取回参数的第一个值
      }
  
      //取所有值
      @Override
      public String[] getParameterValues(String name) {
          Map<String, String[]> parameterMap = getParameterMap();
          String[] values = parameterMap.get(name);
          return values;
      }
  }
  <filter>
         <filter-name>encoding</filter-name>
         <filter-class>com.liu.controller.GenericEncodingFilter</filter-class>
     </filter>
     <filter-mapping>
         <filter-name>encoding</filter-name>
         <url-pattern>/*</url-pattern>
     </filter-mapping>
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广 泛。
采用完全独立于编程语言的文本格式来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例 如字符串、数字、对象、数组等。看看他的要求和语法格式:
JSON 键值对是用来保存 JavaScript 对象的一种方式,和 JavaScript 对象的写法也大同小异,键/值对组 合中的键名写在前面并用双引号 "" 包裹,使用冒号 : 分隔,然后紧接着值:
  {"name": "lium"} 
  {"age": "3"}
  {"sex": "男"}
要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:
  varobj=JSON.parse(‘{"a":"Hello","b":"World"}‘);
要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:
  varjson=JSON.stringify({a:‘Hello‘,b:‘World‘});
Jackson应该是目前比较好的json解析工具了
当然工具不止这一个,比如还有阿里巴巴的 fastjson 等等。
这里使用Jackson,使用它需要导入它的jar包;
  <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.1</version>
  </dependency>
配置SpringMVC需要的配置
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">
      <!-- 配置 DispatchServlet -->
      <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>
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"
         xmlns:context="http://www.springframework.org/schema/context"
         xmlns:mvc="http://www.springframework.org/schema/mvc"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://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">
      <!-- 自动扫包,让指定包下的注解生效,由IOC容器统一管理 -->
      <context:component-scan base-package="com.liu.controller"/>
      <mvc:default-servlet-handler/>
  
      <!-- json 乱码问题解决 -->
      <mvc:annotation-driven>
          <mvc:message-converters register-defaults="true">
              <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                  <constructor-arg value="UTF-8"/>
              </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>
  
      <!-- 视图解析器 -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
          <!-- 前缀 -->
          <property name="prefix" value="/WEB-INF/jsp/"/>
          <!-- 后缀 -->
          <property name="suffix" value=".jsp"/>
      </bean>
  
      <!--    <bean name="/t1" class="com.liu.controller.ControllerTest1"/>-->
  </beans>
User的实体类,测试Controller
  package com.liu.pojo;
  
  import lombok.AllArgsConstructor;
  import lombok.Data;
  import lombok.NoArgsConstructor;
  
  @Data
  @AllArgsConstructor
  @NoArgsConstructor
  public class User {
      private String name;
      private int age;
      private String sex;
  }
  
一个是@ResponseBody,一个是ObjectMapper对象,我们看下具体 的用法
编写一个Controller;
  package com.liu.controller;
  
  import com.fasterxml.jackson.core.JsonProcessingException;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import com.fasterxml.jackson.databind.SerializationFeature;
  import com.liu.pojo.User;
  import com.liu.utils.JsonUtils;
  import org.springframework.stereotype.Controller;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.ResponseBody;
  import org.springframework.web.bind.annotation.RestController;
  
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.List;
  
  //@Controller  走视图解析器
  @RestController //不走视图解析器
  public class UserController {
  
      @RequestMapping(value = "/j1")
      public String json1() throws JsonProcessingException {
  
          ObjectMapper mapper = new ObjectMapper();
  
          User user = new User("lium", 3, "男");
          String s = mapper.writeValueAsString(user);
          return s;
      }
  
      @RequestMapping(value = "/j2")
      public String json2() throws JsonProcessingException {
  
          ObjectMapper mapper = new ObjectMapper();
  
          List<User> userList = new ArrayList<User>();
  
          User user1 = new User("lium1", 1, "男");
          User user2 = new User("lium2", 2, "女");
          User user3 = new User("lium3", 3, "男");
          User user4 = new User("lium4", 4, "女");
  
          userList.add(user1);
          userList.add(user2);
          userList.add(user3);
          userList.add(user4);
  
  //        String s = mapper.writeValueAsString(userList);
          return JsonUtils.getJson(userList);
      }
  
  
      @RequestMapping(value = "/j3")
      public String json3() throws JsonProcessingException {
  
  //        ObjectMapper mapper = new ObjectMapper();
  //        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
  //
  //        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  //        mapper.setDateFormat(sdf);
          Date date = new Date();
  
  //        String s = mapper.writeValueAsString(date);
          return JsonUtils.getJson(date, "yyyy-MM-dd HH:mm:ss");
      }
  }
  
  我们需要设置一下他的编码格式为utf-8,以及它返回的类型; 
  通过@RequestMaping的produces属性来实现,修改下代码
    @RequestMapping(value="/j1",produces="application/json;charset=utf-8")
package com.liu.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 JsonUtils {
    public static String getJson(Object object) {
        return getJson(object, "yyyy-MM-dd HH:mm:ss");
    }
    public static String getJson(Object object, String dateFormat) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        mapper.setDateFormat(sdf);
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转 换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法 很多,最后的实现结果都是一样的。
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>
fastjson 三个主要的类:
@RequestMapping(value = "/j4")
    public String json4() throws JsonProcessingException {
        List<User> userList = new ArrayList<User>();
        User user1 = new User("lium1", 1, "男");
        User user2 = new User("lium2", 2, "女");
        User user3 = new User("lium3", 3, "男");
        User user4 = new User("lium4", 4, "女");
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);
        String s = JSON.toJSONString(userList);
        return s;
    }
纯JS原生实现Ajax我们不去讲解这里,直接使用jquery提供的,方便学习和使用,避免重复造轮 子,有兴趣的同学可以去了解下JS原生XMLHttpRequest ! Ajax的核心是XMLHttpRequest对象(XHR)。XHR为向服务器发送请求和解析服务器响应提供了接 口。能够以异步方式从服务器获取新数据。
jQuery 提供多个与 A JAX 有关的方法。
通过 jQuery A JAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、 XML 或 JSON – 同时您能够把这些外部数据直接载入网页的被选元素中。
jQuery 不是生产者,而是大自然搬运工。
jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!
  jQuery.ajax(...)
    部分参数: url:请求地址
    	type:请求方式,GET、POST(1.9.0之后用method)
  		headers:请求头 data:要发送的数据
      contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded;charset=UTF-8")
      async:是否异步 timeout:设置请求超时时间(毫秒)
      beforeSend:发送请求前执行的函数(全局) complete:完成之后执行的回调函数(全局) success:成功之后执行的回调函数(全局) error:失败之后执行的回调函数(全局)
      accepts:通过请求头发送给服务器,告诉服务器当前客户端课接受的数据类型 dataType:将服务器端返回的数据转换成指定类型
      "xml": 将服务器端返回的内容转换成xml格式
      "text": 将服务器端返回的内容转换成普通文本格式
      "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含
      JavaScript标签,则会尝试去执行。
      "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成
      普通文本格式
      "json": 将服务器端返回的内容转换成相应的JavaScript对象
      "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?"
      jQuery 将自动替换 ? 为正确的函数名,以执行回调函数
配置web.xml 和 springmvc的配置文件【记得静态资源过滤和注解驱动配 置上】
  <?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
         http://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">
    
      <!-- 自动扫包,让指定包下的注解生效,由IOC容器统一管理 -->
      <context:component-scan base-package="com.liu.controller"/>
      <!--静态资源过滤-->
      <mvc:default-servlet-handler/>
      <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>
编写一个登陆页面 login.jsp
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
  <head>
      <title>登录页</title>
  </head>
  <body>
  <h1>登录页</h1>
  <form action="${pageContext.request.contextPath}/user/login" method="post">
      用户名:<input type="text" name="username">
      密码:<input type="text" name="password">
      <input type="submit" value="提交">
  </form>
  </body>
  </html>
  
编写一个Controller处理请求
  package com.liu.controller;
  
  import org.springframework.stereotype.Controller;
  import org.springframework.ui.Model;
  import org.springframework.web.bind.annotation.RequestMapping;
  
  import javax.servlet.http.HttpSession;
  
  @Controller
  @RequestMapping("/user")
  public class LoginController {
  
      @RequestMapping("/main")
      public String main() {
          System.out.println("aaaaaaaaaaaa");
          return "main";
      }
  
      @RequestMapping("/goLogin")
      public String login() {
          System.out.println("bbbbbbbbbbbb");
          return "login";
      }
  
      @RequestMapping("/login")
      public String login(HttpSession session, String username, String password, Model model) {
          session.setAttribute("userLoginInfo", username);
          model.addAttribute("username", username);
          return "main";
      }
  
      @RequestMapping("/goOut")
      public String goOut(HttpSession session) {
          session.removeAttribute("userLoginInfo");
          return "login";
      }
  
  }
编写一个登陆成功的页面 success.jsp
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
  <head>
      <title>首页</title>
  </head>
  <body>
  <h1>首页</h1>
  ${username}
  <p>
      <a href="${pageContext.request.contextPath}/user/goOut">注销</a>
  </p>
  </body>
  </html>
  
在 index 页面上测试跳转!启动Tomcat 测试,未登录也可以进入主页!
  <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
  <head>
      <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/user/goLogin">登录页</a>
  <a href="${pageContext.request.contextPath}/user/main">首页</a>
  </body>
  </html>
  
. 编写用户登录拦截器
  package com.liu.config;
  
  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 {
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          HttpSession session = request.getSession();
  
          if (request.getRequestURI().contains("goLogin")) {
              return true;
          }
          if (request.getRequestURI().contains("login")) {
              return true;
          }
  
  
          if (session.getAttribute("userLoginInfo") != null) {
              return true;
          }
  
          request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
          return false;
      }
  }
  
在Springmvc的配置文件中注册拦截器
  <?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
         http://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">
      <!-- 自动扫包,让指定包下的注解生效,由IOC容器统一管理 -->
      <context:component-scan base-package="com.liu.controller"/>
      <mvc:default-servlet-handler/>
  
      <!-- json 乱码问题解决 -->
      <mvc:annotation-driven>
          <mvc:message-converters register-defaults="true">
              <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                  <constructor-arg value="UTF-8"/>
              </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>
  
      <!-- 视图解析器 -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
          <!-- 前缀 -->
          <property name="prefix" value="/WEB-INF/jsp/"/>
          <!-- 后缀 -->
          <property name="suffix" value=".jsp"/>
      </bean>
  
      <!--拦截器配置-->
      <mvc:interceptors>
          <mvc:interceptor>
              <!--包括这个请求下的所有请求-->
              <mvc:mapping path="/**"/>
              <bean class="com.liu.config.MyInterceptor"/>
          </mvc:interceptor>
          <mvc:interceptor>
              <!--包括这个请求下的所有请求-->
              <mvc:mapping path="/user/**"/>
              <bean class="com.liu.config.LoginInterceptor"/>
          </mvc:interceptor>
      </mvc:interceptors>
  </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">
      <!-- 配置 DispatchServlet -->
      <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:applicationContext.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>
文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上 下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring 的文件上传功能,则需要在上下文中配置MultipartResolver。
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为 multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;
对表单中的 enctype 属性做个详细的说明:
application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编 码方式的表单会将表单域中的值处理成 URL 编码方式。
multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文 件域指定文件的内容也封装到请求参数中,不会对字符编码。
text/plain:除了把空格转换为 "+" 号外,其他字符都不做编码处理,这种方式适用直接通过表单 发送邮件。
  <form action="" enctype="multipart/form-data" method="post">
      <input type="file" name="file"/>
      <input type="submit">
  </form>
一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对 于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation 发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
  <dependencies>
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>
applicationContext.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://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">
    <!-- 自动扫包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.liu.controller"/>
    <mvc:default-servlet-handler/>
    <!-- json 乱码问题解决 -->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </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>
    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--文件上传配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容, 默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/> <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
</beans>
Controller
package com.liu.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.http.HttpServletRequest;
import java.io.*;
@Controller
public class FileController {
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //获取文件名 :file.getOriginalFilename();
        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 is = file.getInputStream(); //文件输入流
        OutputStream os = new FileOutputStream(new File(realPath, uploadFileName)); //文件输出流
        //读取写出
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
    /*
     * 采用file.Transto 来保存上传的文件 */
    @RequestMapping("/upload2")
    public String fileUpload2(@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";
    }
}
 @RequestMapping(value = "/download")
    public String downloads(HttpServletResponse response, HttpServletRequest request) throws Exception {
        //要下载的图片地址
        String path = request.getServletContext().getRealPath("/upload");
        String fileName = "qqq.jpg";
        //1、设置response 响应头
        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);
        //2、 读取文件--输入流
        InputStream input = new FileInputStream(file); //3、 写出文件--输出流
        OutputStream out = response.getOutputStream();
        byte[] buff = new byte[1024];
        int index = 0;
        //4、执行 写出操作
        while ((index = input.read(buff)) != -1) {
            out.write(buff, 0, index);
            out.flush();
        }
        out.close();
        input.close();
        return null;
    }
原文:https://www.cnblogs.com/LiuMiao1128/p/14411356.html