SpringMVC

SpringMVC

    • 1. SpringMVC简介
      • 1.1 概念
      • 1.2 SpringMVC执行原理
    • 2. 第一个SpringMVC
      • 2.1 不使用注解
      • 2.2 使用注解
    • 3. Controller & RestFul
      • 3.1 RestFul
      • 3.2 转发与重定向
      • 3.3 接收参数与数据回显
      • 3.4 乱码问题
    • 4. JSON
      • 4.1 初识JSON
      • 4.2 Jackson-Databind
      • 4.3 FastJson
    • 5. SSM整合
      • 5.1 环境准备
      • 5.2 项目结构
      • 5.3 整合Mybatis
      • 5.4 整合Spring
      • 5.5 整合SpringMVC
      • 5.6 dao层
      • 5.7 service层
      • 5.8 controller层
      • 5.9 前端页面
    • 6. AJax
      • 6.1 概念
      • 6.2 通过JQ发送Ajax
    • 7. 拦截器
      • 7.1 概念
      • 7.2 自定义拦截器
      • 7.3 登录验证
    • 8. 文件上传&下载
      • 8.1 上传
      • 8.2 下载

感谢狂神的分享:B站视频地址

SpringMVC:官网地址

参考博客:地址

1. SpringMVC简介

1.1 概念

  • MVC:是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。代码实现上:模型(service、dao)控制器(controller)视图(jsp)。
  • 概念SpringMVC 是Spring框架中的一个分支,是基于Java实现MVC的轻量级Web框架
  • 核心:Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计的
  • 特点:轻量级,简单易学;高效,基于请求响应的mvc框架;与spring兼容性好,无缝结合;约定大于配置;功能强大:RESTful,数据验证,格式化,本地化,主题
    SpringMVC_第1张图片

1.2 SpringMVC执行原理

SpringMVC_第2张图片

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
    • 假设url为 : http://localhost:8080/SpringMVC/hello,拆成三个部分:
    • 服务器域名:http://localhost:8080
    • 服务器上的站点:SpringMVC
    • 控制器:hello
  2. HandlerMapping(处理器映射器)。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
  3. HandlerExecution,表示具体的 Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
  4. HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
  5. HandlerAdapter(处理器适配器),其按照特定的规则去执行Handler。
  6. Handler 让具体的 Controller 执行
  7. Controller 将具体的执行信息返回给HandlerAdapter,如ModelAndView。
  8. HandlerAdapter 将视图逻辑名或模型传递给 DispatcherServlet。
  9. DispatcherServlet调用ViewResolver(视图解析器)来解析HandlerAdapter传递的逻辑视图名
    DispatchServlet是接收前端的所有路径的请求,接收到之后根据路径去找对应的controller方法,因为每一个controller方法都被用@RequestMapping注解给予对应的路径
  10. ViewResolver将解析的逻辑视图名传给DispatcherServlet
  11. DispatcherServlet根据 ViewResolver 解析的视图结果,调用具体的视图
    1-4相当于原来servletservlet-mapping,5-8,原来servlet,10-12就是servlet 请求转发和重定向

2. 第一个SpringMVC

2.1 不使用注解

创建一个maven项目,导入jar包依赖


<dependencies>
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.11version>
    dependency>
    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-webmvcartifactId>
        <version>5.3.20version>
    dependency>
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>servlet-apiartifactId>
        <version>2.5version>
    dependency>
    
    <dependency>
        <groupId>javax.servlet.jspgroupId>
        <artifactId>jsp-apiartifactId>
        <version>2.1version>
    dependency>
    
    <dependency>
        <groupId>javax.servlet.jsp.jstlgroupId>
        <artifactId>jstl-apiartifactId>
        <version>1.2version>
    dependency>
dependencies>

项目结构如下

SpringMVC_第3张图片

web.xml中注册 DispatcherServlet


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

    
    <servlet>
        <servlet-name>SpringMvcservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:spring_servlet.xmlparam-value>
        init-param>
    servlet>

    
    <servlet-mapping>
        <servlet-name>SpringMvcservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
web-app>

配置SpringMvc核心配置文件


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

    
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    bean>

    
    <bean name="/hello" class="com.kuang.controller.HelloController"/>
    
beans>

自定义类,实现Controller接口

