蒋振飞的博客 - Java进阶07:SpringMVC教程   
正在加载蒋振飞的博客...
V3.0
蒋振飞的博客

Java进阶07:SpringMVC教程

发布时间: 2019年01月31日 发布人: 蒋振飞 热度: 640 ℃ 评论数: 0

1. SpringMVC介绍 

1.1 SpringMVC概述

    ①Spring MVC框架是一个开源的Java平台,为开发强大的基于Java的Web应用程序提供全面的基础架构支持非常容易和非常快速。
    ②Spring web MVC框架提供了MVC(模型 - 视图 - 控制器)架构和用于开发灵活和松散耦合的Web应用程序的组件。 MVC模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。

1.2 MVC架构

    ①模型(Model)封装了应用程序数据,通常它们将由POJO类组成。
    ②视图(View)负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。
    ③控制器(Controller)负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。

1.3 SpringMVC处理流程

springmvc-progress.png

1.4 springmvc与struts2不同

    ①springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过滤器。
    ②springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
    ③Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面,Jsp视图解析器默认使用jstl。

2. SpringMVC入门

2.1 配置文件

    1) springmvc.xml

        SpringMVC本身就是Spring的子项目,对Spring兼容性很好,不需要做很多配置。这里只配置一个Controller扫描就可以了,让Spring对页面控制层Controller进行管理。

<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 配置controller扫描包 -->
<context:component-scan base-package="com.jzfblog.springmvc.controller" />
</beans>

    2) 配置前端控制器

        配置SpringMVC的前端控制器DispatcherServlet。

**web.xml**
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>springmvc-first</display-name>
    <welcome-file-list>
       <welcome-file>index.html</welcome-file>
       <welcome-file>index.htm</welcome-file>
       <welcome-file>index.jsp</welcome-file>
       <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
       <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
 
    <!-- 配置SpringMVC前端控制器 -->
    <servlet>
       <servlet-name>springmvc</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!-- 指定SpringMVC配置文件 -->
       <!-- SpringMVC的配置文件的默认路径是/WEB-INF/${servlet-name}-servlet.xml -->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc.xml</param-value>
       </init-param>
    </servlet>
 
    <servlet-mapping>
       <servlet-name>springmvc</servlet-name>
       <!-- 设置所有以action结尾的请求进入SpringMVC -->
       <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>

2.2 创建商品pojo

public class Item {
    // 商品id
    private int id;
    // 商品名称
    private String name;
    // 商品价格
    private double price;
    // 商品创建时间
    private Date createtime;
    // 商品描述
    private String detail;
    
    创建带参数的构造器
    set/get。。。
}

2.3 创建ItemController

    ①ItemController是一个普通的java类,不需要实现任何接口。
    ②需要在类上添加@Controller注解,把Controller交由Spring管理。
    ③在方法上面添加@RequestMapping注解,里面指定请求的url。其中“.action”可以加也可以不加。

@Controller
public class ItemController {
 
    // @RequestMapping:里面放的是请求的url,和用户请求的url进行匹配
    // action可以写也可以不写
    @RequestMapping("/itemList.action")
    public ModelAndView queryItemList() {
       // 创建页面需要显示的商品数据
       List<Item> list = new ArrayList<>();
       list.add(new Item(1, "1华为 荣耀8", 2399, new Date(), "质量好!1"));
       list.add(new Item(2, "2华为 荣耀8", 2399, new Date(), "质量好!2"));
       list.add(new Item(3, "3华为 荣耀8", 2399, new Date(), "质量好!3"));
       list.add(new Item(4, "4华为 荣耀8", 2399, new Date(), "质量好!4"));
       list.add(new Item(5, "5华为 荣耀8", 2399, new Date(), "质量好!5"));
       list.add(new Item(6, "6华为 荣耀8", 2399, new Date(), "质量好!6"));
 
       // 创建ModelAndView,用来存放数据和视图
       ModelAndView modelAndView = new ModelAndView();
       // 设置数据到模型中
       modelAndView.addObject("list", list);
       // 设置视图jsp,需要设置视图的物理地址
       modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");
 
       return modelAndView;
    }
}

3. Springmvc架构

3.1 框架结构

springmvc-architecture.png

