SpringMVC的笔记

SpringMVC的笔记

MVC

  • M 代表 模型(Model)
    模型就是数据,如:dao,bean
  • V 代表 视图(View)
    视图就是数据的可视化的表现,如:网页,JSP,用来展示模型中的数据
  • C 代表 控制器(Controller)
    控制器就是作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开

SpringMVC的核心类和接口

  • DispatcherServlet -- 前置控制器
    提供SpringWebMVC的集中访问点,而且负责职责的分派,而且与spring IOC容器无缝集成,从而可以获得Spring的优势

  • HandlerMapping接口 -- 处理请求的映射
    HandlerMapping接口的实现类:
    SimpleUrlHandlerMapping 通过配置文件,把一个URL映射到Controller
    DefaultAnnotationHandlerMapping 通过注解,把一个URL映射到Controller类上

  • HandlerAdapter接口 -- 处理请求的映射
    AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上

  • Controller接口 -- 控制器
    由于我们使用了@Controller注解,添加了@Controller注解注解的类就可以担任控制器(Action)的职责,
    所以我们并没有用到这个接口。

  • HandlerInterceptor 接口--拦截器
    无图,我们自己实现这个接口,来完成拦截的器的工作。

  • ViewResolver接口的实现类
    UrlBasedViewResolver类 通过配置文件,把一个视图名交给到一个View来处理
    InternalResourceViewResolver类,比上面的类,加入了JSTL的支持

SpringMVC原理图

SpringMVC原理图

DispatcherServlet说明

使用Spring MVC,配置DispatcherServlet是第一步。
DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。
注:“某某规则”是根据你使用了哪个HandlerMapping接口的实现类的不同而不同。
栗子:使用默认配置文件名

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>Archetype Created Web Application</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

<load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servletp容器一起启动。
<url-pattern>/</url-pattern>会拦截根目录下的请求。
<servlet-name>example</servlet-name>这个Servlet的名字是dispatcher,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。
在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。按照上述代码会生成dispatcher--servlet.xml 的配置文件
栗子:不适用默认配置文件名

<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.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>

指明了配置文件的文件名,不使用默认配置文件名,而使用springMVC.xml配置文件。
其中<param-value>**.xml</param-value> 这里可以使用多种写法
1、不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
2、<param-value>/WEB-INF/classes/springMVC.xml</param-value>
3、<param-value>classpath*:springMVC-mvc.xml</param-value>
4、多个值用逗号分隔

拦截规则

