SpringMVC框架

SpringMVC框架

第一章SpringMVC概述

1.1 SpringMVC基本说明

SpringMVC是基于spring的,是spring中的一个模块,做web开发使用的,springmvc叫做spring web mvc说明他是spring的核心技术,做web开发,springmvc内部是使用mvc架构模式。

springMVC是一个容器,管理对象的,使用IOC核心技术。springmvc管理界面层中的控制器对象。

springMVC底层也是Servlet。以Servlet为核心,接受请求,处理请求。显示处理结果给用户。

处理用户的请求:

用户发起请求-----SpringMVC-----Spring-----Dao-----MyBatis-----MySQL数据库

1.2 SpringMVC中的核心Servlet–DispatcherServlet

DispatcherServlet是框架一个servlet对象。负责接收请求,响应处理结果。

DispatcherServlet的父类是HttpServlet

DispatcherServlet也叫做前端控制器(front controller)。

SpringMVC是管理控制器对象,原来没有SpringMVC之前使用Servlet作为控制器对象使用。现在通过SpringMVC容器创建一种叫做控制器的对象,代替Servlet行使控制器的角色。功能。

SpringMVC主要使用注解的方式,创建控制器对象,处理请求。

web.xml

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <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>*.do</url-pattern>
  </servlet-mapping>
</web-app>

springmvc.xml

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

    <!--springmvc的配置文件-->
    <!--声明组件扫描器-->
    <context:component-scan base-package="com.cs.controller"/>
</beans>

controller

package com.cs.controller;

import com.sun.jmx.snmp.SnmpUnknownModelLcdException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * @Controller:创建控制器对象
 * 控制器:叫做后端控制器,自定义的类处理请求
 * 位置:在类的上面,表示创建此类的对象,对象放在springmvc的容器中
 */

@Controller
public class MyController {
    /**
     * @RequestMapping:请求映射
     * 属性:value 请求中的url地址,唯一值,以“/”开头
     * 位置:在方法上(必须的)在类上面
     * 作用:把指定的请求,交给指定的方法处理,等同于url-pattern
     * @return:ModelAndView表示本次请求的处理结果(数据和视图)
     * Model:表示数据
     * View:表示视图
     */
    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(){
        //使用该方法处理请求,能处理请求的方法叫做控制器方法
        System.out.println("执行了MyController的doSome方法");
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","处理了some.do请求");
        mv.addObject("fun","执行了doSome方法");
        //指定显示数据的视图,视图的完整路径
        mv.setViewName("/show.jsp");
        //返回结果
        return mv;
    }
}

show.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page  isELIgnored="false"%>
<html>
<head>
    <title>show</title>
</head>
<body>
/show.jsp,显示request作用域中的数据<br/>
<h3>msg数据:${msg}</h3>
<h3>fun数据:${fun}</h3>
</body>
</html>

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>第一个springmvc</title>
</head>
<body>
<a href="some.do">发起some.do的请求</a>
</body>
</html>

1.3 SpringMVC请求的处理过程

简单的处理过程:

用户发起请求some.do----->Tomcat接受了请求----->DispatcherServlet----->分配MyController(doSome()返回mv对象)----->mv显示给用户了。

1.4

用户发起some.do—DispatcherServlet(Servlet接受请求)—转给MyController

public class DispatcherServlet extends HttpServlet{
    public void service(HttpServletRequest request,HttpServlet response){
        if("some.do".equals(request.getURL())){
            //从容器中获取MyController
            MyController c = ctx.getBean("some");
            c.doSome();
        }else if("other.do".equals(request.getURL())){
            OtherController c = ctx.getBean("other");
            c.doOther();
        }
    }
}

1.5 web开发中配置文件的说明

  1. web.xml部署描述符文件,给服务器(tomcat)

    作用:服务器在启动的时候,读取web.xml,根据文件中的声明创建各种对象,根据文件中的声明知道请求和servlet等对象的关系。

  2. 框架的配置文件:springmvc的配置文件

    作用:声明框架创建的项目中的各种对象,主要是创建Controller对象的