3.2 架构流程

    ①用户发送请求至前端控制器DispatcherServlet。
    ②DispatcherServlet收到请求调用HandlerMapping处理器映射器。
    ③处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
    ④DispatcherServlet通过HandlerAdapter处理器适配器调用处理器。
    ⑤执行处理器(Controller,也叫后端控制器)。
    ⑥Controller执行完成返回ModelAndView。
    ⑦HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
    ⑧DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
    ⑨ViewReslover解析后返回具体View。
    ⑩DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
    ⑪DispatcherServlet响应用户。

3.3 组件说明

    1) DispatcherServlet:前端控制器

        用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。

    2) HandlerMapping:处理器映射器

        HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

    3) Handler:处理器

        Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。

    4) HandlAdapter:处理器适配器

        通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

    5) ViewResolver:视图解析器

        View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 

    6) View:视图

        springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
        说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件,需要用户开发的组件有handler、view。

3.4 组件扫描器

    使用<context:component-scan>自动扫描标记@Controller的控制器类,在springmvc.xml配置文件中配置如下:

<!-- 配置controller扫描包,多个包之间用,分隔 -->
<context:component-scan base-package="com.jzfblog.springmvc.controller" />

3.5 注解映射器和适配器

    1) 配置处理器映射器

        ①注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射。根据@ResquestMapping定义的url匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。HandlerMethod对象中封装url对应的方法Method。
        ②从spring3.1版本开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射。

        在springmvc.xml配置文件中配置如下:

<!-- 配置处理器映射器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />

    2) 配置处理器适配器

        ①注解式处理器适配器,对标记@ResquestMapping的方法进行适配。
        ②从spring3.1版本开始,废除了AnnotationMethodHandlerAdapter的使用,推荐使用RequestMappingHandlerAdapter完成注解式处理器适配。

        在springmvc.xml配置文件中配置如下:

<!-- 配置处理器适配器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />

    3) 注解驱动

        ①直接配置处理器映射器和处理器适配器比较麻烦,可以使用注解驱动来加载。
        ②SpringMVC使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapters。
        ③可以在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置。

<!-- 注解驱动 -->
<mvc:annotation-driven />

    4) 视图解析器

        视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,这个视图解析器支持JSP视图解析。

        在springmvc.xml配置文件中配置如下:

<!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> 
    "/WEB-INF/jsp/test.jsp" -->
<!-- 配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 配置逻辑视图的前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/" />
    <!-- 配置逻辑视图的后缀 -->
    <property name="suffix" value=".jsp" />
</bean>

    逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为ItemList,则最终返回的jsp视图地址:“WEB-INF/jsp/itemList.jsp”,最终jsp物理地址:前缀+逻辑视图名+后缀。

3.6 修改ItemController

// @RequestMapping:里面放的是请求的url,和用户请求的url进行匹配
// action可以写也可以不写
@RequestMapping("/itemList.action")
public ModelAndView queryItemList() {
    // 创建页面需要显示的商品数据
    List<Item> list = new ArrayList<>();
    list.add(new Item(1, "1华为 荣耀8", 2399, new Date(), "质量好!1"));
    list.add(new Item(2, "2华为 荣耀8", 2399, new Date(), "质量好!2"));
    list.add(new Item(3, "3华为 荣耀8", 2399, new Date(), "质量好!3"));
    list.add(new Item(4, "4华为 荣耀8", 2399, new Date(), "质量好!4"));
    list.add(new Item(5, "5华为 荣耀8", 2399, new Date(), "质量好!5"));
    list.add(new Item(6, "6华为 荣耀8", 2399, new Date(), "质量好!6"));
 
    // 创建ModelAndView,用来存放数据和视图
    ModelAndView modelAndView = new ModelAndView();
    // 设置数据到模型中
    modelAndView.addObject("itemList", list);
    // 设置视图jsp,需要设置视图的物理地址
    // modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");
    // 配置好视图解析器前缀和后缀,这里只需要设置逻辑视图就可以了。
    // 视图解析器根据前缀+逻辑视图名+后缀拼接出来物理路径
    modelAndView.setViewName("itemList");
 
    return modelAndView;
}

4. 整合mybatis

4.1 需要的jar包

    ①spring(包括springmvc)。
    ②mybatis。
    ③mybatis-spring整合包。
    ④数据库驱动。
    ⑤第三方连接池。