当映射为@RequestMapping("/user/add")时,为例:
1、拦截.do、.htm, 例如:/user/add.do
这是最传统的方式,最简单也最实用。不会导致静态文件(jpg,js,css)被拦截。
2、拦截/,例如:/user/add
可以实现现在很流行的REST风格。很多互联网类型的应用很喜欢这种风格的URL。
弊端:会导致静态文件(jpg,js,css)被拦截后不能正常显示。想实现REST风格,事情就是麻烦一些。后面有解决办法还算简单。
3、拦截/*,这是一个错误的方式,请求可以走到Action中,但转到jsp时再次被拦截,不能访问到jsp。

如何访问到静态的文件,如jpg,js,css?

1、在web.xml文件中配置以下,若还有其他后缀文件仿照写配置代码。

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
</servlet-mapping>

2、css文件所在的文件夹若在WEB-INF目录下,把它放到Webapp(或WebRoot)目录下。

Servlet的配置文件

<?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:tx="http://www.springframework.org/schema/tx"
    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-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <!-- 自动扫描的包名 -->
    <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan>

    <!-- 默认的注解映射的支持 -->
    <mvc:annotation-driven />

    <!-- 视图解释类 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑  -->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    </bean>

    <!-- 拦截器 -->
    <mvc:interceptors>
        <bean class="com.core.mvc.MyInteceptor" />
    </mvc:interceptors>

    <!-- 对静态资源文件的访问  方案一 (二选一) -->
    <mvc:default-servlet-handler/>

    <!-- 对静态资源文件的访问  方案二 (二选一)-->
    <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
    <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>
    <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/>

</beans>

<context:component-scan/> 扫描指定的包中的类上的注解,常用的注解有:
@Controller 声明Action组件
@Service 声明Service组件 @Service("myMovieLister")
@Repository 声明Dao组件
@Component 泛指组件, 当不好归类时.
@RequestMapping("/menu") 请求映射
@Resource 用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name="beanName")
@Autowired 用于注入,(srping提供的) 默认按类型装配
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope("prototype") 设定bean的作用域

<mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。
并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。
后面,我们处理响应ajax请求时,就使用到了对json的支持。
后面,对action写JUnit单元测试时,要从spring IOC容器中取DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,来完成测试,取的时候要知道是<mvc:annotation-driven />这一句注册的这两个bean。

<mvc:interceptors/> 是一种简写形式。通过看前面的大图,知道,我们可以配置多个HandlerMapping。<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。其实我们也可以手动配置为每个HandlerMapping注入一个拦截器。

<mvc:default-servlet-handler/> 使用默认的Servlet来响应静态文件。

<mvc:resources mapping="/images/" location="/images/" cache-period="31556926"/> 匹配URL /images/ 的URL被当做静态资源,由Spring读出到内存中再响应http。

请求如何映射到具体的Action中的方法

方案一:基于xml配置映射,可以利用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping进行Url映射和拦截请求。
配置方法略。

方案二:基于注解映射,可以使用DefaultAnnotationHandlerMapping。

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">

但前面我们配置了<mvc:annotation-driven />,他会自动注册这个bean,就不须要我们显示的注册这个bean了。
以上都可以注入interceptors,实现权限控制等前置工作。
我们使用第2种,基于注解来使用spring MVC
并在action类上使用:
@Controller
@RequestMapping("/user")

Spring中的拦截器

参考资料:spring中的拦截器(HandlerInterceptor+MethodInterceptor)
spring为我们提供了:
org.springframework.web.servlet.HandlerInterceptor接口和
org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器(也是实现了HandlerInterceptor接口的抽象类)
实现这个接口或继承此类,可以非常方便的实现自己的拦截器。

接口或者抽象类有以下三个方法:

Action之前执行:
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler);

生成视图之前执行
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView);

最后执行,可用于释放资源
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)

分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
参数中的Object handler是下一个拦截器。

栗子:
拦截器MyInterceptor1 实现HandlerInterceptor接口

package com.jason.web.springdemo.intercptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("Class MyInterceptor1 --> method preHandle executed!");
        System.out.println("Interceptor method : "+ httpServletRequest.getMethod());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("Class MyInterceptor1 --> method postHandle executed!");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("Class MyInterceptor1 --> method afterCompletion executed!");
    }
}

拦截器MyInterceptor2 继承抽象类HandlerInterceptorAdapter

package com.jason.web.springdemo.intercptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

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

public class MyInterceptor2 extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Class MyInterceptor2 --> method preHandle executed!");
        System.out.println("Interceptor method : "+ request.getMethod());
        return super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Class MyInterceptor2 --> method postHandle executed!");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Class MyInterceptor2 --> method afterCompletion executed!");
    }
}

servlet中的配置

    <mvc:interceptors>
        <!--拦截器1-->
        <mvc:interceptor>
            <!--配置拦截器的作用路径-->
            <mvc:mapping path="/api/user/*"/>
            <!--定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截-->
            <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1"/>
        </mvc:interceptor>
        <!--拦截器2-->
        <mvc:interceptor>
            <mvc:mapping path="/api/show"/>
            <bean class="com.jason.web.springdemo.intercptor.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

深入了解

Spring MVC并没有总的拦截器,不能对所有的请求进行前后拦截。
Spring MVC的拦截器,是属于HandlerMapping级别的,可以有多个HandlerMapping ,每个HandlerMapping可以有自己的拦截器。
当一个请求按Order值从小到大,顺序执行HandlerMapping接口的实现类时,哪一个先有返回,那就可以结束了,后面的HandlerMapping就不走了,本道工序就完成了。就转到下一道工序了。
拦截器会在什么时候执行呢? 一个请求交给一个HandlerMapping时,这个HandlerMapping先找有没有处理器来处理这个请求,如何找到了,就执行拦截器,执行完拦截后,交给目标处理器。
如果没有找到处理器,那么这个拦截器就不会被执行。

在spring MVC的配置文件中配置有三种方法:

  • 方案一,(近似)总拦截器,拦截所有url:
<mvc:interceptors>   
    <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1" />   
</mvc:interceptors>  

为什么叫“近似”,前面说了,Spring没有总的拦截器。
<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。总有一个HandlerMapping是可以找到处理器的,最多也只找到一个处理器,所以这个拦截器总会被执行的。起到了总拦截器的作用。如果是REST风格的URL,静态资源也会被拦截。

  • 方案二,(近似) 总拦截器, 拦截匹配的URL:
<mvc:interceptors >
  <mvc:interceptor>
        <mvc:mapping path="/api/user/*" /> <!-- /api/user/*  -->
        <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1"></bean>
    </mvc:interceptor>
</mvc:interceptors>

比 方案一多了一个URL匹配。如果是REST风格的URL,静态资源也会被拦截。

  • 方案三,HandlerMappint上的拦截器
    我们精准的注入了拦截器,这样就算是REST风格的URL,静态资源就不会被拦截
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
  <property name="interceptors">
     <list>
       <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1"></bean>
     </list>
  </property>
</bean>

如果使用了<mvc:annotation-driven />, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。
当然我们可以通过人工配置上面的两个Bean,不使用 <mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了

全局的异常处理

springMVC提供的异常处理主要有两种方式,一种是直接实现自己的HandlerExceptionResolver,当然这也包括使用Spring已经为我们提供好的SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver,另一种是使用注解的方式实现一个专门用于处理异常的Controller——ExceptionHandler。

  • Spring默认的实现配置
    Springmvc的servlet文件配置添加如下:
<!-- 默认的实现类注入 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 为所有的异常定义默认的异常处理页面,exceptionMappings未定义的异常使用本默认配置 -->
        <property name="defaultErrorView">
            <!-- exceptionMapping没有对应的值,则返回默认的异常视图error.jsp -->
            <value>error</value>
        </property>
        <!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
        <property name="exceptionAttribute" value="ex"></property>
        <!--
    定义需要特殊处理的异常,用类名或完全路径名作为key,异常页文件名作为值,
    将不同的异常映射到不同的页面上。
   -->
        <property name="exceptionMappings">
            <props>
                <!-- 表示当抛出NumberFormatException的时候就返回名叫number的视图 -->
                <prop key="NumberFormatException">number</prop> <!-- 对应 number.jsp -->
                <prop key="NullPointerException">error</prop> <!-- 对应 error.jsp -->
            </props>
        </property>

        <property name="statusCodes"><!-- 定义在发生异常时视图跟返回码的对应关系 -->
            <props>
                <!-- 表示在发生NumberFormatException时返回视图number,然后这里定义发生异常时视图number对应的HttpServletResponse的返回码是500 -->
                <prop key="number">500</prop>
                <prop key="error">503</prop>
            </props>
        </property>
        <!-- 表示在发生异常时默认的HttpServletResponse的返回码是多少,默认是200 -->
        <property name="defaultStatusCode" value="404"/>
    </bean>
  • 实现HandlerExceptionResolver接口自定义异常处理
public class CustomExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        if (e instanceof NumberFormatException) {
            return new ModelAndView("number");
        } else if (e instanceof NullPointerException) {
            return new ModelAndView("error");
        }
        return null;
    }
}
  • 调用测试例子测试上面的两种异常处理的做法
@Controller
@RequestMapping("/api")
public class ApiController {
    @RequestMapping("/null")
    public void testNullPointerException() {
        User user = null;
        //这里就会发生空指针异常,然后就会返回定义在SpringMVC配置文件中的null视图
        System.out.println(user.getCode());
    }

    @RequestMapping("/number")
    @ResponseBody
    public int testNumberFormatException() {
        //这里就会发生NumberFormatException,然后就会返回定义在SpringMVC配置文件中的number视图
        Integer.parseInt("abc");
        return 1;
    }

    @RequestMapping("/default")
    public void testDefaultException() {
        if (1==1)
            //由于该异常类型在SpringMVC的配置文件中没有指定,所以就会返回默认的exception视图
            throw new RuntimeException("Error!");
    }
}
  • 使用注解实现异常处理
@Controller
public class GlobalController {

    /**
     * 用于处理异常的
     * @return
     */
    @ExceptionHandler({MyException.class})
    public String exception(MyException e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
        return "exception";
    }

    @RequestMapping("test")
    public void test() {
        throw new MyException("出错了!");
    }

}

