springMVC笔记

本文详细介绍了Spring MVC的架构、配置、注解驱动开发以及执行原理。从搭建web环境到创建Controller,讲解了MVC模式的工作流程,包括处理器映射器、适配器和视图解析器的配置。此外,还探讨了RESTful风格的实现、数据处理、JSON转换以及使用Jackson进行序列化。最后提到了Spring MVC中的拦截器和登录拦截的实现。
摘要由CSDN通过智能技术生成

1、MVC架构

MVC:模型(dao,service),视图(jsp),控制器(servlet)

MVC架构要做的事情

  • 将url映射到java类或者java类的方法
  • 封装用户提交的数据
  • 处理请求—调用相关的业务处理—封装响应数据
  • 将响应的数据进行渲染,jsp/html等表示层数据

搭建web环境时,Maven创建web项目不要直接在创建的时候勾选,我们需要在创建项目之后,右键项目,点击添加架构支持
在这里插入图片描述

点击之后的第一个就是web application勾选就行

2、springMVC初识

springMVC是spring framework的一部分,是基于java实现的MVC的轻量级web框架

springMVC的特点

  • 轻量级,简单易学
  • 高效,基于请求响应的MVC框架
  • 与Spring兼容性好,无缝结合
  • 约定优于配置
  • 功能强大:RESTful(这就是将网参数传递从key=value模式转换为用斜杠来分割)、数据验证,格式化,本地化,主题等
  • 简洁灵活

Spring的web框架围绕DispatcherServlet(调度Servlet)设计

DispatcherServlet的作用是将请求分发到不同的处理器,从Spring 2.5开始,使用Java 5 或者以上版本的用户可以采用基于注解形式开发,十分简洁

正因为SpringMVC好,简单,便捷,易学,天生和spring无缝继承(使用SpringIOC和AOP),使用约定由于配置,能够进行简单的junit测试,支持Restful风格,异常处理,本地化,国际化,数据验证,类型转换,拦截器等,所以需要学习

springMVC调用方法
在这里插入图片描述