4.2 整合思路

    1) Dao层

        ①SqlMapConfig.xml,空文件即可,但是需要文件头。
        ②applicationContext-dao.xml。
            数据库连接池
            SqlSessionFactory对象,需要spring和mybatis整合包下的。
            配置mapper文件扫描器。

    2) Service层

        ①applicationContext-service.xml包扫描器,扫描@service注解的类。
        ②applicationContext-trans.xml配置事务。

    3) Controller层

        ①Springmvc.xml
            包扫描器,扫描@Controller注解的类。
            配置注解驱动。
            配置视图解析器。
        ②Web.xml文件
            配置spring。
            配置前端控制器。

4.3 加入配置文件

    1) sqlMapConfig.xml

        使用逆向工程来生成Mapper相关代码,不需要配置别名。在config/mybatis下创建SqlMapConfig.xml

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

</configuration>

    2) applicationContext-dao.xml

        配置数据源、配置SqlSessionFactory、mapper扫描器。

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

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:db.properties" />

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <property name="maxActive" value="10" />
        <property name="maxIdle" value="5" />
    </bean>

    <!-- 配置SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
        <!-- 加载mybatis的全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
    </bean>

    <!-- 配置Mapper扫描 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 配置Mapper扫描包 -->
        <property name="basePackage" value="com.jzfblog.ssm.mapper" />
    </bean>

</beans>

    3) db.properties

        配置数据库相关信息。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springmvc?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

    4) applicationContext-service.xml

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

    <!-- 配置service扫描 -->
    <context:component-scan base-package="com.jzfblog.ssm.service" />

</beans>

    5) applicationContext-trans.xml

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

    <!-- 事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 传播行为 -->
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
            <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
		</tx:attributes>
	</tx:advice>

    <!-- 切面 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.jzfblog.ssm.service.*.*(..))" />
    </aop:config>

</beans>

    6) springmvc.xml

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

    <!-- 配置controller扫描包 -->
    <context:component-scan base-package="com.jzfblog.ssm.controller" />

    <!-- 注解驱动 -->
    <mvc:annotation-driven />

    <!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> 
		"/WEB-INF/jsp/test.jsp" -->
    <!-- 配置视图解析器 -->
    <bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置逻辑视图的前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 配置逻辑视图的后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

    7) web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>springmvc-web</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

    <!-- 配置spring -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext*.xml</param-value>
    </context-param>

    <!-- 使用监听器加载Spring配置文件 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 配置SrpingMVC的前端控制器 -->
    <servlet>
        <servlet-name>springmvc-web</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/springmvc.xml</param-value>
            </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc-web</servlet-name>
        <!-- 配置所有以action结尾的请求进入SpringMVC -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

</web-app>

4.4 DAO开发

    1) ItemService接口

public interface ItemService {

    /**
    * 查询商品列表
    * 
    * @return
    */
    List<Item> queryItemList();

}

    2)  ItemServiceImpl实现类

@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private ItemMapper itemMapper;

    @Override
    public List<Item> queryItemList() {
        // 从数据库查询商品数据
        List<Item> list = this.itemMapper.selectByExample(null);

        return list;
    }

}

    3) ItemController

@Controller
public class ItemController {

    @Autowired
    private ItemService itemService;

    /**
    * 显示商品列表
    * 
    * @return
    */
    @RequestMapping("/itemList")
    public ModelAndView queryItemList() {
        // 获取商品数据
        List<Item> list = this.itemService.queryItemList();

        ModelAndView modelAndView = new ModelAndView();
        // 把商品数据放到模型中
        modelAndView.addObject("itemList", list);
        // 设置逻辑视图
        modelAndView.setViewName("itemList");

        return modelAndView;
    }
}

5. 参数绑定

5.1 ItemService接口

Item queryItemById(int id);

5.2 ItemServiceImpl实现类

@Override
public Item queryItemById(int id) {

    Item item = this.itemMapper.selectByPrimaryKey(id);
    return item;
}

5.3 ItemController

/**
 * 根据id查询商品
 * 
 * @param request
 * @return
 */
@RequestMapping("/itemEdit")
public ModelAndView queryItemById(HttpServletRequest request) {
    // 从request中获取请求参数
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);
    
    // 根据id查询商品数据
    Item item = this.itemService.queryItemById(id);
    
    // 把结果传递给页面
    ModelAndView modelAndView = new ModelAndView();
    
    // 把商品数据放在模型中
    modelAndView.addObject("item", item);
    
    // 设置逻辑视图
    modelAndView.setViewName("itemEdit");
    return modelAndView;
}