异常处理方式的优先级

既然在SpringMVC中有两种处理异常的方式,那么就存在一个优先级的问题:

当发生异常的时候,SpringMVC会如下处理:
(1)SpringMVC会先从配置文件找异常解析器HandlerExceptionResolver
(2)如果找到了异常异常解析器,那么接下来就会判断该异常解析器能否处理当前发生的异常
(3)如果可以处理的话,那么就进行处理,然后给前台返回对应的异常视图
(4)如果没有找到对应的异常解析器或者是找到的异常解析器不能处理当前的异常的时候,就看当前的Controller中有没有提供对应的异常处理器,如果提供了就由Controller自己进行处理并返回对应的视图
(5)如果配置文件里面没有定义对应的异常解析器,而当前Controller中也没有定义的话,那么该异常就会被抛出来。

转发和重定向

请求转发是服务器内部的跳转
  地址栏会发生变化
  只有一个请求相应
  可以通过request域对跳转目标的请求

请求重定向是浏览器自动发起对跳转目标的请求
  地址栏会发生变化
  两次请求相应
  无法通过request域传递对象

/**
 * 实现转发
 */
@RequestMapping("/hello11.action")
public String hello11(HttpServletRequest request){
   request.setAttribute("name", "cjj");
   return "forward:hello.action";
}

