Spring-MVC Json SSM框架整合学习

1、概念

名称        职责
Model模型:即业务模型,负责完成业务中的数据通信处理,对应项目中的 service和dao
View视图:渲染数据,生成页面。对应项目中的Jsp
Controller控制器:直接对接请求,控制MVC流程,调度模型,选择视图。对应项目中的Servlet

2、开发流程

 2.1   导入依赖:spring-webmvc

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

2.2  配置核心(前端)控制器:

前端向后端发起请求 无法直接请求到SpringMVC 所以MVC框架设计了一款前端控制器 选型在 Servlet 或 Filter两者之一 在框架最前沿率先工作 接收所有请求。

配置的所有请求都要找到 DispatcherServlet ====> SpringMVC ======> mvc.xml 

MVC ==== >  返回给前端时也通过了一些过程

<servlet>
    <servlet-name>mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 局部参数:声明配置文件位置 -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:mvc.xml</param-value>
    </init-param>
    <!-- Servlet启动时刻:可选 -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

  2.3  mvc.xml

<beans 	xmlns="http://www.springframework.org/schema/beans"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:mvc="http://www.springframework.org/schema/mvc"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          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
							http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 告知springmvc  使用的那些包需要注解式开发 -->
    <context:component-scan base-package="com.qf.controller"></context:component-scan>
    <!-- 注册注解开发驱动 -->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

2.4  小案例:配置文件需要加入视图解析器 

//通过Controller 将HelloAction注入到容器中
//配置的前置处理器就可以找到 ====> Action
//根据一级目录找到类 根据二级目录找到方法
//return 表示你要响应前端那个页面
//写完的页面需要MVC视图解析器 解析后才能显示 解析在返回值的前后拼接 ==> "/index.jsp"-->
@Controller
@RequestMapping("/hello")
public class HelloAction {
    @RequestMapping("/test7")
    public String test1(){
        System.out.println("hello");
        return "index";
    }
}
<!-- 视图解析器作用:
                    1.捕获后端控制器的返回值="index"
                    2.解析在返回值的前后 拼接 ==> "/index.jsp"-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

3、接收请求参数

 3.1  前端通过地址 给后端传值 基本数据类型 请求参数的方法的形参 同名即可

@Controller
@RequestMapping("/param")

//前端通过地址给后端传值
//http://localhost:8080/param/demo1?id=1&name=Tom&sex=false&birthday=2023/2/9

public class ParamAction {
    @RequestMapping("/demo1")
    public String demo1(Integer id, String name, Boolean sex, Date birthday){

        System.out.println(id);
        System.out.println(name);
        System.out.println(sex);
        System.out.println(birthday);
        return "index";
    }

    @RequestMapping("/demo2")
    public String demo2(User user){
        System.out.println(user);
        return "index";
    }
}

3.2  实体接收参数

public class User {
    private Integer id;
    private String name;
    private Boolean sex;
    private Date birthday;

    // 构造器 get set toString 
    // 路径 id=?&name=?...
}

3.3  数组收参