5.4 默认支持的参数类型

    处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值。

    1) HttpServletRequest

        通过request对象获取请求信息。

    2) HttpServletResponse

        通过response处理响应信息。

    3) HttpSession

        通过session对象得到session中存放的对象。

5.5 Model和ModelMap

    1) Model

        除了ModelAndView以外,还可以使用Model来向页面传递数据,Model是一个接口,在参数里直接声明model即可。如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值替代。不管是Model还是ModelAndView,其本质都是使用Request对象向jsp传递数据。

/**
 * 根据id查询商品,使用Model
 * 
 * @param request
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, Model model) {
    
    // 从request中获取请求参数
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);
    
    // 根据id查询商品数据
    Item item = this.itemService.queryItemById(id);

    // 把结果传递给页面
    // ModelAndView modelAndView = new ModelAndView();
    // 把商品数据放在模型中
    // modelAndView.addObject("item", item);
    // 设置逻辑视图
    // modelAndView.setViewName("itemEdit");
    
    // 把商品数据放在模型中
    model.addAttribute("item", item);
    return "itemEdit";
}

    2) ModelMap

        ModelMap是Model接口的实现类,也可以通过ModelMap向页面传递数据,使用Model和ModelMap的效果一样,如果直接使用Model,springmvc会实例化ModelMap。

/**
 * 根据id查询商品,使用ModelMap
 * 
 * @param request
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, ModelMap model) {

    // 从request中获取请求参数
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);

    // 根据id查询商品数据
    Item item = this.itemService.queryItemById(id);

    // 把结果传递给页面
    // ModelAndView modelAndView = new ModelAndView();
    // 把商品数据放在模型中
    // modelAndView.addObject("item", item);
    // 设置逻辑视图
    // modelAndView.setViewName("itemEdit");

    // 把商品数据放在模型中
    model.addAttribute("item", item);
    
    return "itemEdit";
}

5.6 绑定简单类型

    当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定,这样,从Request取参数的方法就可以进一步简化。

/**
 * 根据id查询商品,绑定简单数据类型
 * 
 * @param id
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(int id, ModelMap model) {

    // 根据id查询商品数据
    Item item = this.itemService.queryItemById(id);
    
    // 把商品数据放在模型中
    model.addAttribute("item", item);
    
    return "itemEdit";
}

    1) 支持的数据类型

    参数类型推荐使用包装数据类型,因为基础数据类型不可以为null。

整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean

    说明:对于布尔类型的参数,请求的参数值为true或false,或者1或0。

    2) @RequestParam

    使用@RequestParam常用于处理简单类型的绑定。

value:参数名字,即入参的请求参数名字,如value=“itemId”表示请求的参数区中的名字为itemId的参数的值将传入


required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错TTP Status 400 - Required Integer parameter 'XXXX' is not present


defaultValue:默认值,表示如果请求中没有同名参数时的默认值

@RequestMapping("/itemEdit")
public String queryItemById(@RequestParam(value = "itemId", required = true, defaultValue = "1") Integer id,
ModelMap modelMap) {

    // 根据id查询商品数据
    Item item = this.itemService.queryItemById(id);

    // 把商品数据放在模型中
    modelMap.addAttribute("item", item);
    
    return "itemEdit";
}

5.7 绑定pojo类型

    1) ItemService接口

/**
 * 根据id更新商品
 * 
 * @param item
 */
void updateItemById(Item item);

    2) ItemServiceImpl实现类

        ItemServiceImpl里实现接口方法,使用updateByPrimaryKeySelective(item)方法,忽略空参数。

@Override
public void updateItemById(Item item) {

    this.itemMapper.updateByPrimaryKeySelective(item);
}

    3) ItemController

/**
 * 更新商品,绑定pojo类型
 * 
 * @param item
 * @param model
 * @return
 */
@RequestMapping("/updateItem")
public String updateItem(Item item) {

    // 调用服务更新商品
    this.itemService.updateItemById(item);
    
    // 返回逻辑视图
    return "success";
}

        注意:提交的表单中不要有日期类型的数据,否则会报400错误。如果想提交日期类型的数据需要用到后面的自定义参数绑定的内容。