/**
 * 实现重定向
 */
@RequestMapping("/hello12.action")
public String hello12(HttpServletRequest request){
  request.setAttribute("name", "cjj");
  return "redirect:/hello.action";
}

带参数重定向--RedirectAttributes

用户保存或修改后,为了防止用户刷新浏览器(F5)导致表单重复提交,一般在保存或修改操作之后会redirect到一个结果页面(不是forward),同时携带参数,如操作成功的提示信息。因为是Redirect,Request里的attribute不会传递过去。Spring在3.1才提供了这个能力--RedirectAttributes。 反复按F5,操作成功的提示信息也不会再次出来(总共只出现一次),效果很理想。

public String save(@ModelAttribute("group") Group group, RedirectAttributes redirectAttributes) {
    accountManager.saveGroup(group);
    redirectAttributes.addFlashAttribute("message", "操作成功");
    return "redirect:/account/group/";
}

SpringMVC的ajax的使用

实现一个文件上传的例子
servlet的配置,需要增加一个 上传文件的拦截器(文件解析器)CommonsMultipartResolver

<!-- 文件解析器 id 不能缺少,而且一定要是multipartResolver  这个值,不然会出现Controller无法获取到上传的文件对象-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <!-- 上传文件大小上限,单位为字节(100MB) -->
     <property name="maxUploadSize">
         <value>104857600</value>
     </property>
     <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
     <property name="defaultEncoding">
         <value>UTF-8</value>
     </property>
</bean>

uploadForm.jsp的代码:

<%--
  Created by IntelliJ IDEA.
  User: JasonChen
  Date: 2019/10/31
  Time: 10:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <!-- jQuery  -->
    <script src="../js/jquery-3.2.1.min.js"></script>
<%--    <script type="text/javascript" src="../static/jquery-3.4.1.jar"></script>--%>

    <meta http-equiv="Content-Type" content="multipart/form-data; charset=utf-8" />
    <title>文件上传</title>
</head>
<body>
<h2>文件上传</h2>
<form  id="tf"  enctype="multipart/form-data">
    <table>
        <tr>
            <td>文件描述:</td>
            <td><input type="text" name="description" id="description"></td>
        </tr>
        <tr>
            <td>请选择文件:</td>
            <td><input type="file" id="file" name="file"></td>
        </tr>
        <tr>
            <td><input type="button" value="上传" onclick="test()"></td>
        </tr>
    </table>
</form>

