美文网首页
SpringMVC的笔记

SpringMVC的笔记

作者: JasonChen8888 | 来源:发表于2019-11-28 17:21 被阅读0次

    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>
    

    相关文章

      网友评论

          本文标题:SpringMVC的笔记

          本文链接:https://www.haomeiwen.com/subject/dunbwctx.html