3、HelloSpringMVC

  1. 新建一个Moudle,添加web的支持

  2. 确定导入了SpringMVC的依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.14</version>
    </dependency>
    
  3. 配置web.xml,注册DispatcherServlet

    <?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">
        <!--注册DispatcherServlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--关联一个springmvc的配置文件 [servlet-name]-name.xml-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
            <!--启动级别-1-->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <!-- / 匹配所有的请求 不包括.jsp-->
        <!-- /* 匹配所有的请求 包括.jsp-->
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
  4. 编写springMVC的配置文件,名称springmvc-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd"> 
        
    </beans>
    
  5. 添加处理映射器

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    
  6. 添加处理器适配器

    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
  7. 添加视图解析器

    <!--视图解析器:DispatcherServlet给他的ModelAndView
    1.获取了ModelAndView的数据
    2.解析ModelAndView的视图名字
    3.拼接视图名字,找到对应的视图 hello然后进行拼接   /WEB-INF/jsp/hello.jsp
    4.将数据渲染到这个视图上
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
    
  8. 编写要操作的业务Controller,要么实现org.springframework.web.servlet.mvc包下的Controller接口,要么增加注解;返回一个ModelAndView,装数据,封视图

    package com.hty.controller;
    
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class HelloController implements Controller {
    
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //ModelAndView模型和视图
            ModelAndView mv = new ModelAndView();
            //封装对象放在ModelAndView中
            mv.addObject("msg","HelloSpringMVC!");
            //封装要跳转的视图,放在ModelAndView中
            mv.setViewName("hello");//: /WEB-INF/jsp/hello.jsp
            return mv;
        }
    }
    
  9. 将自己的类交给SpringIOC容器,注册bean

    <!--Handler-->
    <bean id="/hello" class="com.hty.controller.HelloController"/>
    
  10. 写要跳转的jsp页面,显示ModelAndView存放的数据,以及我们正常页面

    <%--
      Created by IntelliJ IDEA.
      User: hty
      Date: 2022-02-22
      Time: 21:17
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        ${msg}
    </body>
    </html>
    
  11. 配置tomcat

可能会遇到代码没问题,但是页面404,可能的原因就是jar包识别不到

解决方法:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

最后点击OK就行了

4、SpringMVC执行原理

在这里插入图片描述

在这里插入图片描述

图中圆圈圈出来的是需要我们自己实现的,剩下的都是springMVC实现的

流程简要分析

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心,用户发出请求,DispatcherServlet接受请求并拦截请求
    • 我们假设请求的url为:http://localhost:8080/SpringMVC/hello
    • 如上url拆分成三部分
    • http://localhost:8080服务器域名
    • SpringMVC部署在服务器上的web站点
    • hello表示控制器
    • 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
  2. HandlerMapping为处理器映射,DispatcherServlet调用HandlerMapping,HandlerMpping根据请求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传递的逻辑视图名
  10. 视图解析器将解析的逻辑视图名传给DispatcherServlet
  11. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
  12. 最终视图呈现给用户

5、使用注解开发SpringMVC

  1. 配置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">
        <!--注册DispatcherServlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--关联一个springmvc的配置文件 [servlet-name]-name.xml-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
            <!--启动级别-1-->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <!-- / 匹配所有的请求 不包括.jsp-->
        <!-- /* 匹配所有的请求 包括.jsp-->
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
  2. 编写spring配置文件

    <?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
            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">
    
        <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
        <context:component-scan base-package="com.hty.controller"/>
        <!--让spring MVC不处理静态资源  css  js  html  mp3  mp4-->
        <mvc:default-servlet-handler/>
        <!--支持mvc注解驱动
            在spring中一般采用@RequestMapping注解来完成映射关系
            要想使@RequestMapping注解生效
            必须向上下文中注册DefaultAnnotationHandlerMapping
            和一个AnnotationMethodHandlerAdapter实例
            这两个实例分别在类级别和方法级别处理
            而annotation-driver配置帮助我们自动完成上述两个实例的注入
        -->
        <mvc:annotation-driven/>
    
    
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        <!--视图解析器:DispatcherServlet给他的ModelAndView
        1.获取了ModelAndView的数据
        2.解析ModelAndView的视图名字
        3.拼接视图名字,找到对应的视图 hello然后进行拼接   /WEB-INF/jsp/hello.jsp
        4.将数据渲染到这个视图上
        -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    
  3. 编写controller

    package com.hty.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    //在类上加RequestMapping就相当于是下面所有的RequestMapping都要先加这个然后再加其自己的地址
    //@RequestMapping("/hello")
    public class HelloController {
    
        @RequestMapping("/hello")
        public String hello(Model model){
            //封装数据 可以在jsp中直接取到
            model.addAttribute("msg","Hello,SpringMVCAnnoation");
    
            return "hello";//会被视图解析器处理
        }
    }
    
  4. 编写hello.jsp

    <%--
      Created by IntelliJ IDEA.
      User: hty
      Date: 2022-02-23
      Time: 17:26
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        ${msg}
    </body>
    </html>
    
  5. 启动服务器

SpringMVC必须配置的三大组件

  • 处理器映射器
  • 处理器适配器
  • 视图解析器

通常我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置

6、Controller配置总结

6.1、控制器Controller

  • 控制器负责提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现
  • 控制器负责解析用户的请求并将其转换为一个模型
  • 在SpringMVC中一个控制器类可以包含多个方法

6.2、Controller的配置方式

在SpringMVC中,对于Controller的配置方式有很多种

6.2.1、实现Controller接口

Controller是一个接口,接口中只有一个方法

//处理请求且返回一个模型与视图的控制器
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {}

配置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">
    <!--1.配置DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

编写springmvc-servlet.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        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">

    <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
<!--    <context:component-scan base-package="com.hty.controller"/>-->
    <!--让spring MVC不处理静态资源  css  js  html  mp3  mp4-->
<!--    <mvc:default-servlet-handler/>-->
    <!--支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须向上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理
        而annotation-driver配置帮助我们自动完成上述两个实例的注入
    -->
<!--    <mvc:annotation-driven/>-->


    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--视图解析器:DispatcherServlet给他的ModelAndView
    1.获取了ModelAndView的数据
    2.解析ModelAndView的视图名字
    3.拼接视图名字,找到对应的视图 hello然后进行拼接   /WEB-INF/jsp/hello.jsp
    4.将数据渲染到这个视图上
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

编写ControllerTest1测试类实现Controller接口

package com.hty.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

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

//只要实现了Controller接口的类 说明这就是一个控制器
public class ControllerTest1 implements Controller {
    //返回一个视图对象
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("msg","HelloSpringMVC");

        modelAndView.setViewName("test");

        return modelAndView;
    }
}

将ControllerTest1类配置到spring配置文件中

<bean id="/t1" class="com.hty.controller.ControllerTest1"/>

最后进行测试即可

注:

  • 实现Controller接口定义控制器是比较老的方法
  • 缺点是:一个控制器只有一个方法,如果要多个方法则需要定义多个controller,定义的方式比较麻烦

6.2.2、使用@Controller注解

  • @Controller注解类型用于声明Spring类的实例是一个遥控器(在Spring的IOC部分还有另外三个注解)

  • Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器,为了保证Spring能找到控制器,需要在配置文件中声明组件扫描

    <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
    <context:component-scan base-package="com.hty.controller"/>
    
  • 增加一个ControllerTest2类,使用注解实现

    package com.hty.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    //代表这个类会被spring接管,被这个注解的类中所有方法,如果返回值String,并且有具体页面可以跳转,那么就会被视图解析器解析
    @Controller
    public class ContollerTest2 {
    	//映射访问路径
        @RequestMapping("/t2")
        public String index(Model model){
            //SpringMVC会自动实例化一个Model对象用于向视图中传值
            model.addAttribute("msg","ControllerTest2");
            return "test";
        }
    }
    
  • 然后可以直接进行测试

我们于是就可以发现虽然指向同一个视图,但是返回不同的结果,从这里看出,视图是可以复用的,而且控制器与视图之间是弱耦合关系

7、@RequestMapping说明

@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法,可以用于类或方法上,用于类上,表示类中的所有响应请求的方法都是以改地址作为父路径

其实就是类似于javaweb中servlet在web.xml进行注册访问地址一样

案例

我们让所有的请求前都加上myweb

package com.hty.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/myweb")
public class ControllerTest3 {
    @RequestMapping("/t1")
    public String test1(Model model){
        model.addAttribute("msg","myweb");
        return "test";
    }
}

这样访问的时候就需要加上/myweb

在这里插入图片描述

8、RestFul风格

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

功能

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

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

http://127.0.0.1/item?id=1

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

http://127.0.0.1/item/1 查询 GET

在spingMVC中可以使用@PahtVariable注解,让方法参数的值对应绑定到一个URL模板变量上,添加method参数后可以改变请求方式,此时只有DELETE方式可以访问,或者使用@DeleteMapping("/add/{a}/{b}")也可以

package com.hty.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class RestFulController {
    //传统方式 http://localhost:8080/springMVC_04_controller_war_exploded/add?a=1&b=2
    @RequestMapping("/add")
    public String test1(int a,int b,Model model){
        int res = a+b;
        model.addAttribute("msg","a+b="+res);
        return "test";
    }

    //Restful风格  http://localhost:8080/springMVC_04_controller_war_exploded/add/a/b
    @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
    //@DeleteMapping("/add/{a}/{b}")
    public String test2(@PathVariable int a,@PathVariable int b, Model model){
        int res = a+b;
        model.addAttribute("msg","a+b="+res);
        return "test";
    }
}

我们使用一个表单页面去请求

<%--
  Created by IntelliJ IDEA.
  User: hty
  Date: 2022-02-24
  Time: 0:09
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="add" method="delete">
        <input type="text" name="a">
        <input type="text" name="b">
        <input type="submit">
    </form>
</body>
</html>

使用这种风格的好处

  • 使路径变的更加简洁
  • 获得参数更加方便,框架会自动进行类型转换
  • 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法

小结:

springmvc中的@RequestMapping注解能够处理HTTP请求的方法,比如GET,PUT.POST,DELETE以及PATCH

9、结果跳转方式

9.1、使用Controller+视图解析器

在前面的文章中已经重复多次,在这里不赘述

9.2、使用原生的servlet来进行转发和重定向

package com.hty.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

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

@Controller
public class ModelTest1 {

    @RequestMapping("/m1/t1")
    public String test(HttpServletRequest req, HttpServletResponse resp){
        HttpSession session = req.getSession();

        System.out.println(session.getId());

        return "test";

    }
}

9.3、使用springmvc实现转发和重定向

不配置视图解析器

package com.hty.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

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

@Controller
public class ModelTest1 {

    @RequestMapping("/m1/t1")
    public String test1(Model model){
        model.addAttribute("msg","hello1");
        //请求转发的方式
        return "/WEB-INF/jsp/test.jsp";
    }

    @RequestMapping("/m1/t2")
    public String test2(Model model){
        model.addAttribute("msg","hello2");
        //请求转发的方式 显示的声明
        return "forward:/WEB-INF/jsp/test.jsp";
    }

    @RequestMapping("/m1/t3")
    public String test3(Model model){
        model.addAttribute("msg","hello3");
        //重定向
        return "redirect:/index.jsp";
    }
}

注意:转发是服务器内部的,重定向是客户端的,重定向是让客户端去访问重定向的地址,而WEB-INF下的文件是不能通过外部访问的!所以我们不能通过重定向访问WEB-INF下的test.jsp

配置视图解析器之后,转发的地址只需要写一个jsp页面的名称即可,但是重定向依然要写关键字Redirect

package com.hty.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

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

@Controller
public class ModelTest1 {

    @RequestMapping("/m1/t1")
    public String test1(Model model){
        model.addAttribute("msg","hello1");
        //请求转发的方式
        return "test";
    }
    
    @RequestMapping("/m1/t2")
    public String test3(Model model){
        model.addAttribute("msg","hello2");
        //重定向
        return "redirect:/index.jsp";
    }
}

10、数据处理

10.1、从前端接收数据

10.1.1、提交的参数名称和方法参数名一样

提交数据:http://localhost:8080/springMVC_04_controller_war_exploded/user/t1?username=hty

处理方法

package com.hty.controller;

import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

    @GetMapping("/t1")
    public String test1(String name, Model model){
        //接收前端参数
        System.out.println(name);

        //将结果传递给前端
        model.addAttribute("msg",name);

        //跳转视图
        return "test";
    }
}

控制台输出:hty

10.1.2、提交的参数名称和方法参数名不一样

package com.hty.controller;

import com.hty.pojo.User;
import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

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

    @GetMapping("/t1")
    //使用@RequestParam可以设置从前端接收的参数的名称是什么 此时访问地址就是
    //http://localhost:8080/springMVC_04_controller_war_exploded/user/t1?username=hty
    public String test1(@RequestParam("username") String name, Model model){
        //接收前端参数
        System.out.println(name);

        //将结果传递给前端
        model.addAttribute("msg",name);

        //跳转视图
        return "test";
    }
}

10.1.3、提交的是一个对象

package com.hty.controller;

import com.hty.pojo.User;
import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/user")
public class UserController {
    //前端接收了一个对象 有id  name  age属性
    //http://localhost:8080/springMVC_04_controller_war_exploded/user/t2?id=1&name=hty&age=18
    //springmvc会自动进行属性注入
    @GetMapping("/t1")
    public String test2(User user){
        System.out.println(user);
        return "test";
    }
}

10.2、回传数据给前端

10.2.1、使用ModelAndView

上文已经写过

10.2.2、使用model对象

上文已经写过

10.2.3、使用ModelMap

@GetMapping("/t3")
public String test3(ModelMap modelMap){

    modelMap.addAttribute("msg","hello");

    return "test";
}

10.2.4、区别

model:只有少数几个方法,只适合于存储数据,简化了新手对于Model对象的操作和理解

ModelMap:继承了LinkedHashMap,除了实现自身的一些方法,同样的继承了LinkedHashMap的方法和特性

ModelAndView:可以在存储数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转

10.3、乱码问题

后端接收到中文之后,发送给前端显示,出来是乱码

package com.hty.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/e")
public class EncodingController {

    @PostMapping("/t1")
    public String test1(@RequestParam("name") String name, Model model){
        model.addAttribute("msg",name);
        return "test";
    }
}

在这里插入图片描述

第一种解决方式:自定义过滤器

package com.hty.filter;

import javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

在web.xml中进行注册

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.hty.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <!--这里一定要注意是/* 表示也要过滤jsp文件-->
    <url-pattern>/*</url-pattern>
</filter-mapping>

这样可以解决get方法的乱码问题,但是不能解决post方法的乱码问题

第二种解决方式:使用springmvc的过滤器

web.xml配置

<!--springmvc中自带的过滤器-->
<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <!--这里一定要注意是/* 表示也要过滤jsp文件-->
    <url-pattern>/*</url-pattern>
</filter-mapping>

第三种解决方式:前两种方式都不能解决post的乱码问题那么就需要修改tomcat的配置文件,设置编码

修改conf目录下的server.xml,在第69行的代码进行修改

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding="UTF-8"/>

第四种解决方式:如果还是不能解决,那么就需要在网上寻找自定义过滤器

11、JSON

  • json是一种轻量级的数据交换格式,目前使用特别广泛
  • 采用完全独立编程语言的文本格式来存储和表示数据
  • 简介和清晰的层次结构使得json成为理想的交换语言
  • 易于人阅读和编写,同时也易于及其解析和生成,并有效的提升网络传输效率

JS语言中,一切都是对象,因此,任何JS支持的类型都可以通过json来表示,例如字符串,数字,对象,数组等,语法格式

  • 对象表示为键值对,数据由逗号分隔
  • 花括号保存对象
  • 方括号保存数组

JSON键值对都是用来保存JS对选哪个的一种方法,写法

{"name":"hty"}
{"age":"3"}
{"sex":"男"}

11.1、JSON和JS对象转换

JSON->JS

var obj = JSON.parse({"a":"hello","b":"World"});
//结果是 {a:'Hello',b:'World'}

JS->JSON

var json = JSON.stringify({a:'Hello',b:'World'});
//结果是 '{"a":"hello","b":"World"'

案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        //编写一个javascript对象
        var user = {
            name : "hty",
            age : 3,
            sex : "男"
        }

        //将js对象转换为json对象
        var json = JSON.stringify(user);
        console.log(json);

        //将json对象转换为js对象
        var js = JSON.parse(json);
        console.log(js);
    </script>
</head>
<body>

</body>
</html>

11.2、jackson

json解析工具,还有fastjson等

使用jackson还需要导入jar包

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

案例

package com.hty.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hty.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {

    //使用produces可以解决乱码问题
    @RequestMapping(value = "/j1",produces = "application/json;charset=UTF-8")
    @ResponseBody //不会走视图解析器 会直接返回一个字符串 或者在类上使用RestController也可以实现
    public String json1() throws JsonProcessingException {
        //jackson ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        //创建一个对象
        User user = new User("hty",18,"男");
		
        //使用和这个方法可以把一个对象转换为json字符串
        String s = mapper.writeValueAsString(user);
        return s;
    }
}

使用writeValueAsString方法可以将对象转化为json字符串格式

11.3、乱码问题解决方案

由于produces属性解决的时候过于麻烦,我们可以使用spring配置统一指定

<mvc:annotation-driven>
    <mvc:message-converters>
        <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>

只需要对mvc:annotation-driven标签进行配置即可

11.4、使用jackson将集合转换为json格式

使用方式和单个对象一样,生成的结果是

[{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"}]

两边会用中括号括起来

11.5、使用jackson将时间转换为json格式

ObjectMapper时间解析后的默认格式为:Timestamp 时间戳

要想改为自定义格式,需要使用SimpleDateFormat类来进行格式化

public String json3() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    Date date = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String format = sdf.format(date);
    String s = mapper.writeValueAsString(format);
    return s;
}

使用ObjectMapper进行格式化输出

public String json3() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    //关闭时间戳
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    mapper.setDateFormat(sdf);
    Date date = new Date();
    String s = mapper.writeValueAsString(date);
    return s;
}

11.6、jackson工具类的编写

package com.hty.util;

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

import java.text.SimpleDateFormat;

public class JsonUtil {
    /**
     * @param object 需要转换的对象
     * @param dateformat 如果是日期那就需要传入日期格式 例如 "yyyy-MM-dd HH:mm:ss"
     * @return 返回的是一个json格式的字符串
     * */
    public static String getJson(Object object,String dateformat){
        ObjectMapper mapper = new ObjectMapper();
        //关闭时间戳
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
        SimpleDateFormat sdf = new SimpleDateFormat(dateformat);
        mapper.setDateFormat(sdf);

        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return null;
    }
    
    /**
     * @param object 需要转换的对象
     * @return 返回的是一个json格式的字符串
     * */
    public static String getJson(Object object){
        return getJson(object,"yyyy-MM-dd HH:mm:ss");
    }
}