<script >
    function test(){
        alert("file upload starting")
        var form = document.getElementById("tf");
        var formData = new FormData(form);
        var file = formData.get('file');
        var description = formData.get('description');
        var fileBean = {
            'upFile':file,
            'desc':description
        }
        console.log(file);
        console.log(description);
        $.ajax({
            url:"upload",
            type:"POST",
            data:formData,
            processData:false,
            contentType:false,
            success:function(data){
                if(data=="1"){
                    alert("上传成功")
                }else {
                    alert("上传失败")
                }
            },
            error:function (xhr) {
                alert("错误提示: " + xhr.status + " " + xhr.statusText)
            }
        });
    }

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

Controller的代码:

    @RequestMapping("/uploadPage")
    public ModelAndView uploadPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("111111111111111");
        ModelAndView mv = new ModelAndView();
        mv.setViewName("/uploadForm");
        return mv;
    }

    @RequestMapping(value = "/upload"/*,headers = "content-type=multipart/*", method = RequestMethod.POST*/)
    @ResponseBody
    public String uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
        //存在问题:无法识别@RequestParam这个注解在jsp对应的属性
        System.out.println(file);
        if (file != null && !file.isEmpty()) {
            //上传文件路径
            String path = "E://images/";

            System.out.println(path);

            //上传的文件名
            String fileName = file.getOriginalFilename();
            File fileDest = new File(path, fileName);

            //判断文件要存储的目录是否存在
            if (!fileDest.getParentFile().exists()) {
                fileDest.getParentFile().mkdirs();
            }

            //将上传的文件保存到目标目录中
            String destPath = path + File.separator + fileName;
            file.transferTo(new File(destPath));

            System.out.println(destPath);
            return "1";
        }
        return "0";
    }

SpringMVC + MyBatis + MySQL

实现了一个Springmvc 结合MyBatis + MySQL的例子
以项目以先构建SpringMVC的基础上结合 MyBatis
pom的需要的依赖

<!-- J2EE -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</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>

        <!--springframework-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.github.stefanbirkner</groupId>
            <artifactId>system-rules</artifactId>
            <version>1.16.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>

        <!--其他需要的包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>

        <!--添加java对象注解转json支持-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.8.5</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.9.8</version>
            <scope>compile</scope>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

web.xml 的配置:

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <display-name>Archetype Created Web Application</display-name>
    <!-- spring 默认的配置文件 applicationContext.xml -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 配置servlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--  以下是 不使用默认配置文件名 - dispatcher servlet -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/springMVC.xml</param-value>
        </init-param>

        <load-on-startup>2</load-on-startup>
    </servlet>

    <!-- dispatcher Mapping (缺点:对不同格式文件需要增加配置) -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/.jsp</url-pattern>
    </servlet-mapping>

    <!-- SpringMVC 静态资源CSS,JS访问不了的方法,同时静态文件不能放在WEB-INF的目录下 -->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>

    <!-- springMVC Mapping -->
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.jason.web.springdemo.controller">
        <!-- 如果service和controller在同一个父包中,在扫描父包的时候需要使用该句进行排除,springmvc中同样需要排除 -->
        <!-- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    </context:component-scan>

    <!--默认注解支持-->
    <mvc:annotation-driven>
    </mvc:annotation-driven>
    <!-- 自己编写配置 替代<mvc:annotation-driven> 的自动注册DefaultAnnotationHandlerMapping这个bean -->
    <!--<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="interceptors">
            <list>
                <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1"></bean>
            </list>
        </property>
    </bean>-->
    <!--指定视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 视图的路径 -->
        <property name="prefix" value="/views/"/>
        <!-- 视图名称后缀  -->
        <property name="suffix" value=".jsp"/>
    </bean>

    <mvc:default-servlet-handler/>

    <!-- 文件解析器 id 不能缺少,而且一定要是multipartResolver  这个值,不然会出现Controller无法获取到上传的文件对象-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 上传文件大小上限,单位为字节(100MB) -->
        <property name="maxUploadSize">
            <value>104857600</value>
        </property>
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
        <property name="defaultEncoding">
            <value>UTF-8</value>
        </property>
    </bean>
    <!-- 自定义的实现类 -->