//创建一个类,实现Controller接口
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //创建 ModelAndView 对象
        ModelAndView modelAndView = new ModelAndView();
        //在对象中添加属性值
        modelAndView.addObject("msg","hello,Spring MVC !!!");
        //设置要跳转的视图。
        modelAndView.setViewName("hello");  //结合 prefix 、suffix ,会映射成路径: WEB-INF/jsp/hello.jsp

        return modelAndView;
    }
}

前端JSP页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
    ${msg}
body>
html>

注:如果项目无法正常启动,查看 project structure --> artifacts右侧 -->Output Layout 下 WEB-INF是否导入相关jar包

SpringMVC底层工作原理:
SpringMVC_第4张图片

2.2 使用注解

web.xml


<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>springMVCservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:springMVC.xmlparam-value>
        init-param>
        <load-on-startup>1load-on-startup>
    servlet>
    
    <servlet-mapping>
        <servlet-name>springMVCservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
    
web-app>

springMVC.xml

  • 省略了 handlerMapping、HandlerAdapter的手动配置,由annotation-driven 完成
  • 配置注解扫描指定的包

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

    
    <context:component-scan base-package="com.kuang.controller"/>
    
    <mvc:default-servlet-handler/>

    
    <mvc:annotation-driven/>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    bean>
beans>

controller

@Controller
public class HelloController {

    /*添加方法的访问路径
      如果方法加上 @ResponseBody,或者类用@RestController标识
          则方法返回字符串,不再被视图解析器处理
    */
    @RequestMapping("/hello")
    public String hello(Model model){
        //封装返回数据
        model.addAttribute("msg","hello,annotation method!!!");

        return "test"; //被视图解析器处理,拼装前、后缀形成路径
    }
}

3. Controller & RestFul

3.1 RestFul

优点:

  • 安全:看不出源代码的参数也意义
  • 地址复用:使得 get 和 post 访问相同的URL,框架自动进行类型转换
  • 高效:支持缓存

缺点:

  • 不像原生URL见名只意,URL理解不直观

实现方式

  1. 注解:@GetMapping("/addRest/{a}/{b}") + 参数@PathVariable int a, @PathVariable int b
    url地址:http://localhost:8080/xxx/addRest/1/2
  2. 注解:@PostMapping("/addRest/{a}/{b}") + 参数@PathVariable int a, @PathVariable int b
    使用Post提交url地址:http://localhost:8080/xxx/addRest/1/2
@Controller
public class RestFulController {

    /**
     * 原生的url:http://localhost:8080/xxx/add?a=1&b=1
     */
    @RequestMapping("/add")
    public String getAdd1(int a, int b, Model model) {
        int result = a + b;
        model.addAttribute("add", "原生的url:结果为" + result);
        return "add";
    }

    /**
     * RestFul方式一:method = get
     * RequestMapping("/addRest/{a}/{b}" method=requestMethod.GET) = @GetMapping()
     * http://localhost:8080/springmvc_04/addRest/1/1
     */
    @GetMapping("/addRest/{a}/{b}")
    public String getAdd2(@PathVariable int a, @PathVariable int b, Model model) {
        int result = a + b;
        model.addAttribute("add", "Rest的url:结果为" + result);
        return "addRest";
    }

    /**
     * 复用相同的url
     * RestFul方式二:method=post,使用RestFul的话,请求的url和GET就一样了
     */
    @PostMapping("/addRest/{a}/{b}")
    public String getAdd3(@PathVariable int a, @PathVariable int b, Model model) {
        int result = a + b;
        model.addAttribute("add", "Rest的url:结果为" + result);
        return "addRest";
    }
}

3.2 转发与重定向

  • 可以使用原生的request转发或者response重定向
  • 推荐使用SpringMvc的 return “forward:xxx”/"redirect:xxx"
@Controller
public class ModelTest1 {
    //原生的转发:返回值是void,没有经过视图解析器;原生的重定向同样如此,都不走视图解析器,直接重定向
    @RequestMapping("/test1")
    public void test1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getSession().getId();
        System.out.println(id);
        request.getRequestDispatcher("index.jsp").forward(request,response);
    }
    //SpringMvc转发:测试结果是不走视图解析器,url没变是转发
    @RequestMapping("/test2")
    public String test2(Model model) {
        model.addAttribute("demo1","这是test2中的Spring转发");
        return "forward:/WEB-INF/jsp/demo1.jsp";
    }
    //SpringMvc重定向:测试结果是不走视图解析器
    @RequestMapping("/test3")
    public String test3() {
        System.out.println("跳转回首页index.jsp");
        return "redirect:index.jsp";
    }
}