@RequestMapping("/demo3")
    public String demo3(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "form";
//hobby=football&hobby=basketball
<form action="/param/demo3" method="post">
    足球:<input type="checkbox" name="hobby" value="football">
    篮球:<input type="checkbox" name="hobby" value="basketball">
    网球:<input type="checkbox" name="hobby" value="wq">
    <input type="submit" value="保存">
</form>

3.4  集合接收(了解)

<form action="/param/demo4" method="post">
    id:<input type="text" name="users[0].id"/>编号
    name:<input type="text" name="users[0].name"/>姓名
    sex:<input type="text" name="users[0].sex"/>性别
    id:<input type="text" name="users[1].id"/>编号
    name:<input type="text" name="users[1].name"/>姓名
    sex:<input type="text" name="users[1].sex"/>性别
    <input type="submit" value="保存">
</form>
@RequestMapping("/demo4")
    public String demo4(UserList users){
        System.out.println(users.getUsers());
        return "form";
public class UserList {
    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
//users[0].id=1&users[0].name=zhangsan&users[0].birth=2018-12-12&users[1].id=2&....          注:地址栏不能有符号:[] 
}

3.5  路径参数 RestFul风格

//获取RestFul风格的参数
    @RequestMapping("/demo5/{id}")
    public String demo5(@PathVariable("id") Integer id){
        System.out.println(id);
        return "index";
    }

3.6  中文乱码问题

3.6.1  首先页面中字符集统一

JSP : <%@page  pageEncoding="utf-8" %>
HTML : <meta charset="UTF-8">

3.6.2  其次,tomcat中字符集设置,对get请求中,中文参数乱码有效

Tomcat server.xml 配置:URIEncoding=utf-8
<Connector connectionTimeout="20000"port="8080" protocol="HTTP/1.1"redirectPort="8443" maxPostSize="0" URIEncoding="UTF-8"/>

3.6.3  最后,设置此filter,对post请求中,中文参数乱码有效

<!-- 此过滤器会进行:request.setCharactorEncoding("utf-8"); -->
<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>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4、请求转发 重定向

4.1  请求转发:

@SuppressWarnings("{all}")
@Controller
@RequestMapping("/hello")
public class HelloAction {
    @RequestMapping("/test7")
    public String test1(){
        System.out.println("hello");
        return "index";
    }
    @RequestMapping("/forward")
    public String forward2(){
        System.out.println("forward");
        //绝对路径:要访问到8080后的绝对路径
        return "forward:/hello/test7";
        //return "forward:test7";  访问相对路径
        //return test1();  实现调方法也可以实现
    }
}

4.2  重定向

@Controller
@SuppressWarnings({"all"})
@RequestMapping("/redir")
public class RedirectController {
    @RequestMapping("/test1")
    public String test1(){
        System.out.println("test redirect1");
        return "redirect:test1";
    }
    @RequestMapping("test2")
    public String testRedirect2(){
        System.out.println("test testRedirect2");
        return "redirect:/index.jsp";
    }
}

5、接传值

 5.1  导入jitl依赖

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
</dependency>

 5.2  Request和Session

@RequestMapping("/request")
    public String request(HttpServletRequest request, HttpSession session){
        System.out.println(request);
        System.out.println(session);
        //通过后端给前端传值
        request.setAttribute("request","request");
        session.setAttribute("session","session");
        return "index";
    }

5.3  JSP中取值

//jsp中用EL表达式 取值即可
${requestScope.request}
${sessionScope.session}

5.4  model  model中的数据,会在V渲染之前,将数据复制一份给request

//在jsp中直接取值:${requestScope.model}
@RequestMapping("/model")
    public String model(Model model){
        System.out.println(model);
        model.addAttribute("model","model");
        return "index";
    }

5.5  ModelAndView

 @RequestMapping("/modelAndView")
    public ModelAndView modelAndView(){
        //新建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        System.out.println(mv);
        //设置视图名 即如何跳转
        mv.setViewName("forward:/index.jsp");//表示你要到那个页面去 请求转发/重定向
        //给前端传modelAndView  增加数据
        mv.addObject("modelAndView","modelandview");
        return mv;
        //${requestScope.modelAndView}  JSP直接取值
    }

5.6  @SessionAttributes(不好使

@Controller
@SessionAttributes(names={"gender","name"}) // model中的 name和gender 会存入session中
public class UserController {

    @RequestMapping("/hello")
    public String hello(Model m){
        m.addAttribu te("gender",true); // 会存入session
        m.addObject("name","zhj"); // 会存入session   //不推荐
        return "index";
    }
    
    //jsp中用EL表达式 取值即可
	${sessionScope.name}
    ${sessionScope.gender}
    
    @RequestMapping("/hello2")
    public String hello(SessionStatus status){
        // 移除通过SessionAttributes存入的session
        status.setComplete();
        return "index";
    }
}

6、静态资源

 6.1  静态资源问题

静态文件没有url-pattern 所以默认是访问不到的,之所以可以访问,是因为,tomcat中有一个全局的servlet:org.apache.catalina.servlets.DefaultServlet,它的url-pattern"/",是全局默认的Servlet. 所以每个项目中不能匹配的静态资源的请求,有这个Servlet来处理即可但在SpringMVC中DispatcherServlet也采用了 “/” 作为url-pattern, 则项目中不会再使用全局的Serlvet,则静态资源不能完成访问

6.2  解决方案1:

DispathcerServlet采用其他的url-pattern  此时,所有访问handler的路径都要以 action结尾!!

<servlet>
  	<servlet-name>mvc9</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>mvc9</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

@RequestMapping("/test1")
public String test1(){
	System.out.println("test");
	return "forward:test2.action";
}
@RequestMapping("/test2")
public String test2(){
	System.out.println("test2");
	return "index";
}

6.3  解决方案2:DispathcerServlet的url-pattern依然采用 "/",但追加配置

<!-- 
  额外的增加一个handler,且其requestMapping:  "/**" 可以匹配所有请求,但是优先级最低
  所以如果其他所有的handler都匹配不上,请求会转向 "/**" ,恰好,这个handler就是处理静态资源的
  处理方式:将请求转会到tomcat中名为default的Servlet
  -->
<mvc:default-servlet-handler/>

7、SSM整合 (环境搭建)

7.1  Springjar包的依赖体系

      

一、 Core Container

1. spring-core:依赖注入IoC与DI的最基本实现

2. spring-beans:Bean工厂与bean的装配

3. Spring Context:在基础IOC功能上提供扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持(不常用)

4. Spring Context Support:Spring context的扩展支持,用于MVC方面(不常用)

5. spring-expression:spring表达式语言(不常用)

二、  AOP Aspects Instrumentation Messaging

1. spring-aop :提供了面向切面编程的实现,它允许你定义拦截器 (interceptors) 和 切点 (pointcuts),用以解耦(decouple) 关注点不同的代码

2. Aspects :spring-aspects   AOP

3. spring-instrument: 提供了用于某些应用程序服务器的类工具支持和类加载器(ClassLoader)实现(不常用)

4. spring-instrument-tomcat 是 Spring instrumentation agent for Tomcat (不常用)

三、 Data Access

1. spring-jdbc为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理

2. spring-tx:事务控制

3. spring-orm:对象关系映射,集成orm框架(不常用)

4. spring-oxm:对象xml映射(不常用)

5. spring-jms:java消息服务(不常用)

四、 Web

1. Spring websocket:提供 Socket通信, web端的推送功能(不常用)

2. Servlet

3. Spring web:包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类

4. Spring webmvc portlet:Spring MVC的增强(不常用)

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>com.qf</groupId>
    <artifactId>java2207-SpringMVC-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
        <!--设置为web项目-->
    <packaging>war</packaging>

    <dependencies>



        <!--AOP面向切面编程-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>

        <!--web中引入MVC导入的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>
        <!--Spring JDBC依赖对JDBC的支持-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>
        <!--jstl JSP的依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- Spring整合mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>

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

        <!-- mysql驱动 依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
            <scope>runtime</scope>
        </dependency>

        <!-- 德鲁伊连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>

        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <!-- 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.1.10</version>
        </dependency>


    </dependencies>

</project>

五、applicationContext.Xml(resources)下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- DataSource -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!--基本配置-->
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="${jdbc.init}"/>
        <property name="minIdle" value="${jdbc.minIdle}"/>
        <property name="maxActive" value="${jdbc.maxActive}"/>

        <!-- 配置获取连接等待超时的时间 ms-->
        <property name="maxWait" value="60000"/>

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000"/>

        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000"/>
    </bean>
    <!-- SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入连接池 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 注入dao-mapper文件信息 ,如果映射文件和dao接口 同包且同名,则此配置可省略-->
        <property name="mapperLocations">
            <list>
                <value>classpath:com/qf/dao/*.xml</value>
            </list>
        </property>
        <!-- 为 dao-mapper文件中的实体 定义缺省包路径
            如:<select id="queryAll" resultType="User"> 中 User类可以不定义包

        <property name="typeAliasesPackage" value="com.qf.entity"></property>-->

        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <props>
                            <!-- 页号 调整到合理的值  0  max -->
                            <prop key="reasonable">true</prop>
                        </props>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
    <!-- DAO  MapperScannerConfigurer dao层的自动注入 -->
    <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.qf.dao"></property>
        <!-- 如果工厂中只有一个SqlSessionFactory的bean,此配置可省略 -->
        <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>-->
    </bean>
    <!-- 为导致Spring 与 SpringMVc 自动注入的bean不冲突自动注入的bean
     expression="org.springframework.stereotype.Controller扫描包,并排除Controller -->
    <context:component-scan base-package="com.qf" use-default-filters="true">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <!-- 引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑 -->
    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- @Transactional -->
    <tx:annotation-driven transaction-manager="tx"/>
</beans>

六、SpringMVC配置文件(mvc.xml)

<beans 	xmlns="http://www.springframework.org/schema/beans"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:mvc="http://www.springframework.org/schema/mvc"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          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
							http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 告知springmvc  使用的那些包需要注解式开发 -->
    <context:component-scan base-package="com.qf.controller"></context:component-scan>
    <!-- 注册注解开发驱动 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 视图解析器
	     作用:1.捕获后端控制器的返回值="index"
	          2.解析: 在返回值的前后 拼接 ==> "/index.jsp"-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

<!--    <context:component-scan base-package="com.qf"/>-->
    <!--
    <context:component-scan base-package="com.zhj" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    -->

</beans>

七、jdbc.properties(resources)

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/qf.edu?useSSL=false&useUnicode=true&characterEncoding=UTF8
jdbc.username=root
jdbc.password=1234
jdbc.init=1
jdbc.minIdle=1
jdbc.maxActive=3

八、Mapper.xml 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:所需实现的接口全限定名-->
<mapper namespace="com.qf.dao.AdminDao">
    <sql id="repeatSql">
        select * from admin
    </sql>
    <select id="queryAdmins" resultType="com.qf.pojo.Admin">
        <include refid="repeatSql"></include>
    </select>
</mapper>

 九、web.xml(配置前端处理器)src\main\webapp\web\inf\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">

<!--  导入前端控制器  首先接收前端请求 也就是Servlet/Filter 在框架最前沿工作 接收前端请求-->
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 局部参数:声明配置文件位置 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:mvc.xml</param-value>
        </init-param>
        <!-- Servlet启动时刻:可选 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 此过滤器会进行:request.setCharactorEncoding("utf-8"); -->
    <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>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <!-- 启动Spring工厂 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>


</web-app>

 十、demo

 实体:

public class Admin {
    private String username;
    private String password;
    private String phone;
    private String address;
//get set toString 构造器 可以使用lomBok
}

dao层:

public interface AdminDao {
    List<Admin> queryAdmins();
}

service层(接口):

public interface AdminService {
    List<Admin> queryAll();
}

接口实现类:

@Service("adminService")
public class AdminServiceImpl implements AdminService{
    @Autowired
    private AdminDao adminDao;

    @Override
    public List<Admin> queryAll() {
        return adminDao.queryAdmins();
    }
}

controller层:

/**
 * @author S7
 * @version 1.0
 */
@Controller
@RequestMapping("/admin")
public class AdminAction {

    @Autowired
    private AdminService adminService;
    @RequestMapping("/queryAll")
    public String queryAll(Model model){
        List<Admin> list = adminService.queryAll();
        model.addAttribute("list",list);
        return "admin";
    }
}

八、Json

 8.1  环境搭建resources下:(beans.xml)(1.视图解析器 2.注册开发驱动 3.解决中文乱码问题)

<beans 	xmlns="http://www.springframework.org/schema/beans"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:mvc="http://www.springframework.org/schema/mvc"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          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
							http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!-- 告知springmvc  使用的那些包需要注解式开发 -->
    <context:component-scan base-package="com.qf.controller"></context:component-scan>
    <!-- 注册注解开发驱动 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 视图解析器
	     作用:1.捕获后端控制器的返回值="index"
	          2.解析: 在返回值的前后 拼接 ==> "/index.jsp"-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--    <context:component-scan base-package="com.qf"/>-->
    <!--
    <context:component-scan base-package="com.zhj" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    -->
<!--  编码格式  -->
    <mvc:default-servlet-handler/>

</beans>

8.2  pom.xml(1.设置成web项目 2.导入web-mvc依赖3.导入Json所需要的 Jaskson依赖)

<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>

    <groupId>com.qf</groupId>
    <artifactId>java2207Springmvc-json-ssm</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <packaging>war</packaging>

    <dependencies>

        <!--web中引入MVC导入的依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>

        <!-- Jackson springMVC默认的Json解决方案选择是 Jackson,所以只需要导入jackson的jar,即可使用。-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <!--FastJson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.54</version>
        </dependency>



    </dependencies>
</project>

8.3 web.xml(1.导入前端控制器 2.DispatcherServlet 声明配置文件位置classpath 3.设置过滤器)

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

    <!--  导入前端控制器  首先接收前端请求 也就是Servlet/Filter 在框架最前沿工作 接收前端请求-->
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 局部参数:声明配置文件位置 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:beans.xml</param-value>
        </init-param>
        <!-- Servlet启动时刻:可选 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 此过滤器会进行:request.setCharactorEncoding("utf-8"); -->
    <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>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

8.4.1 demo实体

/**
 * @author S7
 * @version 1.0
 */
public class User {
    @JsonProperty("new_id")//传给前端的数据id属性 名称更改为new_id
    private String name;
    //@JsonIgnore  注释在那个属性上面那个属性就不会传到前端
    //若"name==null" 忽略此属性 此处测试的是List
    //@JsonInclude(JsonInclude.Include.NON_NULL)
    private Integer id;
    @JsonFormat(pattern = "yyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date birthday;
    @JsonInclude(value= JsonInclude.Include.NON_EMPTY)  // 若hobby长度为0或==null 忽略此属性
    private List<String> hobby;

    //自定义序列化
    @JsonSerialize(using = MySerializer.class)
    private Double salary = 1000.111;

    public User(String name, Integer id, Date birthday, List<String> hobby, Double salary) {
        this.name = name;
        this.id = id;
        this.birthday = birthday;
        this.hobby = hobby;
        this.salary = salary;
    }

    public User(String name, Integer id) {
        this.name = name;
        this.id = id;
    }


    public List<String> getHobby() {
        return hobby;
    }

    public void setHobby(List<String> hobby) {
        this.hobby = hobby;
    }

    public User(String name, Integer id, Date birthday) {
        this.name = name;
        this.id = id;
        this.birthday = birthday;
    }

    public User(String name, Integer id, Date birthday, List<String> hobby) {
        this.name = name;
        this.id = id;
        this.birthday = birthday;
        this.hobby = hobby;
    }

    public User() {
    }

    public String getName() {
        return name;
    }

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

    public Integer getId() {
        return id;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", birthday=" + birthday +
                ", hobby=" + hobby +
                ", salary=" + salary +
                '}';
    }
}

8.4.2 测试类

//前端访问路径 通过json给前端传值
//@Controller + @ResponseBody = @RestController加载类上
@RestController
@RequestMapping("/json")
public class JsonAction {

    @RequestMapping("/test1")
    //@ResponseBody
    public User test1(){
        User user = new User("tom",101);
        return user;
    }

    @RequestMapping("/test2")
    //@ResponseBody
    public List<User> test2(){
        List<User> list = new ArrayList<>();
        list.add(new User("jack",2));
        list.add(new User("S7",24));
        return list;//return 给通过json返给前端的请求
    }

//中文乱码问题 在@RequestMapping中设置
@RequestMapping(value="/test3",produces = "text/html;charset=utf-8")
//@ResponseBody

    public String test3(){
        return "宁";
    }

    @RequestMapping("/test4")
    public String test4(@RequestBody User user){
        //加上注释就能将传过来的Json串转换成对象
        System.out.println(user);
        return "ok";
    }

    @RequestMapping("/test5")
    public User test5(){
        return new User("s7",24,new Date());
    }
}

8.4.3 序列化工具类

public class MySerializer extends JsonSerializer<Double> {
    @Override
    public void serialize(Double aDouble, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String number = BigDecimal.valueOf(aDouble).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
        //输出四舍五入的值
        jsonGenerator.writeNumber(number);
    }
}

8.4.4 前端页面 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.6.1.min.js"></script>
    <script>
        $(function () {
            $("#btn1").click(function () {
                var user = {id:1,name:"tom",birthday:"2020-12-12"};
                $.ajax({
                    url: '/json/test4',//路径
                    type: 'post',//请求方式
                    contentType: "application/json",//声明请求参数类型为 json
                    data: JSON.stringify(user),// 转换js对象成json
                    success: function (data) {
                        console.log(data);
                    }
                });
            });
        })
    </script>
</head>
<body>
<button id="btn1">发送json</button>
<!--绑定单击事件 向后端发送json-->
</body>
</html>

8.4.5 Json依赖

<!-- Jackson springMVC默认的Json解决方案选择是 Jackson,所以只需要导入jackson的jar,即可使用。-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>
<!--FastJson-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.54</version>
</dependency>

8.4.6 Json常用注解:

1. 通过前端访问路径 通过json给前端传值 注解+@ResponseBody

2. @Controller + @ResponseBody = @RestController加载类上

3. @RequestMapping(value="/test3",produces = "text/html;charset=utf-8") 中文乱码问题设置

4. public String test4(@RequestBody User user) 加上@RequestBody注释将前端传入Json代码转换成想要的方式类对象

5. @JsonProperty("new_id")  传给前端的数据id属性 名称更改为new_id

6. @JsonIgnore 注释在那个属性上面那个属性就不会传到前端

7. @JsonInclude(JsonInclude.Include.NON_NULL)在类中显示对象属性为空的

8. @JsonInclude(value= JsonInclude.Include.NON_EMPTY) 定义在属性上 如果该属性为        null 或者 长度=0 则忽略此属性

9. @JsonFormat(pattern = "yyy-MM-dd HH:mm:ss", timezone = "GMT+8") 传给前端Data类型注释

10. 自定义序列化 @JsonSerialize(using = MySerializer.class)

例:将三位小数四舍五入

类  private Double salary = 1000.111;

public class MySerializer extends JsonSerializer<Double> {
    @Override
    public void serialize(Double aDouble, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String number = BigDecimal.valueOf(aDouble).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
        //输出四舍五入的值
        jsonGenerator.writeNumber(number);
    }
}

 九、异常解析器

 定义异常解析器,统一处理异常

Controller中的每个Handler不再自己处理异常,而是直接throws所有异常。定义一个“异常解析器” 集中捕获处理 所有异常 此种方案,在集中管理异常方面,更有优势!

前端发起请求后 到异常时候调用工具类:

@RequestMapping("/ex")
@RestController
public class ExceptionAction {
    @RequestMapping("/test1")
    public void test1(){
        System.out.println("todo");
        throw new NullPointerException("null----");
    }
}

工具类:com.qf.Exception.MyExResolver implements HandlerExceptionResolver

public class MyExResolver  implements HandlerExceptionResolver {
    /**
     * 异常解析器:主体逻辑
     * 执行时刻:当handler中抛出异常时,会执行:捕获异常,并可以跳到错误页面
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response, Object handler, Exception ex) {
        ex.printStackTrace();//打印异常栈
        //创建一个ModelAndView
        ModelAndView mv = new ModelAndView();
        //识别异常
        if (ex instanceof NullPointerException) {
            mv.setViewName("redirect:/error1.jsp");
        }else if(ex instanceof ClassCastException){
            mv.setViewName("redirect:/error2.jsp");
        }else{
            mv.setViewName("redirect:/error.jsp");
        }
        return mv;
    }

}

MVC.xml 

<!-- 声明异常解析器  -->	
<bean class="com.baizhi.exception.resolver.MyExResolver"></bean>

 十、拦截器(抽取handler中的冗余功能 )

//test1和test2方法产生了冗余
@RequestMapping("/inter")
@SessionAttributes("state")
public class InterController(){
    @RequestMapping("/login")
    public String login(Model mode){
        model.addAttribute("state","ok");
        return "index";
    }
    @RequestMapping("/test1")
    public String test1(Model model){
        if(model.asMap()).get("state") != null){
            System.out.println("service1");
            return "index";
        }else{
            return "login";
        }
    }
    @RequestMapping("/test1")
    public String test2(Model model){
        if(model.asMap()).get("state") != null){
            System.out.println("service1");
            return "index";
        }else{
            return "login";
        }
    }
}

 定义拦截器:

public class MyInter1 implements HandlerInterceptor{
	//主要逻辑:在handler之前执行:抽取handler中的冗余代码
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		System.out.println("pre~~~");
        /*
        response.sendRedirect("/springMVC_day2/index.jsp");//响应
        return false;//中断请求
        */
        /*
        HttpSession session = request.getSession();
        if(session.getAttribute("state") != null){
            return true;
        }
        */
		return true;//放行,后续的拦截器或handler就会执行
	}
	//在handler之后执行,响应之前:进一步的响应定制
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("post~~");
	}
	//在页面渲染完毕之后,执行:资源回收
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("after~~");
	}
}
//删除冗余代码
@RequestMapping("/login")
public String login(Model mode){
	model.addAttribute("state","ok");
	return "index";
}
@RequestMapping("/test1")
public String test1(Model model){
	System.out.println("service1");
    return "index";
}
@RequestMapping("/test1")
public String test2(Model model){
    System.out.println("service1");
    return "index";
}

配置拦截路径

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/inter/test1"/>
        <mvc:mapping path="/inter/test2"/>
        <mvc:mapping path="/inter/test*"/> <!-- test开头 -->
        <mvc:mapping path="/inter/**"/> <!-- /** 任意多级任意路径 -->
        <mvc:exclude-mapping path="/inter/a/**"/>   <!--不拦截此路径-->
        <bean class="com.baizhi.interceptor.MyInter1"></bean>   <!--拦截器类-->
    </mvc:interceptor>
</mvc:interceptors>

十一、上传

 11.1 导入jar包

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

11.2 表单

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

11.3 上传解析器

<!-- 上传解析器 
	     id必须是:“multipartResolver”
 -->
<bean id="multipartResolver" 
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 最大可上传的文件大小  单位:byte  超出后会抛出MaxUploadSizeExceededException异常,可以异常解析器捕获 1048576=1M tomcat7的几个版本好用,其他版本看不到效果-->
    <property name="maxUploadSize" value="1048576"></property>
</bean>

11.4 Handler

@RequestMapping("/test1")
public String hello1(String username,MultipartFile source,HttpSession session) {
    //文件的原始名称
    String filename = source.getOriginalFilename();
    //定制全局唯一的命名
    String unique = UUID.randomUUID().toString();
    //获得文件的后缀
    String ext = FilenameUtils.getExtension(filename);//abc.txt   txt    hello.html  html
    //定制全局唯一的文件名
    String uniqueFileName = unique+"."+ext;
    System.out.println("唯一的文件名:"+uniqueFileName);

    //文件的类型
    String type = source.getContentType();
    System.out.println("filename:"+filename+" type:"+type);

    //获得 upload_file的磁盘路径 ==> 在webapp目录下创建一个目录"upload_file",且此目录初始不要为空,否则编译时被忽略
    String real_path = session.getServletContext().getRealPath("/upload_file");
    System.out.println("real_path:"+real_path);

    //将上传的文件,存入磁盘路径中
    //source.transferTo(new File("d:/xxxx/xxxx/xx.jpg"))
    source.transferTo(new File(real_path+"\\"+uniqueFileName));
    return "index";
}

也可以在拦截器中拦截文件大小,并手动抛出MaxUploadSizeExceededException异常

 

public class MyFileUploadInterceptor implements HandlerInterceptor {
    private Long maxFileuploadSize;

    public Long getMaxFileuploadSize() {
        return maxFileuploadSize;
    }

    public void setMaxFileuploadSize(Long maxFileuploadSize) {
        this.maxFileuploadSize = maxFileuploadSize;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断上传文件大小  1048576
        ServletRequestContext servletRequestContext = new ServletRequestContext(request);
        // 文件大小 byte
        long l = servletRequestContext.contentLength();
        if(l>maxFileuploadSize){
            throw new MaxUploadSizeExceededException(maxFileuploadSize);
        }
        return true;
    }
}
//在异常解析器中处理
public class MyExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        if(e instanceof MyException1){
            // error1.jsp
            modelAndView.setViewName("redirect:/error1.jsp");
        }else if(e instanceof MyException2){
            // error2.jsp
            modelAndView.setViewName("redirect:/error2.jsp");
        }else if(e instanceof MyException3){
            // error3.jsp
            modelAndView.setViewName("redirect:/error3.jsp");
        }else if(e instanceof MaxUploadSizeExceededException){
            modelAndView.setViewName("redirect:/uploadError.jsp");
        }
        return modelAndView;
    }
}
	<!-- 拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--<mvc:mapping path="/inter/test1"/>
            <mvc:mapping path="/inter/test2"/>-->
            <mvc:mapping path="/inter/**"/>  <!-- /inter/a/test1   /inter/b/test2 -->
            <mvc:exclude-mapping path="/inter/login"/>
            <bean class="com.qf.interceptor.MyInterceptor"/>
        </mvc:interceptor>
		<!--上传文件大小拦截器-->
        <mvc:interceptor>
            <mvc:mapping path="/upload/test1"/>
            <bean class="com.qf.interceptor.MyFileUploadInterceptor">
                <property name="maxFileuploadSize" value="1048576"/>
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

十二 、下载

12.1 超链接 :

<a href="${pageContext.request.contextPath}/download/test1?name=Koala.jpg">下载</a>

12.2 Handler:

@RequestMapping("/test1")
public void hello1(String name,HttpSession session,HttpServletResponse response){
    System.out.println("name:"+name);
    //获得要下载文件的绝对路径
    String path = session.getServletContext().getRealPath("/upload_file");
    //文件的完整路径
    String real_path = path+"\\"+name;

    //设置响应头  告知浏览器,要以附件的形式保存内容   filename=浏览器显示的下载文件名
    response.setHeader("content-disposition","attachment;filename="+name);

    //读取目标文件,写出给客户端
    IOUtils.copy(new FileInputStream(real_path), response.getOutputStream());

    //上一步,已经是响应了,所以此handler直接是void
}

十三 、验证码

 13.1 作用:防止暴力攻击 前端安全保护

13.2 导入Jar包 

<!-- Kaptcha -->
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
    <exclusions>
        <exclusion>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

13.3 声明验证码组件

<servlet>
    <servlet-name>cap</servlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    <init-param>
      <param-name>kaptcha.border</param-name>
      <param-value>no</param-value>
    </init-param>
    <init-param>
      <param-name>kaptcha.textproducer.char.length</param-name>
      <param-value>4</param-value>
    </init-param>
    <init-param>
      <param-name>kaptcha.textproducer.char.string</param-name>
      <param-value>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</param-value>
    </init-param>
    <init-param>
      <!-- 验证码  图片底色 -->
      <param-name>kaptcha.background.clear.to</param-name>
      <param-value>211,229,237</param-value>
    </init-param>
    <init-param>
      <!-- session.setAttribute("captcha","验证码") -->
      <param-name>kaptcha.session.key</param-name>
      <param-value>captcha</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>cap</servlet-name>
    <url-pattern>/captcha</url-pattern>
  </servlet-mapping>

13.4 Page

<img src="${pageContext.request.contextPath}/captcha" style="width:85px" id="cap"/>
<img src="${pageContext.request.contextPath}/captcha" style="width:85px" id="cap" onclick="refresh();"/>
<script>
    $(function(){
        $("#cap").click(function(){
            //刷新验证码
            path = $(this).attr("src")+"?"+new Date().getTime();
            $(this).attr("src",path);
        });
    });
    
    function refresh(){
        var img = document.getElementById("cap");
        img.src = "${pageContext.request.contextPath}/captcha?"+new Date().getTime();
    }
</script>

13.5 登录验证

@Controller
@RequestMapping("/captcha")
public class CaptchaControll(){
    
    @RequestMapping("/test1")
	public String test1(String cap, HttpSession session){
        String captcha = session.getAttribute("captcha");
        if(cap.equals(captcha)){
            return "index";
        }
        return "error1";
    }
}
<from action="${pageContext.request.contextPath}/captcha/test1">
    <img src="${pageContext.request.contextPath}/captcha" style="width:85px" id="cap"/>
    <input type="text" name="cap"/>
    <br />
    <input type="submit" value="提交"/>
</from>

十四、 Rest开发风格

1.   是一种开发风格,遵从此风格开发软件,符合REST风格,则RESTFUL

1.1  每个资源都有唯一的表示(Url)

1.2   不同的行为,使用对应的http-method

例:通过二级路径查询用户 三级路径查询用户1四级用户查询用户1的所有订单

访问标识资源
http://localhost:8989/xxx/users所有用户
http://localhost:8989/xxx/users/1用户1
http://localhost:8989/xxx/users/1/orders用户1的所有订单
请求方式标识意图
GEThttp://localhost:8989/xxx/users查询所有用户
POSThttp://localhost:8989/xxx/users在所有用户中增加一个
PUThttp://localhost:8989/xxx/users在所有用户中修改一个
DELETEhttp://localhost:8989/xxx/users/1删除用户1
GEThttp://localhost:8989/xxx/users/1查询用户1
GET       http://localhost:8989/xxx/users/1/orders查询用户1的所有订单
POSThttp://localhost:8989/xxx/users/1/orders在用户1的所有订单中增加一个
@RestController
@RequestMapping("/restful")
//@RequestMapping(value="/users",method = RequestMethod.GET) 等价 @GetMapping("/users")
public class RestFull {
    @GetMapping("/users")
    public List<User> queryAllUsers(){
        System.out.println("get");
        List<User> users = new ArrayList<>();
        users.add(new User(101,"tom",new Date()));
        users.add(new User(102,"lucky",new Date()));
        return users;
    }
    @PostMapping("/users")
    public String addUser(@RequestBody User user){
        System.out.println("Post user :"+user);
        return "{status:1}";
    }

    @PutMapping("/users")
    public String updateUser(@RequestBody User user){
        System.out.println("Put user" + user+":user");
        return "{status:1}";
    }

    @GetMapping("/users/{id}")
    public String queryOneUser(@PathVariable Integer id){//@PathVariable 接收路径中的值
        System.out.println("Get user id:"+id);
        return "{status:1}";
    }

    @DeleteMapping("/users/{id}")
    public String deleteOneUser(@PathVariable Integer id){//@PathVariable 接收路径中的值
        System.out.println("delete user id:"+id);
        return "{status:1}";
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.6.1.min(1).js"></script>
    <script>
        $(function (){
            $("#btn1").click(function (){
                //传日期是用8位字符串
                var user = {id:1,name:"tom",birthday:"20221212"};
                $.ajax({
                    url:'/json/test4',//要访问的地址
                    type:'post ',//请求方式
                    contentType:"application/json",//声明请求参数类型为json
                    data:JSON.stringify(user),//转换js对象成json
                    success:function (data){
                        console.log(data);
                    }
                })
            });
            $("#btn2").click(function (){
                //传日期是用8位字符串
                var user = {id:1,name:"tom",birthday:"2022-12-12 12:12:12"};
                $.ajax({
                    url:'/restful/users',//要访问的地址
                    type:'get',//请求方式
                    contentType:"application/json",//声明请求参数类型为json
                    //data:JSON.stringify(user),//转换js对象成json
                    success:function (data){
                        console.log(data);
                    }
                })
            });
            $("#btn3").click(function (){
                //传日期是用8位字符串
                var user = {id:1,name:"tom",birthday:"2022-12-12 12:12:12"};
                $.ajax({
                    url:'/restful/users',//要访问的地址
                    type:'post',//请求方式
                    contentType:"application/json",//声明请求参数类型为json
                    data:JSON.stringify(user),//转换js对象成json
                    success:function (data){
                        console.log(data);
                    }
                })
            });
            $("#btn4").click(function (){
                //传日期是用8位字符串
                var user = {id:1,name:"lucky",birthday:"2022-12-12 12:12:12"};
                $.ajax({
                    url:'/restful/users',//要访问的地址
                    type:'put',//请求方式
                    contentType:"application/json",//声明请求参数类型为json
                    data:JSON.stringify(user),//转换js对象成json
                    success:function (data){
                        console.log(data);
                    }
                })
            });
            $("#btn5").click(function (){
                //传日期是用8位字符串
                var user = {id:1,name:"tom",birthday:"2022-12-12 12:12:12"};
                $.ajax({
                    url:'/restful/users/1',//要访问的地址
                    type:'delete',//请求方式
                    contentType:"application/json",//声明请求参数类型为json
                    //data:JSON.stringify(user),//转换js对象成json
                    success:function (data){
                        console.log(data);
                    }
                })
            });
        })
    </script>
</head>
<body>
<button id="btn1">发送json</button>
<button id="btn2">queryAllUsers</button>
<button id="btn3">addUser</button>
<button id="btn4">updateUser</button>
<button id="btn5">deleteOneUser</button>
</body>
</html>

SpringMVC执行流程

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值