12、SSM框架整合

项目地址

E:\编程\java项目\狂神说ssm框架整合

13、Ajax技术

  • Asynchronous JavaScript and XML(异步的JS和XML)
  • Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
  • Ajax不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术
  • Ajax就是在百度搜索的时候会自动在搜索框下面显示出来可能需要的搜索关键词,完成自动补充
  • 传统的网页(即不用ajax技术的网页)想要更新内容或者提交一个表单,都需要重新加载整个网页
  • 使用ajax技术的网页通过在后台服务器进行少量的数据交换,就可以实现异步局部更新
  • 使用Ajax用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面

我们可以使用jQuery中的ajax库来进行实现

语法:$.ajax({name:value, name:value, ... })

名称值/描述
async布尔值,表示请求是否异步处理。默认是 true。
beforeSend(xhr)发送请求前运行的函数。
cache布尔值,表示浏览器是否缓存被请求页面。默认是 true。
complete(xhr,status)请求完成时运行的函数(在请求成功或失败之后均调用,即在 success 和 error 函数之后)。
contentType发送数据到服务器时所使用的内容类型。默认是:“application/x-www-form-urlencoded”。
context为所有 AJAX 相关的回调函数规定 “this” 值。
data规定要发送到服务器的数据。
dataFilter(data,type)用于处理 XMLHttpRequest 原始响应数据的函数。
dataType预期的服务器响应的数据类型。
error(xhr,status,error)如果请求失败要运行的函数。
global布尔值,规定是否为请求触发全局 AJAX 事件处理程序。默认是 true。
ifModified布尔值,规定是否仅在最后一次请求以来响应发生改变时才请求成功。默认是 false。
jsonp在一个 jsonp 中重写回调函数的字符串。
jsonpCallback在一个 jsonp 中规定回调函数的名称。
password规定在 HTTP 访问认证请求中使用的密码。
processData布尔值,规定通过请求发送的数据是否转换为查询字符串。默认是 true。
scriptCharset规定请求的字符集。
success(result,status,xhr)当请求成功时运行的函数。
timeout设置本地的请求超时时间(以毫秒计)。
traditional布尔值,规定是否使用参数序列化的传统样式。
type规定请求的类型(GET 或 POST)。
url规定发送请求的 URL。默认是当前页面。
username规定在 HTTP 访问认证请求中使用的用户名。
xhr用于创建 XMLHttpRequest 对象的函数。