配置文件的加载顺序和功能

  1. tomcat服务器启动,读取web.xml.根据web.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>*.do</url-pattern>
      </servlet-mapping>
    

    创建DispatcherServlet的对象,会执行init方法,在init方法中会执行springmvc容器对象创建WebApplicationContext ctx = new ClassPathXmlApplicationContext(“classpath:springmvc.xml”)

  2. springmvc框架,new ClassPathXmlApplicationContext() 读取springmvc的配置文件

     <!--springmvc的配置文件-->
        <!--声明组件扫描器-->
        <context:component-scan base-package="com.cs.controller"/>
        <!--视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/view/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    

    使用组件扫描器base-package=“com.cs.controller”,遍历controller包中的所有类,MyController类,找到这个类中的@Controller,@RequestMapping注解,就能创建MyController对象。知道some.do的请求是执行doSome()方法

    以上1,2都是项目启动的过程,没有执行任何的用户请求

  3. 用户发起请求some.do—DispatcherServlet

    DispatcherServlet里面有WebApplicationContext。WebApplicationContext里面有MyController对象。

    请求some.do,DispatcherServlet就知道是MyController处理的。

第二章 SpringMVC注解式开发

2.1 @RequestMapping注解的使用

@RequestMapping:请求映射

属性:value 请求中的url地址,唯一值,以“/”开头
位置:在方法上(必须的)在类上面作为模块名称

作用:把指定的请求,交给指定的方法处理,等同于url-pattern

@Request(value = "/some.do",method = RequestMethod.POST)
public ModelAndView doOther(){}

对请求提交方式的定义

序号请求方式提交方式
1表单请求默认GET,可以指定POST
2Ajax请求默认GET,可以指定POST
3地址栏请求GET请求
4超链接请求GET请求
5src资源路径请求GET请求

2.2 接收请求中的参数

对应HttpServletRequest,HttpServletResponse,HttpSession只需要在控制器方法的形参列表中,定义就可以了,框架会给参数赋值,在控制器方法内可以直接使用request,response,session参数。

400:http status,表示客户端异常。主要是发生在用户提交参数过程中。

接收请求中的参数:逐个接收,对象接收

2.2.1 逐个接收

逐个接收:请求中的参数名和控制器方法的形参名一样。按照名称对应接受参数

<p>逐个接收请求参数</p>
<form action="receive-property.do" method="post">
    姓名:<input type="text" name="name"/><br/>
    年龄:<input type="text" name="age"/><br/>
    <input type="submit" value="提交参数">
</form>