<!--    <bean id="exceptionHandler" class="com.jason.web.springdemo.exception.CustomExceptionHandler"/>-->

    <!-- 配置全局异常的处理 -->
    <!-- 默认的实现类注入 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 为所有的异常定义默认的异常处理页面,exceptionMappings未定义的异常使用本默认配置 -->
        <property name="defaultErrorView">
            <value>error</value> <!-- exceptionMapping没有对应的值,则返回默认的异常视图error.jsp -->
        </property>
        <!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
        <property name="exceptionAttribute" value="ex"></property>
        <!--
    定义需要特殊处理的异常,用类名或完全路径名作为key,异常页文件名作为值,
    将不同的异常映射到不同的页面上。
   -->
        <property name="exceptionMappings">
            <props>
                <!-- 表示当抛出NumberFormatException的时候就返回名叫number的视图 -->
                <prop key="NumberFormatException">number</prop>
                <prop key="NullPointerException">error</prop>
            </props>
        </property>

        <property name="statusCodes"><!-- 定义在发生异常时视图跟返回码的对应关系 -->
            <props>
                <!-- 表示在发生NumberFormatException时返回视图number,然后这里定义发生异常时视图number对应的HttpServletResponse的返回码是500 -->
                <prop key="number">510</prop>
                <prop key="error">503</prop>
            </props>
        </property>
        <!-- 表示在发生异常时默认的HttpServletResponse的返回码是多少,默认是200 -->
        <property name="defaultStatusCode" value="404"/>
    </bean>

    <!--<mvc:default-servlet-handler/>-->

<!--    <mvc:interceptors>-->
<!--        &lt;!&ndash;拦截器1&ndash;&gt;-->
<!--        <mvc:interceptor>-->
<!--            &lt;!&ndash;配置拦截器的作用路径&ndash;&gt;-->
<!--            <mvc:mapping path="/api/user/*"/>-->
<!--            &lt;!&ndash;定义在<mvc:interceptor>下面的表示匹配指定路径的请求才进行拦截&ndash;&gt;-->
<!--            <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1"/>-->
<!--        </mvc:interceptor>-->
<!--        &lt;!&ndash;拦截器2&ndash;&gt;-->
<!--        <mvc:interceptor>-->
<!--            <mvc:mapping path="/api/show"/>-->
<!--            <bean class="com.jason.web.springdemo.intercptor.MyInterceptor2"/>-->
<!--        </mvc:interceptor>-->
<!--    </mvc:interceptors>-->
    <!-- 默认拦截总的URL -->
    <mvc:interceptors>
        <bean class="com.jason.web.springdemo.intercptor.MyInterceptor1"/>
    </mvc:interceptors>

</beans>

Spring配置文件applicationContext.xml: 主要是配置 数据库属性文件配置、数据库Datasource配置、会话配置、扫描数据读写接口配置、数据库事务配置

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

    <context:component-scan base-package="com.jason.web.springdemo.service">
        <!-- Spring希望管理所有的业务逻辑组件,不包含controller -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <context:property-placeholder location="db.properties"/>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- 基本属性 url,user,pass -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!-- 配置初始化大小,最小增长,最大活动连接 -->
        <property name="initialSize" value="${jdbc.initialSize}"/>
        <property name="minIdle" value="${jdbc.minIdle}"/>
        <property name="maxIdle" value="${jdbc.maxIdle}" />
        <property name="maxActive" value="${jdbc.maxActive}"/>
        <!-- 获取连接超时时间,单位毫秒 -->
        <property name="maxWait" value="60000"/>

        <!-- 设置间隔多久进行一次检查关闭空闲链接,单位毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="30000"/>

        <!-- 设置每个连接在池中的最小生存时间,单位毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="30000"/>
    </bean>

    <!--
            整合mybatis
                目的:1、spring管理所有组件。mapper的实现类。
                        service==>Dao   @Autowired:自动注入mapper;
                      2、spring用来管理事务,spring声明式事务
    -->
    <!-- spring事务管理 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 开启基于注解的事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--创建出SqlSessionFactory对象  -->
    <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 加载mybatis核心配置文件 -->
        <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
        <!-- 别名包扫描 -->
        <property name="typeAliasesPackage" value="com.jason.web.springdemo.bean"></property>
        <!--mapperLocations: 指定mapper文件的位置-->
        <property name="mapperLocations" value="classpath:com/jason/web/springdemo/mapper/*.xml"></property>
    </bean>

    <!-- Mapper接口所在包名,Spring会自动查找其下的类 -->
    <bean id="mapperScannerConfig" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.jason.web.springdemo.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>
    <!-- 扫描所有的mapper接口的实现,让这些mapper能够自动注入;
        base-package:指定mapper接口的包名
         -->
    <mybatis-spring:scan base-package="com.jason.web.springdemo.mapper"/>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="del*" propagation="REQUIRED"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="upd*" propagation="REQUIRED"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:advisor advice-ref="txAdvice"
                     pointcut="execution(* com.jason.web.springdemo.service.*.*(..))" />
    </aop:config>