3.3 接收参数与数据回显

  • 前端提交的name和后端映射器接受的形参名一样,则直接接受
  • 前端提交的name和后端映射器接受的形参名不用一样,在形参前@RequestParam("xxx")更改名称一致
  • 如果后端参数封装成一个pojo,前端传过来的name会自动pojo中的成员属性,不匹配的属性=null/0
@Controller
public class UserController {
    /** http://localhost:8080/springmvc_04/t1?id=1&name=abc&age=18
     * @param user SpringMvc 会自动封装数据到参数里的pojo,不匹配的属性=null/0
     */
    @GetMapping("/t1")
    public String getUser(User user){
        System.out.println(user);
        return "test1";
    }
}

3.4 乱码问题

  • 方法一:web.xml里面配置的SpringMvc自带的过滤器CharacterEncodingFilter/*:因为要跳转到xxx.jsp页面,所以url是 /* (≠/)

<filter>
    <filter-name>encodefilter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
    <init-param>
        <param-name>encodingparam-name>
        <param-value>utf-8param-value>
    init-param>
filter>
<filter-mapping>
    <filter-name>encodefilter-name>
    <url-pattern>/*url-pattern>
filter-mapping>
  • 方法二:一劳永逸,但需要重启Tomcat服务器,修改Tomcat里面的server.xml配置文件:URIEncoding = “UTF-8”
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding = "UTF-8"/>

4. JSON

4.1 初识JSON

JSON(JavaScript Object Notation, JS对象标记)是一种轻量级的数据交换格式。它基于 ECMAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsontitle>
    <script type="text/javascript">
        //user是一个js对象
        var user = {
            name: "张三",
            age: 18,
            sex: "男"
        };
        //后端传的json其实是一个字符串,前端将后端传的json转换成js对象渲染在页面上
        //jsonUser:模拟后端传的json数据
        //js转换成json
        var jsonUser = JSON.stringify(user);
        console.log(jsonUser);
        //jsUser:js是一个对象
        //json转换成js
        var jsUser = JSON.parse(jsonUser);
        console.log(jsUser)
    script>
head>
html>

4.2 Jackson-Databind

1. 导入依赖:

<dependency>
    <groupId>com.fasterxml.jackson.coregroupId>
    <artifactId>jackson-databindartifactId>
    <version>xxxversion>
dependency>
  • json=一个字符串,所以会有中文乱码问题,需要在springmvc.xml配置

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

2. 编写Controller

  • @RestControoler:该类下所有方法不走视图解析器,返回一个json数据
  • @ResponseBody:该方法不走视图解析器,返回一个json数据
@RestController
public class UserController {
    //Json返回一个对象
    @RequestMapping("/t1")
    public String json1() throws JsonProcessingException {
        User user = new User(1, "张三", 20);
        ObjectMapper jacksonMapper = new ObjectMapper();
        String str_user = jacksonMapper.writeValueAsString(user);
        //str_user有中文乱码问题,springMvc可以统一配置
        return str_user;
    }
}

4.3 FastJson

1. 导包

<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
    <version>xxxversion>
dependency>

2. 介绍

  • JSONObject 代表JSON对象
    JSONObject实现了Map接口,对应的是json对象,通过各种形式的get()方法可以获取对象中的数据,使用诸如size(),isEmpty()方法获取 "键:值"的个数或判断是否为空。本质是通过实现Map接口,病调用其中的方法完成的。
  • JSONArray 代表JSON数组
    内部是List接口中的方法,完成操作的
  • JSON 代表 JSONObject与JSONArray的转化
    主要实现 json对象、json数组、Javabean对象、json字符串之间的相互转化

5. SSM整合

5.1 环境准备

数据库:

CREATE TABLE `books` (
  `bookId` int(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
  `bookName` varchar(100) NOT NULL COMMENT '书名',
  `bookCounts` int(11) NOT NULL COMMENT '数量',
  `detail` varchar(200) NOT NULL COMMENT '描述',
  KEY `bookId` (`bookId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.kuanggroupId>
    <artifactId>SpringMVCartifactId>
    <packaging>pompackaging>
    <version>1.0-SNAPSHOTversion>
    <modules>
        <module>spring_jsonmodule>
        <module>spring_ssmmodule>
    modules>

    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
    properties>

    <dependencies>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.13.2version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.29version>
        dependency>
        
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.2version>
        dependency>
        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>servlet-apiartifactId>
            <version>2.5version>
        dependency>
        <dependency>
            <groupId>javax.servlet.jspgroupId>
            <artifactId>jsp-apiartifactId>
            <version>2.2version>
        dependency>
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>jstlartifactId>
            <version>1.2version>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.5.10version>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>2.0.7version>
        dependency>

        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.3.21version>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>5.3.21version>
        dependency>
    dependencies>

    
    <build>
        <resources>
            <resource>
                <directory>src/main/resourcesdirectory>
                <includes>
                    <include>**/*.propertiesinclude>
                    <include>**/*.xmlinclude>
                includes>
                <filtering>truefiltering>
            resource>

            <resource>
                <directory>src/main/javadirectory>
                <includes>
                    <include>**/*.propertiesinclude>
                    <include>**/*.xmlinclude>
                includes>
                <filtering>truefiltering>
            resource>
        resources>
    build>

project>

5.2 项目结构

SpringMVC_第5张图片

5.3 整合Mybatis

mybatis-config.xml配置如下(数据库连接交给 spring_dao.xml 管理):


DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    settings>
    
    
    <typeAliases>
        
        <package name="com.kuang.pojo"/>
    typeAliases>

    <mappers>
        <mapper class="com.kuang.dao.BooksMapper">mapper>
    mappers>

configuration>
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/stu?useSSL=false&useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

5.4 整合Spring

分成spring_dao.xml,spring_service.xml,spring_mvc.xml 三层整合,然后通过Spring核心配置文件,将三部分合并到一起

Spring_dao.xml主要配置mybatis-spring.jar中的信息


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    
    <context:property-placeholder location="classpath:jdbc.properties"/>

    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <property name="autoCommitOnClose" value="false"/>
        <property name="checkoutTimeout" value="10000"/>
        <property name="acquireRetryAttempts" value="2"/>
    bean>

    
    <bean name="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        
        <property name="dataSource" ref="dataSource"/>
        
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    bean>

    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
        
        <property name="basePackage" value="com.kuang.dao"/>
    bean>

beans>

spring_service.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    
    <context:component-scan base-package="com.kuang.service"/>
    
    <bean id="booksServiceImpl" class="com.kuang.service.BooksServiceImpl">
        <property name="booksMapper" ref="booksMapper"/>
    bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    bean>
    

beans>

通过applicationContext.xml,合并spring的几个配置文件


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

    <import resource="spring_dao.xml"/>
    <import resource="spring_service.xml"/>
    <import resource="spring_mvc.xml"/>

beans>

5.5 整合SpringMVC

添加web项目支持,并配置web.xml

SpringMVC_第6张图片
web.xml配置如下


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

    
    <servlet>
        <servlet-name>SpringMVCservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            
            <param-value>classpath:applicationContext.xmlparam-value>
        init-param>
    servlet>
    <servlet-mapping>
        <servlet-name>SpringMVCservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>

    
    <filter>
        <filter-name>encodingFilterfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>utf-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>encodingFilterfilter-name>
        <url-pattern>/*url-pattern>
    filter-mapping>
web-app>

spring_mvc.xml配置如下:


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    
    <mvc:annotation-driven/>
    
    <mvc:default-servlet-handler/>
    
    <context:component-scan base-package="com.kuang.controller"/>
    
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    bean>
beans>

5.6 dao层

dao层有 BooksMapper.java、 BooksMapper.xml,内容如下:

public interface BooksMapper {
    //增加一本书
    int addBook(Books books);
    //删除一本书
    int deleteBookById(@Param("bookId") int id);
    //修改一本书
    int updateBook(Books books);
    //查询一本书根据id
    Books queryBookById(@Param("bookId")int id);
    //查询全部书
    List<Books> queryAllBook();

    Books queryBookByName(@Param("bookName") String bookName);
}

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.kuang.dao.BooksMapper">
    <insert id="addBook" parameterType="Books">
        insert into ssmbuild.books(bookName, bookCounts, detail)
        values (#{bookName},#{bookCounts},#{detail});
    insert>
    <delete id="deleteBookById" parameterType="int">
        delete from ssmbuild.books where bookId = #{bookId}
    delete>
    <update id="updateBook" parameterType="Books">
        update ssmbuild.books set
                                  bookName=#{bookName},
                                  bookCounts=#{bookCounts},
                                  detail=#{detail}
        where bookId=#{bookId};
    update>
    <select id="queryBookById" parameterType="int" resultType="Books">
        select * from ssmbuild.books where bookId = #{bookId};
    select>
    <select id="queryAllBook" resultType="Books">
        select * from ssmbuild.books;
    select>

    <select id="queryBookByName" parameterType="String" resultType="Books">
        select * from ssmbuild.books where bookName=#{bookName}
    select>

mapper>

5.7 service层

public interface BooksService {
    //增加一本书
    int addBook(Books books);
    //删除一本书
    int deleteBookById(int id);
    //修改一本书
    int updateBook(Books books);
    //查询一本书根据id
    Books queryBookById(int id);
    //查询全部书
    List<Books> queryAllBook();
    
    Books queryBookByName(String bookName);
}
public class BooksServiceImpl implements BooksService {

    //在spring中,注入Dao层
    private BooksMapper booksMapper;
    public void setBooksMapper(BooksMapper booksMapper) {
        this.booksMapper = booksMapper;
    }

    @Override
    public int addBook(Books books) {
        return booksMapper.addBook(books);
    }

    @Override
    public int deleteBookById(int id) {
        return booksMapper.deleteBookById(id);
    }

    @Override
    public int updateBook(Books books) {
        return booksMapper.updateBook(books);
    }

    @Override
    public Books queryBookById(int id) {
        return booksMapper.queryBookById(id);
    }

    @Override
    public List<Books> queryAllBook() {
        return booksMapper.queryAllBook();
    }

    @Override
    public Books queryBookByName(String bookName) {

        return booksMapper.queryBookByName(bookName);
    }
}

5.8 controller层

@Controller
@RequestMapping("book")
public class BooksController {

    @Autowired
    @Qualifier("booksServiceImpl")
    private BooksService booksService;

    @RequestMapping("allBook")
    public String allBook(Model model){
        List<Books> books = booksService.queryAllBook();
        model.addAttribute("list", books);
        return "allBook";
    }

    //跳转到增加书籍页面
    @RequestMapping("/toAddBook")
    public String toAddBook() {
        return "addBook";
    }

    //添加书籍,成功后跳转至所有书籍页面
    @RequestMapping("/addBook")
    public String addBook(Books books) {
        int result = booksService.addBook(books);
        if (result > 0) {
            System.out.println("添加书籍成功");
        }
        return "redirect:/book/allBook";
    }

    @RequestMapping("/toUpdateBook")
    public String toUpdate(int bookId, Model model) {
        Books books = booksService.queryBookById(bookId);
        model.addAttribute("book", books);
        return "updateBook";
    }

    //没有提交事务操作,更新会失败
    @RequestMapping("/updateBook")
    public String updateBook(Books books) {
        int result = booksService.updateBook(books);
        if (result > 0) {
            System.out.println("修改书籍成功");
        }
        return "redirect:/book/allBook";
    }

    //删除书籍,回顾RestFul风格
    @RequestMapping("/deleteBook/{bookId}")
    public String deleteBook(@PathVariable("bookId") int bookId) {
        int result = booksService.deleteBookById(bookId);
        if (result > 0) {
            System.out.println("删除书籍成功");
        }
        return "redirect:/book/allBook";
    }

    @RequestMapping("/queryBook")
    public String queryBook(String queryBookName, Model model) {
        Books books = booksService.queryBookByName(queryBookName);
        //复用,这样就显示一个
        List<Books> list = new ArrayList<>();
        list.add(books);
        if (books == null) {
            list= booksService.queryAllBook();
            model.addAttribute("errMsg","未查任何书籍");
        }
        model.addAttribute("list", list);
        return "allBook";
    }   
}

5.9 前端页面

allBook.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>所有书籍title>
    <%--BootStrap美化界面--%>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
head>
<body>
<div class="container">
    <div class="row clearfix">
        <%--屏幕分成12列--%>
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small> 书籍列表——————————显示所有书籍small>
                h1>
            div>
        div>
        <div class="row">
            <div class="col-md-4 column">
                <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍a>
                <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">显示全部书籍a>
            div>

            <div class="col-md-4 column">div>

            <div class="col-md-8 column">
                <form action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float: right">
                    <%--前端未传任何信息,就显示错误提示信息:未查任何书籍--%>
                    <span style="color: red;font-weight: bold">${errMsg}span>
                    <%--class="form-inline"保证在同一行--%>
                    <input type="text" name="queryBookName" class="form-inline" placeholder="请输入要查询的书籍名称">
                    <input type="submit" value="查询" class="btn btn-primary">

                form>
            div>
        div>

    div>
    <div class="row clearfix">
        <div class="col-md-12 column">
            <table class="table table-hover table-striped">
                <thead>
                <tr>
                    <th>书籍编号th>
                    <th>书籍名称th>
                    <th>书籍数量th>
                    <th>书籍详情th>
                    <th>操作th>
                tr>
                thead>
                <%--书籍从数据库中查询出来,从这个list中遍历出来,foreach--%>
                <tbody>
                <c:forEach var="book" items="${list}">
                    <tr>
                        <td>${book.bookId}td>
                        <td>${book.bookName}td>
                        <td>${book.bookCounts}td>
                        <td>${book.detail}td>
                        <td>
                            <a href="${pageContext.request.contextPath}/book/toUpdateBook?bookId=${book.bookId}">修改a>
                              |  
                            <a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookId}">删除a>
                        td>
                    tr>
                c:forEach>
                tbody>
            table>
        div>
    div>
div>
body>
html>

addBook.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加书籍title>
    <%--BootStrap美化界面--%>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
head>
<body>
<div class="row clearfix">
    <%--屏幕分成12列--%>
    <div class="col-md-12 column">
        <div class="page-header">
            <h1>
                <small>新增书籍small>
            h1>
        div>
    div>
div>
    <%--BootStrap官网拿"表单"数据  name属性保证pojo属性名称一致 required保证必须提交--%>
    <form action="${pageContext.request.contextPath}/book/addBook" method="post">
        <div class="form-group">
            <label for="bName">书籍名称:label>
            <input type="text" name="bookName" class="form-control" id="bName" required>
        div>
        <div class="form-group">
            <label for="bCount">书籍数量:label>
            <input type="text" name="bookCounts" class="form-control" id="bCount" required>
        div>
        <div class="form-group">
            <label for="bDesc">书籍描述:label>
            <input type="text" name="detail" class="form-control" id="bDesc" required>
        div>
        <div class="form-group">
            <input type="submit" class="form-control" value="添加">
        div>
    form>
body>
html>

updateBook.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>修改书籍title>
    <title>Titletitle>
    <%--BootStrap美化界面--%>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
head>
<body>
<div class="row clearfix">
    <%--屏幕分成12列--%>
    <div class="col-md-12 column">
        <div class="page-header">
            <h1>
                <small>修改书籍small>
            h1>
        div>
    div>
div>
<%--BootStrap官网拿"表单"数据  name属性保证pojo属性名称一致 required保证必须提交--%>
<form action="${pageContext.request.contextPath}/book/updateBook" method="post">
    <%--提交失败:没有回显:问题:
        1. 事务没有提交
        2. sql执行失败,没有提交BookId,需要前端的隐藏域
    --%>
    <%--添加bookId的隐藏域--%>
    <input type="hidden" name="BookId" value="${book.bookId}">
    <div class="form-group">
        <label for="bName">书籍名称:label>
        <input type="text" name="bookName" class="form-control" id="bName" value="${book.bookName}" required>
    div>
    <div class="form-group">
        <label for="bCount">书籍数量:label>
        <input type="text" name="bookCounts" class="form-control" id="bCount" value="${book.bookCounts}"required>
    div>
    <div class="form-group">
        <label for="bDesc">书籍描述:label>
        <input type="text" name="detail" class="form-control" id="bDesc" value="${book.detail}" required>
    div>
    <div class="form-group">
        <input type="submit" class="form-control" value="修改">
    div>
form>
body>
html>

6. AJax

6.1 概念

Ajax:Asynchronous Javascript And XML(异步JavaScript和XML),一个异步无刷新请求,无需更新整个页面就异步加载一些数据。

使用iframe,模拟异步请求

 DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模拟Ajax异步请求title>
    <script>
        function go() {
            var url = document.getElementById("url").value;
            document.getElementById("iframe1").src = url;
        }
    script>
head>
<body>
<div>
    <p>请输入地址:p>
    <p>
        <input type="text" id="url">
        <input type="button" id="button" value="提交" onclick="go()">
    p>
div>
<div>
    <iframe id="iframe1" style="width:100%;height: 500px">
    iframe>
div>
body>
html>

6.2 通过JQ发送Ajax

初试Ajax

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$title>
    <%--加载动态的JQ资源--%>
    <script src="https://code.jquery.com/jquery-3.4.1.js">script>
    <script>
        /*
        AJax参数:
        url:后端接受的地址
        data:后端接受到的请求参数,json数据格式=前后端分离时候,后端传的数据便于前端接受就是json数据
        success:后端接受成功返回的函数
        error:后端失败接受返回的函数
        */
        function username() {
            $.post({
                url: "${pageContext.request.contextPath}/a1",
                data: {"name": $("#username").val()},
                success: function (data, status) {
                    console.log("data:" + data);
                    console.log("status:" + status);
                }
            })
        }

    script>