Controller接收参数

 @RequestMapping(value = "/receive-property.do")
    public ModelAndView doPropertyParam(String name,Integer age){

2.2.2 接收参数的问题

  1. 参数最好使用包装类型,例如Integer,能接收空值情况,接受的是null

  2. 框架可以使用String到int,long,float,double等类型转换

  3. post请求中有乱码的问题,使用字符集过滤器

    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
          <param-name>encoding</param-name>
          <param-value>utf-8</param-value>
        </init-param>
        <!--强制请求(request)对象使用encoding的编码格式-->
        <init-param>
          <param-name>forceRequestEncoding</param-name>
          <param-value>true</param-value>
        </init-param>
        <!--强制应答(response)对象使用encoding的编码格式-->
        <init-param>
          <param-name>forceResponseEncoding</param-name>
          <param-value>true</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!--强制所有请求,先经过过滤器处理-->
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

2.2.3 请求中参数名和形参名不一样,使用@RequestParam

    /* 形参值与请求值不一致
     * @RequestParam:解决名称不一致问题
     * 属性:value 请求中的参数名称
     *       required boolean类型的,默认是true
     *           true:请求中必须有此参数,没有报错
     *           false:请求中可以没有此参数。
     * 位置:在形参定义的前面
     */
    @RequestMapping(value = "/receive-param.do")
    public ModelAndView doReceiveParam(@RequestParam(value = "rname",
                                                     required = false) String name,
                                       @RequestParam(value = "rage",
                                                     required = false) Integer age)

2.2.4 对象接收

对象接收:在控制器方法的形参是java对象,使用java对象的属性接收请求中的参数值

要求:java对象的属性值名和请求中的参数名一样

例子:

public class Student {
    private String name;
    private Integer age;
    //ser|get方法
    
    
  @RequestMapping(value = "/receive-object.do")
    public ModelAndView doReceiveObject(Student student){  
        System.out.println("执行了MyController的doReceiveObject方法"+student);
        ModelAndView mv = new ModelAndView();
        mv.addObject("myname",student.getName());
        mv.addObject("myage",student.getAge());
        mv.setViewName("show");
        return mv;
    }

2.3 控制器方法的返回值

控制器方法的返回值表示本次请求的处理结果,返回值有ModelAndView,String,void,Object

请求的处理结果包含:数据和视图

2.3.1 ModelAndView数据和视图

请求结果有数据和视图,使用MOdelAndView最方便

数据:存放request作用域

视图:执行forward转发操作

2.3.2 String视图

框架对返回值是string,执行的是forward转发操作

视图可以表示为完整视图路径,或者视图的逻辑名称

@RequestMapping(value = "/return-string-view.do")
    public String doReturnStringView(HttpServletRequest request,String name, Integer age){
        System.out.println("执行了MyController的doReturnStringView="+ name +",age=" + age);
        //返回结果,forward,转发到show.jsp
        //逻辑名称,需要配置视图解析器
        request.setAttribute("myname",name);
        request.setAttribute("myage",age);
        return "show";
    }



@RequestMapping(value = "/return-string-view2.do")
    public String doReturnStringView2(HttpServletRequest request,String name, Integer age){
        System.out.println("执行了MyController的doReturnStringView2="+ name +",age=" + age);
        request.setAttribute("myname",name);
        request.setAttribute("myage",age);
        //完整视图路径,不能使用视图解析器
        return "/WEB-INF/view/show.jsp";
    }

2.3.3 void 没有数据和视图

void:没有数据和视图,可以使用HttpServletResponse对象输出数据,响应ajax请求。

   /**
     * 控制器方法返回时void,响应ajax请求,使用HttpServletResponse输出数据
     */
    @RequestMapping("/return-void-ajax.do")
    public void returnVoidAjax(HttpServletResponse response,String name, Integer age) throws IOException {
        System.out.println("处理void返回类型,name="+ name + ",age=" + age);
        //调用service得到结果对象
        Student student = new Student();
        student.setName(name + "同学");
        student.setAge(age);

        //把对象转为json
        ObjectMapper om  =  new ObjectMapper();
        String json = om.writeValueAsString(student);
        System.out.println("服务器端对象转为的json===="+json);

        //输出json,响应ajax
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw = response.getWriter();
        pw.println(json);
        pw.flush();
        pw.close();
    }
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>请求方式</title>
    <script type="text/javascript" src="js/jquery-1.12.4.js"></script>
    <script type="text/javascript">
        $(function () {
            //绑定事件
            $("#btnAjax").on("click",function () {
               $.ajax({
                   url: "return-void-ajax.do",
                   data: {
                       name:"lisi",
                       age:20
                   },
                   dataType:"JSON",
                   success:function(resp){
                       alert("resp=="+resp.name+"==="+resp.age);
                   }
               })
            })
        })
    </script>
</head>
<body>
<button id="btnAjax">发起ajax请求</button>
</body>
</html>

2.3.4 Object

返回Student表示数据,还是视图。所以控制器方法返回对象Object,用来响应ajax请求

返回对象Object,可以是List,Student,Map,String,Integer…这些都是数据,而ajax请求需要的就是数据。在ajax请求中,一般需要从服务器返回的是json格式的数据,经常要处理java对象到json的转换,而且还需要输出数据响应ajax请求。框架提供了处理java对象到json转换,还是数据输出工作。

2.3.4.1 HttpMessageConverter消息转换器

HttpMessageConverter接口,作用是:

1)实现请求的数据转为java对象

2)把控制器方法返回的对象转为json,xml,text,二进制等不同格式的数据。

public interface HttpMessageConverter<T> {
    /**
    作用:检查var1这个类型的对象,能否转为mediayType表示的数据格式
         如果能转为var2表示的类型,返回true,返回true调用read()
    */
    boolean canRead(Class<?> var1, @Nullable MediaType var2);

    boolean canWrite(Class<?> var1, @Nullable MediaType var2);

    List<MediaType> getSupportedMediaTypes();

    T read(Class<? extends T> var1, HttpInputMessage var2) throws IOException, HttpMessageNotReadableException;

    void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
}