5.8 解决post乱码问题

    提交发现,保存成功,但是保存的是乱码在web.xml中加入:

<!-- 解决post乱码问题 -->
<filter>
    <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 设置编码参是UTF8 -->
        <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>

    以上可以解决post请求乱码问题。

5.9 解决get中文参数出现乱码

    ①修改tomcat配置文件添加编码与工程编码一致,如下:

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

    ②另外一种方法对参数进行重新编码:

String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

        ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。

5.10 绑定包装pojo

    1) 包装对象

public class QueryVo {

    private Item item;
    set/get。。。
}

    2) 页面定义

<input type="text" name="item.id"/>
<input type="text" name="item.name"/>

    3) 接收查询条件

// 绑定包装数据类型
@RequestMapping("/queryItem")
    public String queryItem(QueryVo queryVo) {
    System.out.println(queryVo.getItem().getId());
    System.out.println(queryVo.getItem().getName());
    
    return "success";
}

5.11 自定义参数绑定

    由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。

    1) 自定义Converter

//Converter<S, T>
//S:source,需要转换的源的类型
//T:target,需要转换的目标类型
public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        try {
            // 把字符串转换为日期类型
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
            Date date = simpleDateFormat.parse(source);
            return date;
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 如果转换异常则返回空
        return null;
    }
}

    2) 配置Converter

<!-- 配置注解驱动 -->
<!-- 如果配置此标签,可以不用配置... -->
<mvc:annotation-driven conversion-service="conversionService" />

<!-- 转换器配置 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.jzfblog.springmvc.converter.DateConverter" />
        </set>
    </property>
</bean>

    3) 配置方式2(了解)

<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer" ref="customBinder"></property>
</bean>
 
<!-- 自定义webBinder -->
<bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
    <property name="conversionService" ref="conversionService" />
</bean>
 
<!-- 转换器配置 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.jzfblog.springmvc.convert.DateConverter" />
        </set>
    </property>
</bean>

    注意:此方法需要独立配置处理器映射器、适配器,不再使用<mvc:annotation-driven/>。

6. 高级参数绑定

6.1 绑定数组

    1) Jsp修改

<td><input type="checkbox" name="ids" value="${item.id}"/></td>

    2) Controller

        Controller方法中可以用String[]接收,或者pojo的String[]属性接收。两种方式任选其一即可。

public class QueryVo {
    
    // 用对象的属性接收数组,属性名要同页面的name值相同
    private Integer[] ids;
}
/**
 * 包装类型 绑定数组类型,可以使用两种方式,pojo的属性接收,和直接接收
 * 
 * @param queryVo
 * @return
 */
@RequestMapping("queryItem")
public String queryItem(QueryVo queryVo, Integer[] ids) {
   
    System.out.println(queryVo.getItem().getId());
    System.out.println(queryVo.getItem().getName());
    
    System.out.println(queryVo.getIds().length);
    System.out.println(ids.length);
    
    return "success";
}

6.2 绑定集合

    1) 定义pojo

public class QueryVo {
    
    // 用对象的属性接收list集合
    private List<Item> itemList;
}

    2) Jsp改造

<c:forEach items="${itemList }" var="item" varStatus="s">
    <tr>
        <td><input type="checkbox" name="ids" value="${item.id}"/></td>
        <td>
            <input type="hidden" name="itemList[${s.index}].id" value="${item.id }"/>
            <input type="text" name="itemList[${s.index}].name" value="${item.name }"/>
        </td>
        <td><input type="text" name="itemList[${s.index}].price" value="${item.price }"/></td>
        <td><input type="text" name="itemList[${s.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
        <td><input type="text" name="itemList[${s.index}].detail" value="${item.detail }"/></td>
        <td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
    </tr>
</c:forEach>

7. @RequestMapping

7.1 URL路径映射

    @RequestMapping(value="item")或@RequestMapping("/item"),value的值是数组,可以将多个url映射到同一个方法。

/**
 * 查询商品列表
 * @return
 */
@RequestMapping(value = { "itemList", "itemListAll" })
public ModelAndView queryItemList() {
    
    // 查询商品数据
    List<Item> list = this.itemService.queryItemList();
    
    // 创建ModelAndView,设置逻辑视图名
    ModelAndView mv = new ModelAndView("itemList");
    
    // 把商品数据放到模型中
    mv.addObject("itemList", list);
    
    return mv;
}