head>
<body>
<%--
	实现Ajax异步请求
    	1 绑定单击事件
    	2 单击事件函数使用Jq:$.post({})
--%>
用户名:<input type="text" id="username" onclick="username()">
body>
html>

异步加载

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Ajaxtitle>

    <script src="https://code.jquery.com/jquery-3.4.1.js">script>
    <script>
        /*页面加载完,触发函数*/
        $(function () {
            /*绑定btn单击事件*/
            $("#btn").click(function () {
                /*JQ使用Ajax异步请求*/
                $.post("${pageContext.request.contextPath}/a2", function (data) {
                    // data接受返回的值
                    //console.log(data);
                    var html = "";
                    for (let i = 0; i < data.length; i++) {
                        html += "" +
                            "" + data[i].name + "" +
                            "" + data[i].age + "" +
                            "" + data[i].sex + "" +
                            +""
                    }
                    $("#content").html(html);
                });
            });
        })
    script>
head>
<body>
<input type="button" id="btn" value="加载数据">
<table>
    <tr>
        <td>姓名td>
        <td>年龄td>
        <td>性别td>
    tr>
    <tbody id="content">
    	
    tbody>
table>
body>
html>

登录验证

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>logintitle>
    <script src="https://code.jquery.com/jquery-3.4.1.js">script>
    <script>
        function nameFun() {
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data: {"name": $("#name").val()},
                success: function (data) {
                    //console.log(data);
                    if (data.toString() === "用户名成功") {
                        $("#userInfo").css("color", "green");
                    } else {
                        $("#userInfo").css("color", "red");
                    }
                    $("#userInfo").html(data);
                }
            })
        }

        function passwordFun() {
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data: {"password": $("#password").val()},
                success: function (data) {
                    if (data.toString() === "密码正确") {
                        $("#userPasswordInfo").css("color", "green");
                    }else {
                        $("#userPasswordInfo").css("color", "red");
                    }
                    $("#userPasswordInfo").html(data);
                }
            })
        }
    script>
