MyBatis+SpringMVC+SpringBootJava学习之路Java学习笔记

01_Springmvc学习及SSM整合

2017-08-29  本文已影响98人  明天你好向前奔跑

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才调用
上一篇下一篇

猜你喜欢

热点阅读