7.2 添加在类上面

    在class上添加@RequestMapping(url)指定通用请求前缀,限制此类下的所有方法请求url必须以请求前缀开头。

@Controller 
@RequestMapping("item")
public class ItemController{
    ...

7.3 请求方法限定 

    除了可以对url进行设置,还可以限定请求进来的方法。

    1) 限定GET方法

@RequestMapping(method = RequestMethod.GET)

        如果通过POST访问则报错:

HTTP Status 405 - Request method 'POST' not supported

    2) 限定POST方法

@RequestMapping(method = RequestMethod.POST)

        如果通过GET访问则报错:

HTTP Status 405 - Request method 'GET' not supported

    3) GET和POST都可以

@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})

8. Controller方法返回值

8.1 返回ModelAndView

    controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。

8.2 返回void

    在Controller方法形参上可以定义request和response,使用request或response指定响应结果:

    1) 使用request转发页面

request.getRequestDispatcher("页面路径").forward(request, response);
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);

    2) 通过response页面重定向

response.sendRedirect("url")
response.sendRedirect("/springmvc-web2/itemEdit.action");

    3) 通过response指定响应结果,例如响应json数据

response.getWriter().print("{\"abc\":123}");

    4) 代码演示

/**
 * 返回void测试
 * 
 * @param request
 * @param response
 * @throws Exception
 */
@RequestMapping("queryItem")
public void queryItem(HttpServletRequest request, HttpServletResponse response) throws Exception {

    // 1 使用request进行转发
    // request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,
    // response);
    
    // 2 使用response进行重定向到编辑页面
    // response.sendRedirect("/springmvc-web2/itemEdit.action");
    
    // 3 使用response直接显示
    response.getWriter().print("{\"abc\":123}");
}

8.3 返回字符串

    1) 逻辑视图名

        controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。

//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/itemList.jsp
return "itemList";

    2) Redirect重定向

        Contrller方法返回字符串可以重定向到一个url地址,如下商品修改提交后重定向到商品编辑页面。

/**
 * 更新商品
 * 
 * @param item
 * @return
 */
@RequestMapping("updateItem")
public String updateItemById(Item item) {
    // 更新商品
    this.itemService.updateItemById(item);
    
    // 修改商品成功后,重定向到商品编辑页面
    // 重定向后浏览器地址栏变更为重定向的地址,
    // 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失
    
    // 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数
    return "redirect:/itemEdit.action?itemId=" + item.getId();
}

    3) forward转发

        Controller方法执行后继续执行另一个Controller方法,如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中。

/**
 * 更新商品
 * 
 * @param item
 * @return
 */
@RequestMapping("updateItem")
public String updateItemById(Item item) {
    
    // 更新商品
    this.itemService.updateItemById(item);
    
    // 修改商品成功后,重定向到商品编辑页面
    // 重定向后浏览器地址栏变更为重定向的地址,
    // 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失
    // 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数
    // return "redirect:/itemEdit.action?itemId=" + item.getId();
    
    // 修改商品成功后,继续执行另一个方法
    // 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址,
    // 转发并没有执行新的request和response,所以之前的请求参数都存在
    return "forward:/itemEdit.action";
}

9. 异常处理器

9.1 异常处理思路

    系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。

9.2 自定义异常类

public class MyException extends Exception {
    
    // 异常信息
    private String message;
    
    public MyException() {
        super();
    }

    public MyException(String message) {
        super();
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

9.3 自定义异常处理器

public class CustomHandleException implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
    
        // 定义异常信息
        String msg;

        // 判断异常类型
        if (exception instanceof MyException) {
            // 如果是自定义异常,读取异常信息
            msg = exception.getMessage();
        } else {
            // 如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
            Writer out = new StringWriter();
            PrintWriter s = new PrintWriter(out);
            exception.printStackTrace(s);
            msg = out.toString();
        }
        // 把错误信息发给相关人员,邮件,短信等方式
        // TODO
        
        // 返回错误页面,给用户友好页面显示错误信息
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", msg);
        modelAndView.setViewName("error");
        
        return modelAndView;
    }
}

9.4 异常处理器配置

    在springmvc.xml中添加:

<!-- 配置全局异常处理器 -->
<bean 
id="customHandleException" class="com.jzfblog.ssm.exception.CustomHandleException"/>

9.5 异常测试

    修改ItemController方法“queryItemList”,抛出异常:

/**
 * 查询商品列表
 * 
 * @return
 * @throws Exception
 */
@RequestMapping(value = { "itemList", "itemListAll" })
public ModelAndView queryItemList() throws Exception {
        
    // 自定义异常
    if (true) {
        throw new MyException("自定义异常出现了~");
    }
    // 运行时异常
    int a = 1 / 0;
    
    // 查询商品数据
    List<Item> list = this.itemService.queryItemList();
    
    // 创建ModelAndView,设置逻辑视图名
    ModelAndView mv = new ModelAndView("itemList");
    
    // 把商品数据放到模型中
    mv.addObject("itemList", list);
    
    return mv;
}

10. 上传图片

10.1 配置虚拟目录 

    在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:

<Context docBase="D:\develop\upload\temp" path="/pic" reloadable="false"/>

    访问http://localhost:8080/pic即可访问D:\develop\upload\temp下的图片。

10.2 加入jar包

commons-fileupload-1.2.2.jar
commons-io-2.4.jar

10.3 配置上传解析器

    在springmvc.xml中配置文件上传解析器。

<!-- 文件上传,id必须设置为multipartResolver -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置文件上传大小 -->
    <property name="maxUploadSize" value="5000000" />
</bean>

10.4 jsp页面

<c:if test="${item.pic != null}">
    <img src="/pic/${item.pic}>
</c:if>
<input type="file" name="pictureFile"/>

    设置表单可以进行文件上传

enctype="multiport/form-data"

10.5 图片上传

/**
 * 更新商品
 * 
 * @param item
 * @return
 * @throws Exception
 */
@RequestMapping("updateItem")
public String updateItemById(Item item, MultipartFile pictureFile) throws Exception {
    
    // 图片上传
    // 设置图片名称,不能重复,可以使用uuid
    String picName = UUID.randomUUID().toString();

    // 获取文件名
    String oriName = pictureFile.getOriginalFilename();

    // 获取图片后缀
    String extName = oriName.substring(oriName.lastIndexOf("."));

    // 开始上传
    pictureFile.transferTo(new File("C:/upload/image/" + picName + extName));

    // 设置图片名到商品中
    item.setPic(picName + extName);
    // ---------------------------------------------
    // 更新商品
    this.itemService.updateItemById(item);
    return "forward:/itemEdit.action";
}

11. json数据交互

11.1 @RequestBody

    作用:@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上。

    本例子应用:@RequestBody注解实现接收http请求的json数据,将json数据转换为java对象进行绑定

11.2 @ResponseBody

    作用:@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

    本例子应用:@ResponseBody注解实现将Controller方法返回java对象转换为json响应给客户端。

11.3 请求json,响应json

    1) 加入jar包

        如果需要springMVC支持json,必须加入json的处理jar

jackson-annotations.2.4.0.jar
jackson-core-2.4.2.jar
jackson.databind-2.4.2.jar

    2) ItemController编写

/**
 * 测试json的交互
 * @param item
 * @return
 */
@RequestMapping("testJson")
    // @ResponseBody
    public @ResponseBody Item testJson(@RequestBody Item item) {
    return item;
}

    3) 配置json转换器

        如果不使用注解驱动<mvc:annotation-driven />,就需要给处理器适配器配置json转换器,参考之前的自定义参数绑定。在springmvc.xml配置文件中,给处理器适配器加入json转换器:

<!--处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
        </list>
    </property>
</bean>

12. RESTful支持

12.1 什么是restful

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

    1) 传统方式操作资源

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

    2) 使用RESTful操作资源

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

12.2 从URL上获取参数

/**
 * 使用RESTful风格开发接口,实现根据id查询商品
 * 
 * @param id
 * @return
 */
@RequestMapping("item/{id}")
@ResponseBody
public Item queryItemById(@PathVariable() Integer id) {
   
    Item item = this.itemService.queryItemById(id);
    return item;
}

    如果@RequestMapping中表示为"item/{id}",id和形参名称一致,@PathVariable不用指定名称。如果不一致,例如"item/{ItemId}"则需要指定名称@PathVariable("itemId")。