head>
<body>
<p>
    用户名:<input type="text" id="name" onclick="nameFun()">
    <%--span提示信息--%>
    <span id="userInfo">span>
p>
<p>
    用户密码:<input type="password" id="password" onclick="passwordFun()">
    <span id="userPasswordInfo">span>
p>
body>
html>

7. 拦截器

7.1 概念

拦截器(Interceptor)基于反射机制(动态代理)实现,Struts、SpringMVC都有拦截器功能,不依赖Tomcat等容器,不能修改 Request 中的内容,用于验证信息(用户是否登录、权限验证、日志记录等

过滤器(Filter)与拦截器(Interceptor)都体现了AOP的思想,区别如下:

实现方式不同

Filter基于回调函数实现,依赖于Tomcat等容器,只能用在web项目中。而Interceptor是Spring的一个组件,不依赖于Tomcat等容器,也可以用在Application、Swing等容器中。

触发时机不同

SpringMVC_第7张图片

Filter在请求进入容器之后,但进入Servlet容器之前进行预处理,请求结束是在Servlet处理完之后。
Interceptor在请求进入Servlet后,但进入Controller之前进行预处理,Controller中渲染了对应的视图之后请求结束。

拦截范围不同

Filter 几乎可以对所有进入容器的请求起作用
Interceptor 只对Controller中请求或static目录下的资源请求起作用

7.2 自定义拦截器

自定义拦截器,实现HandlerInterceptor接口:

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //return true:执行下一个拦截器
        System.out.println("===========处理前,这里进行拦截处理=================");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("===========处理后,通常进行日志管理=================");
    }

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