默认情况下:springmvc使用了HttpMessageConveter接口的4个实现类。包括了StringHttpMessageConverter

需要在springmvc的配置文件中,加入注解驱动的标签mvc:annotation-driven.加入这个标签后,springmvc项目启动后,会创建HttpMessageConverter接口的7个实现类对象,包括StringHttpMessageConverter和Mappingglackson2HttpMessageConverter。

2.3.4.2 @ResponseBody

@ResponseBody注解的作用,就是把student转换后的json通过HttpServletResponse对象输出给浏览器。

//输出json,响应ajax
        response.setContentType("application/json;charset=utf-8");
        PrintWriter pw = response.getWriter();
        pw.println(json);
        pw.flush();
        pw.close();

 @ResponseBody注解作用就是上面代码的实现
2.3.4.3 控制器方法返回对象转为的步骤
  1. pom.xml加入jackson依赖,springmvc框架,默认处理json就是使用jackson
  2. 在springmvc的配置文件中,加入注解驱动的标签mvc:annotation-driven
  3. 在控制器方法的上面加入@ResponseBody注解,表示返回值数据输出到浏览器。

2.4 静态资源处理

2.4.1 tomcat的default servlet

tomcat安装目录/conf/web.xml

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

default叫做默认servlet,作用:
1、它提供静态资源的处理
2、它处理所有未映射到其他请求的请求过程

2.4.2 中央调度器设置“/”

使用斜杠“/”,导致中央调度器成为了默认的default servlet。

需要处理静态资源和其他的未映射的请求。默认中央调度器没有处理

静态资源的控制器对象,所以静态资源都是404。some.do这个请求有MyController对象,所以能访问

如果项目中,中央调度器设置了“/“,动态资源能访问,静态资源不能访问。

需要处理静态资源的访问工作。

2.4.3 第一种方式处理静态资源

在springmvc的配置文件中加入mvc:default-servlet-handler标签,springmvc框架会在项目运行时,加入DefaultServletHttpRequestHandler对象,让这个对象处理静态资源的访问

<!--springmvc的配置文件-->
    <!--声明注解驱动
    default-servlet-handler和@RequestMapping使用有冲突
    -->
    <mvc:annotation-driven/>

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--声明静态资源的第一种处理方式-->
    <mvc:default-servlet-handler/>

优点:解决方式简单

缺点:依赖tomcat服务器提供的能力。

2.4.4 第二种静态资源的处理方式

在springmvc配置文件中加入一个mvc:resources标签,框架会创建ResourcesHttpRequestHandler控制器对象,使用这个对象处理静态资源的访问。不依赖tomcat服务器。推荐使用。

<!--springmvc的配置文件-->
    <!--声明注解驱动
    default-servlet-handler和@RequestMapping使用有冲突
    -->
    <mvc:annotation-driven/>

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--声明静态资源的第二种处理方式mapping:访问静态资源的url地址,可以使用通配符(**)
        **:表示任意的目录和目录的资源名称
        location:静态资源在项目中的位置,不要使用/WEB-INF目录
-->
    <mvc:resources mapping="/static/**" location="/static/"/>

2.5 JSR303校验

数据校验:如何校验?注解?

  1. 使用JSR303验证标准
  2. 加入hibernate validator验证框架
  3. 在springmvc配置文件中添加
  4. 需要在bean的属性上添加对应的注解
  5. 在目标方法bean类型的前面添加@Valid注解

验证出错转向哪一个页面?

错误消息如何显示,如何把错误消息进行国际化

2.6 RestFul风格

RestFul就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

功能

  • 资源:互联网所有的事物都可以被抽象为资源
  • 资源操作:使用POST DELETE、PUT、GET,使用不同方法对资源进行操作。
  • 分别对应添加,删除,修改,查询。

传统方式操作资源:通过不同的参数来实现不同的效果!方法单一,post和get

  • http://127.0.0.1/item/queryItem.action?id=1查询,GET
  • http://127.0.0.1/item/saveItem.action新增,POST
  • http://127.0.0.1/item/updateItem.action更新,POST
  • http://127.0.0.1/item/deleteItem.action?id=1删除,GET或POST

**使用RestFul操作资源:**可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同

  • http://127.0.0.1/item/1查询,GET
  • http://127.0.0.1/item新增,POST
  • http://127.0.0.1/item更新,PUT
  • http://127.0.0.1/item/1删除,DELETE

