01_Springmvc学习及SSM整合

1. ssm的整合

思路:mvc三层架构
1. dao:mybatis
    1.1. mybatis的核心配置文件:sqlMapConfig.xml --配置Mapper映射文件的包名作为别名。
    1.2. applicationContext_dao.xml配置数据源,sqlSessionFactory(mybatis的session工厂),
    配置Mapper接口的basepackage(mybatis的动态代理开发,根据接口mybatis实现,我们只需要提供接口与mapper的sql配置即可)
    1.3. 上面1.2相当于完成了spring与mybatis的整合

2. service : spring
    2.1. applicationContext_service.xml:配置service层的注解扫描: 
        <context:component-scan base-package="com.itdream.ssm.service" />
    2.2. applicationContext_tx.xml:spring的事务管理

3. web : springmvc
    3.1. springmvc.xml : 
        1. 配置controller的注解扫描
        2. <!--配置注解驱动,HttpMappingHandlerMapping与HttpMappingHandlerAdapter代替默认淘汰的映射器与适配器-->
            <mvc:annotation-driven/>
        3.  配置视图解析器,简化controller层,返回页面view的书写
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
        </bean>

4. web.xml配置servlet容器(tomcat)启动加载spring,并且配置springmvc的前端控制器
    <!--spring的核心监听器-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:resources/spring/applicationContext-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--springmvc的前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:resources/spring/springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.action</url-pattern>
</servlet-mapping>

这里SpringMVC在拦截url请求时有三种方式:

1. /* 拦截所有,包括JSP
2. /  拦截所有,不包括JSP
3. *.action 只拦截以.action结尾的请求,不拦截静态资源等其他资源


如果使用了第二种拦截方式,但是又要放行静态资源如 js/jquery/css等,可以在springmvc.xml中进行配置:

<!--
    配置静态资源映射,让静态资源不被拦截
    location : 原资源文件的物理路径
    mapping : 映射的虚拟路径
-->
<mvc:resources mapping="/js/**" location="/js/"/>

2. springmvc的使用

2.1 @RequestMapping

通过@RequestMapping注解可以定义不同的处理器映射规则。

1.URL路径映射(写在方法上,根据url映射到对应的方法),value的值是数组,可以将多个url映射,到同一个方法,用逗号分隔
@RequestMapping(value="item")或@RequestMapping("/item")

@RequestMapping("/item/itemList.action")
public ModelAndView findItemList() {
    // 查询商品数据
    List<Item> list = this.itemService.queryItemList();

    // 创建ModelAndView,设置逻辑视图名
    ModelAndView mv = new ModelAndView("itemList");

    // 把商品数据放到模型中
    mv.addObject("itemList", list);
    return mv;
}

2. 写在类上,窄化路径
如 
@RequestMapping("/item")
public class itemController {}

相当于将所有方法上的RequestMapping前加了/item的前缀,可以用它来抽取或统一路径的前缀

3. 对方法的限定
    限定GET方法
    @RequestMapping(method = RequestMethod.GET)
    限定POST方法
    @RequestMapping(method = RequestMethod.POST)

2.2 Controller方法的返回值

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

2. 返回String(官方推荐)
    controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。数据使用Model model的model.addAttribbute(k,v)存储到request域
此外:返回String还支持重定向与请求转发,例如:
    return "redirect:/itemList.action";
    return "forward: /itemEdit.action?id="+id;

3. 返回void
    在Controller方法形参上可以定义request和response,使用request或response指定响应结果:适用于ajax请求访问

2.3 springmvc解决post请求乱码问题

在web.xml中添加拦截器,拦截所有请求,将其携带参数转为UTF-8格式
<!--解决Post乱码问题-->
<filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--设置编码参数是UTF-8-->
    <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>

如果要解决GET请求的乱码问题:
1.png

2.4 解决返回Json数据乱码问题

<!-- 解决返回Json数据乱码问题 -->
<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
          <property name="supportedMediaTypes">
              <list>
                <!-- 顺序不能乱 -->
                <value>text/html;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
              </list>
          </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

2.4 springmvc中的自定义参数转换器

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

前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,
并对方法中的形参进行参数绑定。可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。

一般使用<mvc:annotation-driven/>注解驱动加载处理器适配器,可以在此标签上进行配置。

1. 编写自定义转换器Converter 实现 Converter<S,T>
//S:source,需要转换的源的类型
//T:target,需要转换的目标类型
public class DateConverter implements Converter<String, Date> {

    @Override
    public Date convert(String s) {
        if (StringUtils.isEmpty(s)) {
            return null;
        }

        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return df.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}


2. 在springmvc.xml中配置自定义Converter

<!--conversion-service:自定义转换器-->
<mvc:annotation-driven conversion-service="conversionService"/>

<!--转换器配置-->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.itdream.ssm.converter.DateConverter"/>
        </set>
    </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>

<!-- 转换器配置 -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="cn.itcast.springmvc.convert.DateConverter" />
        </set>
    </property>
</bean>
注意:此方法需要独立配置处理器映射器、适配器,
不再使用<mvc:annotation-driven/>

3. springmvc的进阶知识点

3.1 自定义异常处理器

系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:

2.png

为了区别不同的异常,通常根据异常类型进行区分,这里我们创建一个自定义系统异常。
如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。

//自定义异常
public class CustomerException extends Exception {
    public CustomerException(String message) {
        super(message);
    }
}

接下来自定义异常处理器:

/**
 * 自定义异常处理器
 * Created by Administrator on 2017/8/29.
 */