</beans>

MySQL数据库配置文件:db.properties

#数据库连接
jdbc.driver=com.mysql.cj.jdbc.Driver
#数据库连接
jdbc.url=jdbc:mysql://localhost:3306/testdb?serverTimezone=GMT
#数据库用户名
jdbc.username=root
#数据库密码
jdbc.password=Chen388321
#定义初始连接数
jdbc.initialSize=0
#定义最大连接数
jdbc.maxActive=20
#定义最大空闲
jdbc.maxIdle=20
#定义最小空闲
jdbc.minIdle=1

用到的数据库表:


用到的数据库表

MyBatis的原理图


MyBatis的原理图.png

对应数据库表的实体类

package com.jason.web.springdemo.bean;

public class Student {

    Integer id;
    String name;
    String sex;
    String date;
    String content;

    public Student() {
    }

    public Student(Integer id, String name, String sex, String date, String content) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.date = date;
        this.content = content;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

编写mapper接口:StudentMapper.java

package com.jason.web.springdemo.mapper;

import com.jason.web.springdemo.bean.Student;
import org.apache.ibatis.annotations.Param;

public interface StudentMapper {

    Student getStudentById(@Param("id") int id);

    Student getStudentByName(@Param("name") String name);
}

编写mapper文件:StudentMapper.xml 注:mapper接口和对应的映射文件的名称要一致

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jason.web.springdemo.mapper.StudentMapper">
    <select id="getStudentById" resultType="com.jason.web.springdemo.bean.Student">
        select * from student where id = #{id}
    </select>

    <select id="getStudentByName" resultType="com.jason.web.springdemo.bean.Student">
        select * from student where name = #{name}
    </select>
</mapper>

创建service层:
接口:

package com.jason.web.springdemo.service;

import com.jason.web.springdemo.bean.Student;
import org.springframework.stereotype.Service;

@Service
public interface StudentService {

    Student getStudentById(int id);

    Student getStudentByName(String name);
}

实现类:

package com.jason.web.springdemo.service;

import com.jason.web.springdemo.bean.Student;
import com.jason.web.springdemo.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentMapper studentMapper;

    @Override
    public Student getStudentById(int id) {
        System.out.println("id = "+id);
        if(studentMapper != null) {
            return studentMapper.getStudentById(id);
        }
        return null;
    }