测试

@Controller
public class MyController {
    @RequestMapping("/index.do/{a}/{b}")
    public String restful(@PathVariable int a,@PathVariable int b, Model model){
        int res = a+b;
        model.addAttribute("msg","结果为:"+ res);
        return "test";
    }
}

2.7 json

2.7.1 jackson

加入依赖

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.10.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.10.0</version>
    </dependency>

需要注意使用ObjectMapper对象需要使用jackson2.10.0以上的版本

@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
    @ResponseBody
    public String json() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        User user = new User("小艾1号", 3, "男");
        String string = objectMapper.writeValueAsString(user);
        return string;
    }

乱码问题解决

  1. 在注解@RequestMapping中加入参数produces = “application/json;charset=utf-8”

  2. 在配置文件中加入:

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

手写一个json的工具类JsonUtils

package com.cs.utils;

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

import java.text.SimpleDateFormat;

public class JsonUtils {

    public static String getJson(Object object){
        return getJson(object,"yy-MM-dd HH:mm:ss");
    }


    public static String getJson(Object object,String dataFormat){
        ObjectMapper objectMapper = new ObjectMapper();
        //不使用时间戳的方式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
        //自定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat(dataFormat);
        objectMapper.setDateFormat(sdf);
        String string = null;
        try {
            string = objectMapper.writeValueAsString(object);
            return string;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
       return null;
    }
}

2.7.2 fastjson

导入依赖

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.60</version>
    </dependency>
@RequestMapping(value = "/j3")
    @ResponseBody
    public String json2(){
        List<User> list = new ArrayList<>();
        list.add(new User("小艾1号", 3, "男"));
        list.add(new User("小艾2号", 3, "男"));
        list.add(new User("小艾3号", 3, "男"));
        list.add(new User("小艾4号", 3, "男"));
        String string = JSON.toJSONString(list);
        return string;
    }

2.8 Ajax

Ajax不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的web应用程序的技术。

jquery向服务器发送一个ajax请求后,可以返回多种类型的数据格式,包括:html,xml,json,text等。

Ajax的标准格式:

$.ajax({
            url:"http://www.test.com",  //请求的url地址  
            dataType:"json", //返回格式为json  async:true,//请求是否异步,默认为异步,这也是ajax重要特性     data:{"id":"1","name":"名字"},  //参数值  type:"GET",  //请求方式                    beforeSend:function(){    //请求前的处理  },
            success:function(req){    //请求成功时处理  },
                complete:function(){    //请求完成的处理  }, 
                    error:function(){    //请求出错处理  }
                    });

举例:使用Ajax实现用户登录校验

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script src="${pageContext.request.contextPath}/js/jquery-1.12.4.js"></script>
    <script>
        function a1(){
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{"name":$("#name").val()},
                success:function (data) {
                    if (data.toString()==='ok'){
                        $("#userInfo").css("color","green");
                    }else{
                        $("#userInfo").css("color","red");
                    }
                    $("#userInfo").html(data);
                }
            })
        }
        function a2(){
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{"pwd":$("#pwd").val()},
                success:function (data) {
                    if (data.toString()==='ok'){
                        $("#pwdInfo").css("color","green");
                    }else{
                        $("#pwdInfo").css("color","red");
                    }
                    $("#pwdInfo").html(data);
                }
            })
        }
    </script>
</head>
<body>
<p>
    用户名:<input type="text" id="name" οnblur="a1()">
    <span id="userInfo"></span>
</p>
<p>
    密码:<input type="text" id="pwd" οnblur="a2()">
    <span id="pwdInfo"></span>
</p>
</body>
</html>
@RequestMapping("/a3")
    public String s3(String name,String pwd){
        String msg = "";
        if (name!=null) {
            if ("admin".equals(name)) {
                msg = "ok";
            }else{
                msg = "用户名有误!";
            }
        }
        if (pwd!=null) {
            if ("123456".equals(pwd)) {
                msg = "ok";
            }else{
                msg = "密码有误!";
            }
        }
        return msg;
    }

2.9 拦截器

SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自定义一些拦截器来实现特定的功能。

**过滤器和拦截器的区别:**拦截器是AOP思想的具体应用。

拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/image/js是不会进行拦截的。

2.9.1 自定义拦截器

想要自定义拦截器,必须实现HandlerIntercepot接口。

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        //放行:判断什么情况下登录
        /**
         *  1、session有值
         *  2、登陆页面也会放行
         */
       if (request.getRequestURI().contains("Login")){
           return true;
       }
        if (session.getAttribute("userLoginInfo")!=null){
            return true;
        }
        //判断什么情况下没有登录
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }
}

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <context:component-scan base-package="com.cs.controller"/>
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--拦截器配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.cs.config.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

2.10 文件上传和下载

导入依赖

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.6</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
    </dependency>
 <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>

SpringMVC使用表单文件上传需要设置enctype为multipart/form-data;浏览器就会采用二进制的方式来处理表单数据。

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

SpringMVC为文件上传提供了直接的支持,这种支持是用即插即用的MultipartResolve实现的。配置文件上传的id必须是multipartResolver

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--请求的编码格式,必须和jsp的pageEncoding属性一致-->
    <property name="defaultEncoding" value="utf-8"/>
    <!--上传文件大小上限,单位为字节(10485760=10M)-->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>

两种下载方式

@RestController
public class MyController {

    @RequestMapping("/upload1")
    public String file(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //获取文件名
        String uploadFileName = file.getOriginalFilename();
        //如果文件名为空,直接回到首页
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名:"+uploadFileName);

        //上传路径保存
        String path = request.getServletContext().getRealPath("upload");
        //如果路径不存在,创建一个
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+ realPath);
        InputStream is = file.getInputStream();//文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName));//文件输出流
        //读取写出
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
    /**
     * 方式二:采用file.transferTo 来保存上传的文件
     */
    @RequestMapping("upload2")
    public String fileUpload2(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException {
        //上传路径保存设置
        String path = request.getServletContext().getRealPath("upload");
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        //上传文件地址
        System.out.println("上传文件保存地址:"+ realPath);

        //通过CommonsMultipartFile的方式直接写文件
        file.transferTo(new File(realPath + "/" + file.getOriginalFilename()));

        return "redirect:/index.jsp";
    }
}

第三章 SSM整合

3.1 SSM思路

SSM思路:Springmvc+Spring+MyBatis(IBatis),所以有人叫做SSI整合。

SSM整合是使用三个框架的优势功能。三个框架对应的三层架构的三层。SpringMVC是视图层,Spring是业务层,MyBatis持久层。

SSM整合,需要把对象交给容器管理,让容器去创建项目中要使用的java对象。现在有两个容器。

第一个是Spring容器:Spring容器是管理service和dao等对象的。是业务层对象的容器。

第二个是SpringMVC容器:管理控制器对象的。是视图层对象。

SSM整合就是把对象交给容器管理。两个容器共存。各自负责管理不同的对象。把对象声明到配置文件中,让两个容器创建对象。spring创建service,dao,springmvc创建controller。

3.2 容器的创建

Spring容器的创建:在web.xml声明了监听器ContextLoaderListener,这个功能框架写好了。功能是创建spring的容器对象WebApplicationContext。在创建WebApplicationContext对象时,读取spring的配置文件,读取文件的时候,遇到bean标签或者注解,就能创建service,dao等对象,放到容器中。

SpringMVC容器:在web.xml声明了中央调度器DisPacherServlet。在这个servlet的init()方法中,创建了容器对象WebApplicationContext,在创建WebApplicaitonContext对象,读取springmvc的配置文件,读取了文件的时候,遇到@Controller注解,创建控制器controller对象,放到容器中。

内存中,创建对象

WebApplicationContext spring = new WebApplicationContext();//spring–map(service,dao)

WebApplicationContext springmvc = new WebApplicationContext();//springmvc–map(controller)

SpringMVC容器和Spring容器的关系:设计上springMVC容器对象是Spring容器的子容器

Spring是父容器。springmvc子容器,相当于java中的继承关系

3.3 SSM整合开发步骤