14、拦截器

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

过滤器与拦截器的区别:拦截器AOP思想的决堤应用

拦截器:

  • 是springmvc框架自己的,只有使用了springmvc框架的工程才能使用
  • 拦截器只会拦截访问的控制器方法,如访问的是jsp/html/css/image/js是不会拦截的

14.1、自定义拦截器

实现HandlerInterceptor接口

package com.hty.config;

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

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

public class MyInterceptor implements HandlerInterceptor {
    //return true  执行下一个拦截器,放行
    //return false 执行下一个拦截器,放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        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("=============清理==============");
    }
}

在applicationContext.xml中需要进行配置

<!--拦截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--包括这个请求下面的所有请求-->
        <mvc:mapping path="/**"/>
        <bean class="com.hty.config.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

14.2、登陆拦截

网站不登录不能访问主页

package com.hty.config;

import org.springframework.web.servlet.HandlerInterceptor;

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


public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        //放行的判断

        //已经在登陆页面了
        if(request.getRequestURI().contains("login")){
            return true;
        }
        //已经注册了
        if(session.getAttribute("userLoginInfo") != null){
            return true;
        }

        //判断什么情况下没有登陆
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false;
    }
}

注:一定要在spring配置文件进行注册才行

14.3、小细节

在web目录下的jsp文件拦截器不会进行拦截

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值