在Spring配置文件中注册:


<mvc:interceptors>
    <mvc:interceptor>
        
        <mvc:mapping path="/**"/>
        <bean class="com.ssl.config.MyInterceptor"/>
    mvc:interceptor>
mvc:interceptors>

7.3 登录验证

拦截器

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        request.getRequestURL();
        //URL: http://localhost:8080/springmvc_07_interceptor/user/main
        System.out.println("URL:" + request.getRequestURL());
        //URI: /springmvc_07_interceptor/user/main
        System.out.println("URI:" + request.getRequestURI());

        if (session.getAttribute("username") == null || session.getAttribute("password") == null) {
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        } else if (session.getAttribute("username").equals("admin") && session.getAttribute("password").equals("123456")) {
            return true;
        }
        if (request.getRequestURI().contains("login")) {
            return true;
        }
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
}

控制层

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

    @RequestMapping("/main")
    public String main() {
        //沒登陸就不等進入首頁
        return "main";
    }

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


    @RequestMapping("/login")
    public String login(String username, String password, HttpSession session, Model model) {
        session.setAttribute("username", username);
        session.setAttribute("password", password);
        model.addAttribute("username", username);
        return "main";
    }

    @RequestMapping("/outUser")
    public String outUser(HttpSession session) {
        session.removeAttribute("username");
        session.removeAttribute("password");
        return "main";
    }
}