  1. 使用的student表(id,name,age)
  2. 创建maven web项目
  3. 修改pom.xml加入依赖:spring,springmvc,mybatis,mybatis-spring,MySQL驱动,druid,jackson
  4. 写web.xml:声明容器对象
    • 声明spring的监听器ContextLoaderListener:创建spring的容器对象,创建service,dao对象
    • 声明springmvc的中央调度器DispatcherServlet:创建springmvc容器对象,创建controller对象
    • 声明字符集的过滤器CharacterEncodingFilter,解决post请求乱码的问题
  5. 创建程序中的包,dao,service,controller,entity
  6. 写spring,springmvc,mybatis配置文件
  7. 写java代码,实体类,dao接口和mapper文件,service类,controller类,使用注解声明对象和赋值
  8. 创建视图文件,各种jsp

pom.xml

 <!--Spring-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.11.RELEASE</version>
    </dependency>
    <!--Spring JDBC-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.11.RELEASE</version>
    </dependency>
    <!--Spring AOP-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.0.11.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.0.11.RELEASE</version>
    </dependency>
    <!--MyBatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.5</version>
    </dependency>
    <!--MyBatis整合Spring-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
    <!--MySQL驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.11</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <!--Druid-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.10</version>
    </dependency>
    <!--JSTL-->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <!--Servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>
    <!--jsp-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2.1-b03</version>
    </dependency>
    <!--jackson依赖-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>

    <!--lombok-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.6</version>
    </dependency>

  </dependencies>

 <!--静态资源导出问题-->
  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.properties</include>
        </includes>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.xml</include>
          <include>**/*.properties</include>
        </includes>
          <filtering>false</filtering>
      </resource>
    </resources>
  </build>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!--声明springmvc的中央调度器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:conf/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--声明字符集过滤器-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceRequestEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>forceResponseEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
<filter-mapping>
  <filter-name>characterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

    <!--加载静态资源-->
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.js</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.css</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.jpg</url-pattern>
    </servlet-mapping>

spring-dao.xml

 <!-- 配置整合mybatis -->
    <!-- 1.关联数据库文件 -->
    <context:property-placeholder location="classpath:database.properties"/>

    <!-- 2.数据库连接池 -->
    <!--数据库连接池
        dbcp  半自动化操作  不能自动连接
        c3p0  自动化操作(自动的加载配置文件 并且设置到对象里面)
    -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="driverClassName" value="${jdbc.driver}"/>
        <!-- c3p0连接池的私有属性 -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>
    <!-- 3.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置MyBatis全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!-- 4.配置扫描Dao接口包,动态实现Dao接口注入到spring容器中 -->
    <!--解释 :https://www.cnblogs.com/jpfss/p/7799806.html-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="com.cs.dao"/>
    </bean>

spring-service.xml

 <!--扫描service下的包-->
    <context:component-scan base-package="com.cs.service"/>

    <!--将我们的所有业务类,注入到Spring,可以通过配置,或者注解实现-->
    <bean id="BookServiceImpl" class="com.cs.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>

    <!--声明式事务配置-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--aop事务支持-->
<!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务的传播特性:new propagation-->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.cs.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

spring-mvc.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc
    https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 配置SpringMVC -->
    <!-- 1.开启SpringMVC注解驱动 -->
    <mvc:annotation-driven />
    <!-- 2.静态资源默认servlet配置-->
    <mvc:default-servlet-handler/>

    <!-- 3.配置jsp 显示ViewResolver视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!-- 4.扫描web相关的bean -->
    <context:component-scan base-package="com.cs.controller" />
</beans>

mybatis-config

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="com.cs.pojo"/>
    </typeAliases>
    <mappers>
        <mapper resource="com/cs/dao/BookMapper.xml"/>
    </mappers>
</configuration>

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cs.dao.BookMapper">
    <insert id="addBook" parameterType="Books">
        insert into books(bookName,bookCounts,detail)
        values(#{bookName},#{bookCounts},#{detail});
    </insert>
    <delete id="deleteBook" parameterType="int">
        delete from books
        where bookID = #{bookID};
    </delete>
    <update id="updateBook" parameterType="Books">
        update books set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
        where bookID = #{bookID};
    </update>
    <select id="queryBookById" resultType="Books">
        select * from books
        where bookID = #{bookID};
    </select>
    <select id="queryAllBook" resultType="Books">
        select * from books;
    </select>
    <select id="queryBookByName" resultType="Books">
        select * from books
        where bookName = #{bookName};
    </select>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值