http://127.0.0.1/item/123?id=1

    ①@PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)。
    ②如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,目前返回的json数据。如果不加,就走视图解析器,返回页面。

13. 拦截器

13.1 定义

    Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

13.2 拦截器定义

    实现HandlerInterceptor接口,如下:

public class HandlerInterceptor1 implements HandlerInterceptor {
    
    // controller执行后且视图返回后调用此方法
    // 这里可得到执行controller时的异常信息
    // 这里可记录操作日志
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception {
        System.out.println("HandlerInterceptor1....afterCompletion");
    }
    
    // controller执行后但未返回视图前调用此方法
    // 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception {
        System.out.println("HandlerInterceptor1....postHandle");
    }

    // Controller执行前调用此方法
    // 返回true表示继续执行,返回false中止执行
    // 这里可以加入登录校验、权限拦截等
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        System.out.println("HandlerInterceptor1....preHandle");
        // 设置为true,测试使用
        return true;
    }
}

13.3 拦截器配置

    上面定义的拦截器再复制一份HandlerInterceptor2,注意新的拦截器修改代码:

System.out.println("HandlerInterceptor2....preHandle");

    在springmvc.xml中配置拦截器

<!-- 配置拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- 所有的请求都进入拦截器 -->
        <mvc:mapping path="/**" />
        <!-- 配置具体的拦截器 -->
        <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1" />
    </mvc:interceptor>

    <mvc:interceptor>
        <!-- 所有的请求都进入拦截器 -->
        <mvc:mapping path="/**" />
        <!-- 配置具体的拦截器 -->
        <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2" />
    </mvc:interceptor>
</mvc:interceptors>

13.4 拦截器应用

    1) 处理流程

    ①有一个登录页面,需要写一个Controller访问登录页面。
    ②登录页面有一提交表单的动作。需要在Controller中处理。
        a) 判断用户名密码是否正确(在控制台打印)。
        b) 如果正确,向session中写入用户信息(写入用户名username)。
        c) 跳转到商品列表。

    ③拦截器。

        a) 拦截用户请求,判断用户是否登录(登录请求不能拦截)。

        b) 如果用户已经登录。放行。

        c) 如果用户未登录,跳转到登录页面。

    2) 编写登录jsp

<form action="${pageContext.request.contextPath }/user/login.action">
    <label>用户名:</label>
    <br>
    <input type="text" name="username">
    <br>
    <label>密码:</label>
    <br>
    <input type="password" name="password">
    <br>
    <input type="submit">
</form>

    3) 用户登陆Controller

@Controller
@RequestMapping("user")
public class UserController {
    
    /**
     * 跳转到登录页面
     * 
     * @return
     */
    @RequestMapping("toLogin")
    public String toLogin() {
        return "login";
    }
    
    /**
     * 用户登录
     * 
     * @param username
     * @param password
     * @param session
     * @return
     */
    @RequestMapping("login")
    public String login(String username, String password, HttpSession session) {
    
        // 校验用户登录
        System.out.println(username);
        System.out.println(password);
        // 把用户名放到session中
        session.setAttribute("username", username);
        return "redirect:/item/itemList.action";
    }
}

    4) 编写拦截器

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
    
    // 从request中获取session
    HttpSession session = request.getSession();
    
    // 从session中获取username
    Object username = session.getAttribute("username");

    // 判断username是否为null
    if (username != null) {
        // 如果不为空则放行
        return true;
    } else {
        // 如果为空则跳转到登录页面
        response.sendRedirect(request.getContextPath() + "/user/toLogin.action");
    }
    return false;
}

    5) 配置拦截器

    只能拦截商品的url,所以需要修改ItemController,让所有的请求都必须以item开头。

<mvc:interceptor>
    <!-- 配置商品被拦截器拦截 -->
    <mvc:mapping path="/item/**" />
    <!-- 配置具体的拦截器 -->
    <bean class="cn.itcast.ssm.interceptor.LoginHandlerInterceptor" />
</mvc:interceptor>

打赏 蒋振飞

取消

感谢您的支持,我会继续努力的!

扫码支持
一分也是爱     一块不嫌多

点击 支付宝 或 微信 打赏蒋振飞

打开支付宝扫一扫,即可进行扫码打赏哦

评论列表