8. 文件上传&下载

8.1 上传

  • 前端form添加enctype=“multipart/form-data”,method=“post”
<form enctype="multipart/form-data" method="post" action="">
    
form>
  • 后端pom导包
 <dependencies>
    <dependency>
        <groupId>commons-fileuploadgroupId>
        <artifactId>commons-fileuploadartifactId>
        <version>1.4version>
    dependency>
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>javax.servlet-apiartifactId>
        <version>4.0.1version>
    dependency>
dependencies>
  • Spring自带的文件上传,application.xml配置
 <!--4 文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="utf-8"/>
    <!--最大上传大小:单位是1字节-->
    <property name="maxUploadSize" value="10485760"/>
    <property name="maxInMemorySize" value="40960"/>
</bean>
@RestController
public class FileController {
    @RequestMapping("/upFile")
    public String upFile(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //设置文件保存路径
        String path = request.getServletContext().getRealPath("/upload");
        System.out.println("path:" + path);
        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";
    }
}

8.2 下载

  • 方式一:写方法下载
@RequestMapping(value = "/download")
public String downLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
    //手动设置,要下载的图片地址
    String path = request.getServletContext().getRealPath("/upload");
    String fileName = "1.png";
    //设置响应头
    response.reset();//设置页面不缓存,清空buffer
    response.setCharacterEncoding("UTF-8");
    response.setContentType("multipart/form-data");//二进制传输数据
    response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
    File file = new File(path, fileName);
    //读取文件-输入流
    InputStream input = new FileInputStream(file);
    //写入文件-输出流
    OutputStream out = response.getOutputStream();
    byte[] buff = new byte[1024];
    int index = 0;
    while ((index = input.read(buff)) != -1) {
        out.write(buff,0,index);
        out.flush();
    }
    input.close();
    out.close();
    return "redirect:/index.jsp";
}
  • 方法二:标签直接获取web下的静态资源
<a href="${pageContext.request.contextPath}/static/1.png">图片下载a>

你可能感兴趣的:(java,servlet,mvc,spring,ajax)