01_Springmvc学习及SSM整合

作者: 明天你好向前奔跑 | 来源:发表于2017-08-29 23:59 被阅读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才调用

    相关文章

      网友评论

        本文标题:01_Springmvc学习及SSM整合

        本文链接:https://www.haomeiwen.com/subject/fhfzdxtx.html