SpringMVC

第一章 springmvc基础知识

1.1. 什么是springmvc

springmvcspring框架的一个模块,springmvcspring无需通过中间整合层进行整合

springmvc是一个mvcweb框架,mvc是一个设计模式:modelviewcontrol

 

 

 

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

 

1.2. springmvc框架原理

主要有前端控制器、处理器映射器、处理器适配器、视图解析器。

 

 

 

1.2.1. 前端控制器DispatcherServlet

接收请求,响应结果,相当于转发器,减少其他组件之间的耦合度

web.xml:
<!-- springmvc前端控制器 -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- contextConfigLocation配置springmvc加载的配置文件 
                                        如果不配置contextConfigLocation,默认加载/WEB-INF/servlet名称-servlet.xml(springmvc-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,访问以*.action结尾的DispatcherServlet进行解析
                                    第二种:/ 所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet解析
                                                    使用这种方法可以进行RESTful风格的url
                                   第三种:/* 这样配置不对,使用这种配置,最终要转发到jsp页面时,仍然由DispatcherServlet解析jsp地址,
                                                    不能根据jsp页面找到Handler,会报错
         -->
        <url-pattern>*.action</url-pattern>
</servlet-mapping>

 

1.2.2. 处理器映射器HandlerMapping

根据请求url查找Handler

 

<!-- 处理器映射器 -->
<!-- 根据bean的name进行查找Handler 将action的url配置在bean的name中 -->
      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean name="/queryItem.action" class="cn.kai.ssm.controller.ItemsController1"/>

 

<!-- 简单映射器 -->
      <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <!-- <prop key="/queryItem.action">itemsController1</prop> -->
                <prop key="/queryItem1.action">itemsController1</prop>
                <prop key="/queryItem2.action">itemsController2</prop>
            </props>
        </property>
      </bean>
<bean name="itemsController1" class="cn.kai.ssm.controller.ItemsController1"/>
<bean name="itemsController2" class="cn.kai.ssm.controller.ItemsController2"/>
<!--注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!-- 注解的handler -->
<bean class="cn.kai.ssm.controller.ItemsController3"/>
@Controller
public class ItemsController3{

    @RequestMapping("/queryItem")
    public ModelAndView queryItem(HttpServletRequest request, HttpServletResponse response) {

1.2.3. 处理器适配器handlerAdapter

按照特定规则去执行Handler

<!-- 处理器适配器

                        所有处理器适配器都实现HandlerAdapter接口,controller需要实现Controller

       -->

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

 

<!-- controller需要实现HttpRequestHandler -->

<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>

 

<!--注解适配器 -->

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

 

<!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置

    mvc:annotation-driven默认加载很多的参数绑定方法,

            比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMappingRequestMappingHandlerAdapter

             实际开发时使用mvc:annotation-driven

     -->

<mvc:annotation-driven></mvc:annotation-driven>

 

1.2.4. 处理器Handler

编写Handler时按照HandlerAdapter的要求,适配器才可以正确执行handler,需要程序员开发。

<bean name="itemsController1" class="cn.kai.ssm.controller.ItemsController1"/>

 

1.2.5. 视图解析器View resolver

进行视图解析,根据逻辑视图名解析成真正的视图

 

<!-- 视图解析器 
                                解析jsp解析,默认使用jstl标签,classpath下的jstl的包
      -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
            <!-- jsp路径前缀 -->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!-- jsp路径后缀 -->
            <property name="suffix" value=".jsp"/>
      </bean>

 

1.2.6. 视图View

view是一个接口,实现类支持不同的view类型jspfreemarkerpdf...需要程序员开发

 

1.3. springmvc注解开发

常用注解

<!--注解映射器 -->

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

<!--注解适配器 -->

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

 

参数绑定(简单类型、pojo、集合类型)

自定义参数绑定

对标记@Controller类中标识有@RequestMapping的方法进行映射。在@RequestMapping里边定义映射的url。使用注解的映射器不用在xml中配置urlHandler的映射关系。

注解处理器适配器和注解的处理器映射器是配对使用。理解为不能使用非注解映射器进行映射。

 

 

1.4. springmvc struts2区别

 

1、springmvc基于方法开发的,struts2基于类开发的。

 

2、springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。

 

经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl

 

 

第二章 springmvc整合mybatis

 

 

 

2.1. 事务控制

 

2.1.1. 注解式事务

 

spring+mybatis 事务配置:

 

<!-- 定义事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!--使用注释事务 -->
    <tx:annotation-driven  transaction-manager="transactionManager" />

 

spring+hibernate 事务配置:

 

<!-- 事务管理器配置,单数据源事务 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <!-- 使用annotation定义事务 -->
    <tx:annotation-driven  transaction-manager="transactionManager"   proxy-target-class="true" />

 

 

@Transactional:

把这个注解放在类名称上面了,这样你配置的这个@Transactional 对这个类中的所有public方法都起作用

 

@Transactional 方法方法名上,只对这个方法有作用,同样必须是public的方法

事务的传播性:@Transactional(propagation=Propagation.REQUIRED)

事务的超时性:@Transactional(timeout=30) //默认是30

事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED) 

 

 

 

 

 

回滚:

指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。

要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常})

@Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚

只读:@Transactional(readOnly=true)

 

spring配置文件中引入<tx:>命名空间:xmlns:tx="http://www.springframework.org/schema/tx"

 http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.2.xsd

 

 

2.1.2. AOP的方式实现事务的配置

 

<!-- 定义事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- 下面使用aop切面的方式来实现 -->
    <tx:advice id="TestAdvice" transaction-manager="transactionManager">
        <!--配置事务传播性,隔离级别以及超时回滚等问题 -->
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="*" rollback-for="Exception" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <!--配置事务切点 -->
        <aop:pointcut id="services"
            expression="execution(* com.website.service.*.*(..))" />
        <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" />
    </aop:config>

 

spring 配置文件中引入:xmlns:aop="http://www.springframework.org/schema/aop"

 http://www.springframework.org/schema/aop

 http://www.springframework.org/schema/aop/spring-aop.xsd

 

tx:attribute标签所配置的是作为事务的方法的命名类型。 如<tx:method name="save*" propagation="REQUIRED"/> 其中*为通配符,即代表以save为开头的所有方法,即表示符合此命名规则的方法作为一个事务。propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。

 

aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。

expression="execution(* com.test.testAda.test.model.service.*.*(..))"

其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,..代表方法参数。

 

 

2.2. 乱码

POST:

<!-- 提交 数据乱码处理 -->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
       <filter-name>CharacterEncodingFilter</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>

GET: 

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

2.3. @RequestMapping

URL路径映射

@RequestMapping(value="/item")@RequestMapping("/item"

value的值是数组,可以将多个url映射到同一个方法

 

窄化请求映射

@RequestMapping放在类名上边,设置请求前缀

@RequestMapping("/item")

@RequestMapping放在方法名上边,如下:

@RequestMapping("/queryItemsList ")

访问地址为:/item/queryItemsList

2.4. 参数绑定

注解适配器对RequestMapping标记的方法进行适配,对方法中的形参会进行参数绑定,早期springmvc采用PropertyEditor(属性编辑器)进行参数绑定将request请求的参数绑定到方法形参上,3.X之后springmvc就开始使用Converter进行参数绑定。

默认支持的参数类型:HttpServletRequestHttpServletResponseHttpSessionModel/ModelMap

 

 

 

 

 2.4.1. 简单类型

整型,字符串,单精度/双精度,布尔型

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

public String editItem(@RequestParam(value="item_id",required=true) String id) {

}

value:参数名字

required:是否必须,默认是true

 

defaultValue:默认值

 

多个参数需要多个@RequestParam

 

 

2.4.2. 简单pojo

 

pojo对象中的属性名于传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中

 

 

 

<input type="text" name="name"/>

 

<input type="text" name="price"/>

 

 

 

public String editItemSubmit(Items items)throws Exception

 

2.4.3. 自定义参数绑定

public class DateFormatConverters implements Converter<String, Date>{

 

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

 <!-- 自定义参数绑定 -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <!-- 需要绑定的列表 -->
            <list>
                <!-- 日期格式绑定 -->
                <bean class="cn.kai.sm.controller.converters.DateFormatConverters"/>
            </list>
        </property>
</bean>
<!--注解适配器 -->
    <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>
<!-- conversionService -->
<bean id="conversionService"
        class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!-- 转换器 -->
        <property name="converters">
            <list>
                <bean class="cn.kai.sm.controller.converters.DateFormatConverters"/>
            </list>
        </property>
    </bean>

 

第三章 springmvc高级应用

 

3.1. 参数绑定

 

3.1.1. 包装类型pojo参数绑定

 

商品名称:<input type="text" name="items.name" />

 

items 要和包装类中属性一致

 

 

 

 

// 查询商品列表

@RequestMapping(value = "/queryItemsList")

public ModelAndView queryItemsList(ItemsQueryVo itemsQueryVo) throws Exception

 

3.1.2. 数组绑定

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

 

function deleteItems(){

      document.itemsForm.action="${pageContext.request.contextPath }/items/deleteItemsList.action"

        document.itemsForm.submit();

}

 

//批量删除商品信息

@RequestMapping("/deleteItemsList")

public String deleteItemsList(Integer[] items_id) throws Exception{

//处理删除

 

return "success";

}

3.1.3. list绑定

 

public class ItemsQueryVo {

 

public List<Items> itemsList;

 

 

 

<td><input name="itemsList[${status.index }].name" value="${item.name }"/></td>

 

<td><input name="itemsList[${status.index }].price" value="${item.price }"/></td>

 

 

 

//批量修改信

 

@RequestMapping("/updateItemsList")

 

public String updateItemsList(ItemsQueryVo itemsQueryVo) throws Exception{

 

3.1.4. map绑定

 

public class ItemsQueryVo {

 

private Map<String, String> itemsMap;

 

 

 

<input type="text" name="itemsMap['name'] " value="test"/>

 

<input type="text" name="itemsMap['price'] " value="1000"/>

 

 

 

@RequestMapping("/updateItemsList")

 

public String updateItemsList(ItemsQueryVo itemsQueryVo) throws Exception{

 

Map<String,String> itemsMap = itemsQueryVo.getItemsMap();

 

3.2. 数据回显

提交后,如果出现错误,将刚才提交的数据回显到刚才的提交页面:

  1. 如果页面属性名和传入参数属性名相同时自动回显
  2. 在参数前加@ModelAttribute("items"),其中items为页面所用属性名

@ModelAttribute("items") ItemsQueryVo itemsQueryVo

  3. 利用model/ModelAndView

model.addAttribute("items", items);

modelAndView.addObject("itemsList", items);

  4. @ModelAttribute("itemsType")

    

//商品类型
    @ModelAttribute("itemsType")
    public Map<String,String> getItemsType(){
        Map<String,String> itemsType = new HashMap<String,String>();
        itemsType.put("01", "日用");
        itemsType.put("02", "家电");
        return itemsType;
    }

3.3. springmvc校验

3.3.1. 配置校验器

方法一:

<!-- 校验错误信息配置文件 -->
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <!-- 资源文件名 -->
        <property name="basenames">
            <list>
                <value>classpath:CustomValidationMessages</value>
            </list>
        </property>
        <!-- 资源文件编码格式 -->
        <property name="fileEncodings" value="utf-8" />
        <!-- 对资源文件内容缓存时间,单位秒 -->
        <property name="cacheSeconds" value="120" />
    </bean>

<!--校验器注入-->

<mvc:annotation-driven conversion-service="conversionService" validator="validator"></mvc:annotation-driven>

方法二:

<!-- 自定义webBinder -->
    <bean id="customBinder"
        class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
        <property name="validator" ref="validator" />
    </bean>

<!-- 注解适配器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="webBindingInitializer" ref="customBinder"></property>
    </bean>

 

3.3.2. 注解的方法添加校验规则

@Size(min = 1,max = 30,message = "{items.name.length.error}")

private String name;

 

 @NotNull(message = "{items.createtime.isNull}")

private Date createtime;

 

3.3.3. CustomValidationMessages.properties

#validator message

items.name.length.error=商品名的长度为(1,30)个字符

items.createtime.isNull=商品生成日期不能为空

 

3.3.4. 捕获校验错误信息

public String updateItems(Model model,Integer id,@Validated Items items,BindingResult result) throws Exception {
if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            for (ObjectError error:errors) {
                System.out.println(error.getDefaultMessage());
            }
            model.addAttribute("itemsErrors", errors);
            return "items/editItems";
        }

@ValidatedBindingResult bindingResult是成对出现,并且形参顺序是固定,BindingResult在紧接着的pojo类后面

 

 

3.3.5. 页面显示

<c:if test="${itemsErrors!=null}">
    <c:forEach items="${itemsErrors}" var="error">
        ${error.defaultMessage } <br/>
    </c:forEach>
</c:if>

3.3.6. 分组校验

public interface ValidGroup1 {

//对不同的校验进行分组,不需要实现类

}

 

归纳为ValidGroup1校验:

@Size(min = 1,max = 30,message = "{items.name.length.error}",groups = {ValidGroup1.class})

private String name;

 

只校验ValidGroup1的校验:

@Validated(value = {ValidGroup1.class}) Items items,BindingResult result

 

3.4. 异常处理

3.4.1. 处理思路

 

 

3.4.2. 自定义异常

public class ParamVlidationException extends Exception {

    private static final long serialVersionUID = -3142200140109183920L;

    public String message;

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

    public String getMessage() {
        return message;
    }

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

}

3.4.3. 全局异常处理器

实现HandlerExceptionResolver接口:

 

public class OverallExceptionResolver implements HandlerExceptionResolver {
    List customException;

    @Override
    public ModelAndView resolveException(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception ex) {
        ParamVlidationException paramVlidationException = null;

        if (ex instanceof ParamVlidationException) {
            paramVlidationException = (ParamVlidationException) ex;
        } else {
            paramVlidationException = new ParamVlidationException("未定义异常!");
        }

        String message = paramVlidationException.getMessage();

        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("message", message);

        modelAndView.setViewName("error");

        return modelAndView;
    }

}

 

 

 

 

3.4.4. springmvc.xml配置全局异常处理器

只要实现HandlerExceptionResolver接口,会加载且仅加载一个全局异常处理器

<bean class="cn.kai.sm.exception.OverallExceptionResolver"/>

 

3.5. 上传图片

form中提交enctype="multipart/form-data"的数据时,需要springmvcmultipart类型的数据进行解析

 

<!-- 文件上传 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为5MB -->
        <property name="maxUploadSize">
            <value>5242880</value>
        </property>
</bean>

 

创建图片虚拟目录存储图片

tomcat界面添加:

 

 

 

配置文件添加:

 

tomcatconf/server.xml中添加:

 

<Context docBase=""E:\workspace\pic_temp" path="/pic" reloadable="false"/>

public String updateItems(Model model,Integer id,@Validated(value = {ValidGroup1.class}) Items items,
            BindingResult result,MultipartFile items_pic) throws Exception 

if(items_pic!=null) {
            //图片原始名称
            String originalFilename = items_pic.getOriginalFilename();
            if(originalFilename!=null && originalFilename.length() > 0) {
                //图片物理存储地址
                String pic_path = "E:\\workspace\\pic_temp\\";
                //新图片名称
                String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
                //创建新图片
                File newfile = new File(pic_path+newFileName);
                //图片写入磁盘
                items_pic.transferTo(newfile);
                
                items.setPic(newFileName);
            }
                
        }
<td>商品图片</td>
    <td>
        <c:if test="${items.pic !=null}">
            <input type="hidden" name="pic" value="${items.pic}"/>
            <img src="/pic/${items.pic}" width=100 height=100/>
            <br/>
        </c:if>
        <input type="file"  name="items_pic"/> 
    </td>

3.6. json数据交互

3.6.1. 导入jar

 

 

 

3.6.2. 配置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>

如果使用<mvc:annotation-driven /> 则不用定义上边的内容

 

 

3.6.3. 页面

function jsonRequest(){
    $.ajax({
        type:"POST",
        url:"${pageContext.request.contextPath }/jsonRequest.action",
        contentType:"application/json;charset=utf-8",
        data:'{"id":"1","name":"笔记本","price":5000}',
        success:function(data){
            alert(data.id+":"+data.name+":"+data.price);
        }
    });
}
function keyValueRequest(){
    $.ajax({
        type:"POST",
        url:"${pageContext.request.contextPath }/keyValueRequest.action",
        //contentType:"application/json;charset=utf-8",  默认为key/value
        data:'id=1&name=笔记本&price=5000',
        success:function(data){
            alert(data.id+":"+data.name+":"+data.price);
        }
    });
}

3.6.4. Controller

json请求,json输出

 

//@RequestBody 将json格式请求转换为pojo实体类Items
    //@ResponseBody 将pojo实体类items转换为json格式输出
    @RequestMapping("/jsonRequest")
    public @ResponseBody Items jsonRequest(@RequestBody Items items) {
        return items;
    }

 

key/value请求,json输出

 

//@ResponseBody 将pojo实体类items转换为json格式输出
    @RequestMapping("/keyValueRequest")
    public @ResponseBody Items keyValueRequest(Items items) {
        return items;
    }

 

3.7. RESTful支持

3.7.1. RESTful架构

 

 

 

结构清晰、符合标准、易于理解、扩展方便

 

 

 

RESTurlhttp://...../queryItems.action?id=001&type=T01

 

RESTurl风格:http://..../items/001

 

特点:url简洁,将参数通过url传到服务端

 

 

 

例:

 

配置前端控制器:

<!-- springmvc前端控制器,RESTful配置 -->
    <servlet>
        <servlet-name>springmvc_rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- contextConfigLocation配置springmvc加载的配置文件 如果不配置contextConfigLocation,默认加载/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc_rest</servlet-name>
        <url-pattern>/</url-pattern>
</servlet-mapping>

Controller

 

//查询商品信息
    //返回json格式
    @RequestMapping("/queryItemsById/{id}")
    public @ResponseBody Items queryItemsById(@PathVariable("id") Integer itemsId) throws Exception {
        Items items = itemsService.findItemsById(itemsId);
        return items;
    }

 

@RequestMapping(value="/queryItemsById/{id}"){×××}占位符,请求的URL可以是“/queryItemsById/1”或“/queryItemsById/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。

如果RequestMapping中表示为"/ queryItemsById /{id}"id和形参名称一致,@PathVariable不用指定名称。

 

 

静态资源解析:

 

<!-- 静态资源解析 -->

 

    <!-- <mvc:default-servlet-handler/> -->

 

    <mvc:resources location="/js/" mapping="/js/**"/>

 

 

 

访问:

 

 

 

3.8. 拦截器

3.8.1. 定义拦截器,实现HandlerInterceptor接口

比如:统一日志处理拦截器,需要该拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。

 

比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)

 

3.8.2. 拦截器配置

类似全局的拦截器:

<!-- 配置全局拦截器
                            需要实现接口HandlerInterceptor
     -->
    <mvc:interceptors>
        <!-- 登陆拦截器 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="cn.kai.sm.interceptor.LoginInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="cn.kai.sm.interceptor.HandlerInterceptor1"/>
        </mvc:interceptor>
</mvc:interceptors>

 

针对某种mapping配置拦截器:

 

 <!-- 针对某种mapping配置拦截器 -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="loginInterceptor"/>
                <ref bean="handlerInterceptor2"/>
            </list>
        </property>
    </bean>
    <bean id="loginInterceptor" class="cn.kai.sm.interceptor.LoginInterceptor"/>
<bean id="handlerInterceptor1" class="cn.kai.sm.interceptor.HandlerInterceptor1"/>

 

3.8.3. Controller

@Controller
public class LoginController {

    // login
    @RequestMapping("/userLogin")
    public String userLogin(HttpSession session, String username, String password) {
        // service登陆逻辑
        // ...
        session.setAttribute("username", username);
        return "redirect:/items/queryItemsList.action";
    }

    // logout
    @RequestMapping("/userLogout")
    public String userLogout(HttpSession session) {
        // service退出逻辑
        // ...
        session.invalidate();
        return "redirect:/items/queryItemsList.action";
    }
}

3.8.4. LoginInterceptor

public class LoginInterceptor implements HandlerInterceptor {

    //进入handler之前执行
    //用于身份认证、身份授权
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
        String url = request.getRequestURI();
        //不需要登陆就能访问的地址不需要拦截
        if( url.indexOf("userLogin.action") > 0 ) {
            return true;
        }
        String username = (String) request.getSession().getAttribute("username");
        if(username!=null) {
            return true;
        }
        request.getRequestDispatcher("/WEB-INF/jsp/userLogin.jsp").forward(request, response);
        
        //false表示拦截,不向下执行
        //true表示不拦截
        return false;
    }
    
    //进入handler之后,返回ModelAndView之前
    //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
    }
    
    //执行handler完成之后执行
    //应用场景:统一异常处理,统一日志处理
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
    }

}

 

汇总:

posted @ 2021-02-15 23:40  無_茗  阅读(54)  评论(0)    收藏  举报