    @Override
    public Student getStudentByName(String name) {
        try{
            System.out.println("name = "+name);
            if(studentMapper != null) {
                System.out.println("Start query database...");
                return studentMapper.getStudentByName(name);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}

编写控制器的调用:

package com.jason.web.springdemo.controller;

import com.jason.web.springdemo.bean.Person;
import com.jason.web.springdemo.bean.Student;
import com.jason.web.springdemo.service.StudentService;
import com.jason.web.springdemo.utils.JsonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.List;

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

    @Autowired
    StudentService studentService;

    @RequestMapping(value = "/toLogin", method = RequestMethod.GET)
    public String toLogin() {
        return "login";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(Person person) {
        if (10025 == person.getPid() && "123".equals(person.getPwd())) {
            return "redirect:queryAll";
        } else {
            return "login";
        }
    }

    @RequestMapping(value = "/queryAll", method = RequestMethod.GET)
    public ModelAndView queryAll() {
        ModelAndView mav = new ModelAndView("show");
        List<Person> list = new ArrayList<Person>();
        list.add(new Person(10025, "tom", "123"));
        list.add(new Person(10026, "jakson", "123"));
        list.add(new Person(10027, "nikly", "123"));
        mav.addObject("list", list);
        return mav;
    }

    @RequestMapping("/ajax")
    @ResponseBody
    public String ajax(Person person) {
        if(studentService != null) {
            Student student = studentService.getStudentByName("aa");
            if(student != null) {
                System.out.println(JsonUtil.object2Json(student));
            }
        }
        System.out.println(person.getPid() + person.getPwd());
        if (123 == person.getPid() && "123".equals(person.getPwd())) {
            return "1";
        } else {
            return "0";

        }

    }

    @RequestMapping(value = "/ajax2")
    @ResponseBody
    public String ajax2(String loginData) {
        System.out.println(loginData);
        if (loginData != null && !loginData.isEmpty()) {
            System.out.println("true");
            return "1";
        } else {
            System.out.println("false");
            return "0";

        }

    }
}

视图层的jsp代码:

<%--
  Created by IntelliJ IDEA.
  User: JasonChen
  Date: 2019/10/31
  Time: 17:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=utf-8"
         pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Insert title here</title>
</head>
<script type="text/javascript" src="../js/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
    $(function(){
        $("#sub").click(function(){
            var form = document.getElementById("myForm");
            var formData = new FormData(form);
            var pid = formData.get("pid");
            var pwd = formData.get("pwd");
            var str = pid+","+pwd;
            alert(pid+","+pwd);
            var person = {'pid':'123','pname':'Tom','pwd':'123'};
            $.ajax({
                url:"ajax",
                type:"POST",
                dataType: 'json',
                data:person,
                success:function(data){
                    if(data == '1'){
                        alert("登录成功");
                        location.href="queryAll";
                    }else {
                        alert("请核对用户名和密码");
                    }
                },
                error:function (xhr) {
                    alert("错误提示: " + xhr.status + " " + xhr.statusText)
                }
            });
        })
    })
</script>
<body>
<form  method="post" id="myForm">
    <table border="1" width="300px">
        <tr>
            <td>帐号</td>
            <td><input type="text" name="pid"/></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="pwd"/></td>
        </tr>
        <tr>
            <!-- <td colspan="2"><input type="submit" value="提交"/></td> -->
            <td colspan="2"><input type="button" value="提交" id="sub"/></td>
        </tr>
    </table>
</form>

</body>
</html>

运行 http://localhost:8080/SpringDemo_war/user/toLogin,在调用登录的时候,ajax的请求去查询数据库的数据

结果

出现的错误

  • Loading class com.mysql.jdbc.Driver. This is deprecated. The new driver class is com.mysql.cj.jdbc.Driver.
    解决:将com.mysql.jdbc.Driver,修改为com.mysql.cj.jdbc.Driver

  • IntelliJ Idea解决Could not autowire. No beans of 'xxxx' type found的错误提示
    解决:spring auto scan配置,在编辑情况下,无法找不到对应的bean,于是提示找不到对应bean的错误。常见于mybatis的mapper,如下:添加如下配置

<!-- mapper scanner configurer -->
<bean id="mapperScannerConfig" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.jason.web.springdemo.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
  • mybatis配置时出现org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
    解决:在项目pom文件下的<build>标签下天际filter
<resources>
    <resource>
        <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        <filtering>true</filtering>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        <filtering>true</filtering>
    </resource>
</resources>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容

  • 对于java中的思考的方向,1必须要看前端的页面,对于前端的页面基本的逻辑,如果能理解最好,不理解也要知道几点。 ...
    神尤鲁道夫阅读 804评论 0 0
  • 前文 刚刚入职,项目大范围的使用到了 Spring + SpringMVC + MyBatis 框架,对于一个 J...
    琦小虾阅读 11,667评论 0 7
  • Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和...
    Java小辰阅读 1,077评论 0 14
  • IOC 控制反转容器控制程序对象之间的关系,而不是传统实现中,有程序代码之间控制,又名依赖注入。All 类的创建,...
    irckwk1阅读 934评论 0 0
  • 第一次见到你的时候 是18年六月吧 被你隔壁家的美容院给拉到你们店里理发 好奇怪哦 那个美容院夹在两家理发店中间 ...
    君晓墨阅读 131评论 0 2