public class MyEceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
        ModelAndView mav = new ModelAndView();

        //根据不同的异常定义友好提示信息
        if (e instanceof CustomerException) {
            mav.addObject("errorMsg", e.getMessage());
        } else {
            mav.addObject("errorMsg", "未知异常");
        }
        e.printStackTrace();
        //发生异常后跳转的页面WEB-INF/jsp/error.jsp
        mav.setViewName("error");
        return mav;
    }
}

最后,在springmvc.xml中配置该自定义异常处理器即可,那么以后碰到异常,前端控制器都会交给这个异常处理器处理:

<!--配置全局自定义异常处理器-->
<bean id="myEceptionResolver" class="com.itdream.ssm.exception.MyEceptionResolver"/>

3.2 springmvc实现图片上传

图片上传后需要保存到本地磁盘,配置tomcat的虚拟路径,在tomcat的config/server.xml中修改:
DocBase : 真实路径  path : 虚拟路径
<Context docBase="D:\upload\img" path="/img" reloadable="false"/>

我使用的idea也可以直接在ide工具配置:
    选择+,extra source选择要映射的真实路径,右侧ApplicationContext填写虚拟路径
3.png
配置完后,还需要在server勾选:勾选这里后,idea也可以直接访问tomcat的首页了,否则不行
4.png

加入jar包:

6.png

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

<!--配置文件上传解析器,id必须设为multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--配置上传文件的最大大小:50M:1*1024*1024*50-->
    <property name="maxUploadSize" value="52428800"/>
</bean>

同时前端页面需要满足:enctype="multipart/form-data

并且,input标签type为file,name与controller接收的形参名称一致

Controller实现文件上传,将上传的图片文件保存到本地服务器,并将路径保存到数据库:

//提供参数MultipartFile,参数名与前端的name一致
@RequestMapping("/updateItem.action")
public String updateItem(Items item, MultipartFile pictureFile) throws IOException {
    //获取文件原始名称
    String originalFilename = pictureFile.getOriginalFilename();
    //获取后缀名
    String ext = FilenameUtils.getExtension(originalFilename);
    //获取uuid随机文件名
    String name = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    String filename = "/img/" + name + "." + ext;

    //save to disk 上传保存到本地服务器
    pictureFile.transferTo(new File("D:/upload/img/" + name + "." + ext));

    //save to database 保存路径到数据库
    item.setPic(filename);
    itemsService.updateItems(item);
    return "redirect:/item/list.action";
}

3.3 json数据交互

加入jar包:

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

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

@RequestMapping("/testAjaxJson")
public @ResponseBody
Items testAjaxJson(@RequestBody Items item, ModelMap model) {
    System.out.println(item);
    return item;
}

3.4 Restful开发

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

1.使用注解@RequestMapping("item/{id}")声明请求的url
{xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”

2.使用(@PathVariable() Integer id)获取url上的数据   

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

/**
 * Restful风格开发  这里的url访问路径使用restful1.action,使用PathVariable()可以接收到url中的id
 */
@RequestMapping("restful{id}.action")
public String restful(@PathVariable() Integer id,ModelMap model) {
    Items item = itemsService.findItemsById(id);
    model.addAttribute("item",item);
    return "editItem";
}

3.5 springmvc的自定义拦截器

自定义拦截器实现HandlerIntercepter接口:进而实现它的三个方法

public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("执行方法前1");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("执行方法后1");

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("渲染页面后1");
    }
}

在springmvc.xml中配置自定义拦截器:

<!--自定义拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.itdream.ssm.interceptor.MyInterceptor1"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.itdream.ssm.interceptor.MyInterceptor2"/>
    </mvc:interceptor>
</mvc:interceptors>

总结:
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用

postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容