Spring MVC&&Spring整合框架

  • 三层架构 : 表现层 业务层 持久层
  • MVC设计模型: 模型 javabean 视图 jsp 控制器 servlet.
  • Spring MVC 与Struts2区别
    • 核心控制器不同 前者为Servlet,后者为Filter.
    • Spring MVC基于方法设计 而Struts2基于类,Struts2 多例,每次执行都会创建一个类.
    • Struts2 的OGNL表达式 开发效率更高,
Spring MVC 框架

过程:

  1. 环境搭建
    1. 导入依赖.
    2. 配置前端控制器. 配servlet. DispatcherServlet类.
    3. 配置Tomcat服务器.

编写代码
1… 首先前端jsp 文件需要调用后端servlet. 所以可以在java普通类中加注释@Controller. 注释需要扫描,所以还需要在xml配置文件中开启注解扫描.
2. 控制器类能扫描到了,要调用的方法怎么识别? 通过@RequestMapping 映射(path="/hello") ,映射hello路径为该方法的请求路径.
RequestMapping属性:value 与 path 是等价的; method属性指定请求的方法必须是哪些. params 指定请求要传过来哪些参数 headers指定要包含哪些请求头.
3. xml配置文件还没被加载,所以注解扫描无法生效.要让Tomcat服务器启动时就加载,需要在web.mxl里面全局初始化.

<init-param>
	<param-name>contextConifgLocation</param-name>
	<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
  1. 视图类 在WEB-INF 下创建pages文件夹, 需要配置 视图解析器对象.<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 需要内嵌两个属性.<property name="prefix" value="/WEB-INF/pages/"/> 视图类的目录,<property name="suffix" value=".jsp" /> 后缀名.

流程分析

  • 启动服务器,加载配置文件.
    • DispatcherServlet对象创建
    • 初始化参数 : springmvc.xml被加载
    • 扫描注解,Controller注解类被创建成对象.
  • 发送请求, 后台处理
    • 首先请求经过DispatcherServlet类, 根据请求路径,找到相应映射的方法.
    • return “success” 经前端控制器 DispatcherServlet 找视图解析器.
    • 当返回值为void时,默认的返回页面为WEB-INF/pages/映射同名.jsp . 要转发到成功页面, 用request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
    • 重定向 response.sendRedirect(request.getContextPath+“index.jsp”);
      在这里插入图片描述
请求参数绑定
  • 请求传的参数与方法参数对应时,会参数绑定,传的参数,方法就可以直接用.
  • 请求参数绑定实体类型 方法的参数写要封装的javabean的类. 请求参数名字要同成员变量名相同.
  • 当Javabean的类里面还有引用类时, 请求的参数 名字用user.name
  • 当Javabean的类里面还有集合类时,请求的参数 : List< User > 用 list[0].name Map< String,User> 用 map[‘one’].name
  • 请求传参中文乱码问题 用过滤器解决乱码问题.
  <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>
自定义类型转换器
  • SpringMVC框架提供了类型转换, 请求都传的是字符串,会给你转换成Integer 等相应类型. 但有些情况如date. 2099/9/9 会转换成功,但2099-9-9就会出现异常. 所以有些类型需要自定义转换器.
  • 实现Converter< String,Target>接口,实现convert方法.用target 要转换类型的格式化方法写相应格式. 如Date格式 用DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
  • 主配置文件中配置自定义类型转换器
    <!--配置自定义类型转换器-->
    <bean id="conversion" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!--注册自定义类型转换器-->
                <bean class="com.hk.utils.TestConverter"/>
            </set>
        </property>
    </bean>
<!-- 添加自定义类型转换器支持-->
    <mvc:annotation-driven  conversion-service="conversion"/>
SpringMVC常用注解
  • @RequestParam : 当传参与方法参数名称不匹配时, 需要在方法的参数前面@RequestParam(“传参的名称.”)
  • @RequestBody: Get请求方式不适用, 因为Get方式不会有请求体,内容直接写在URI后面. 在控制器类的方法参数(@RequestBody String body) 即得到body为请求体的内容.
  • @PathVariable:
    RESTful架构:URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。
    增加一个朋友,uri: generalcode.cn/v1/friends 接口类型:POST
    删除一个朋友,uri: generalcode.cn/va/friends 接口类型:DELETE
    修改一个朋友,uri: generalcode.cn/va/friends 接口类型:PUT
    查找朋友,uri: generalcode.cn/va/friends 接口类型:GET
    通过HTTP请求类型 而不是在URI里面写动词来描述操作.
    /friends/{id} PathVariable 即用于获取{id} 占位符的值.
    @RequestMapping("/aa/{sid}") 在方法参数中用@ParVariable(name=“sid”) String id 获取.
  • HiddenHttpMethodFilter 由于浏览器form表单只支持GET与POST请求,而DELETE,PUT等method并不支持,Spring3.0添加了一个过滤器,可以将请求的方式改为指定方式,使得能支持DELETE,PUT方式.
  • @RequestHeader 获取指定值的请求头
  • @CookieValue
  • @ModelAttribute 出现在方法上,表示当前方法会在控制器的方法执行之前先执行.有无具体返回值的方法都可修饰.
    可以用于表单数据不完整时,通过返回User 类,由于先执行,使其能传给控制器类一个完整的User封装数据.
    也可以没有返回值,通过Map< String,User> . 在控制器类方法参数上再加@ModelAttribute(“键”)
  • @SessionAttributes 为了降低耦合,控制器类的参数不会写 HttpRequest. 而是用提供的Model类. 底层会存储到request域对象中.
    @SessionAttributes 只能加在类上面. 可以通过键 将值存入session中.
    取session值 需要用到Model的实现类,ModelMap.
    删掉session值,用到SessionStatus类. 使用方法setComplete()
响应返回值
  • 返回值为ModelAndView类型 通过把user对象存储到ModelAndView对象中,同时也存入了request对象. (mv.addObject(“user”,user)).然后跳转页面,mv.setViewName(“success”); [用的视图解析器跳转] 返回String类型 底层是用的ModelAndView
响应JSON

使用jQuery,出现用不了的问题: 前端控制器拦截了静态资源. 在主配置文件中< mvc:resources mapping="/js/" location="/js/"/>

  1. 发送ajax请求
$("#btn").click(function () {
                /*发送ajax请求*/
                $.ajax({  //json格式
                    url:"account/testAjax", //要请求的java控制器方法路径.
                    contentType:"application/json;charset=UTF-8", //json默认类型
                    data:'{"userName":"aaa","password":"123","money":"300.5"}', //请求发送的数据
                    dataType:"json",
                    type:"post", //HTTP请求方法
                    success:function (data) { //请求成功后的回调函数
                        //data 服务器端响应过来的json数据,进行解析.
                        alert(data);
                        alert(data.userName);
                        alert(data.password);
                        alert(data.money);
                    }
                })
            });
  1. 控制器响应ajax请求.
    @RequestMapping(path = "/testAjax")   //映射该方法访问路径.
    //接受发送过来的ajax请求的数据 ,要用@RequestBody注解
    //导入Jackson相关jar包,可以自动将json数据封装成相应的javabean
    //客户端发送ajax请求,后台处理请求,封装成相应javabean
    public @ResponseBody Account testAjax(@RequestBody Account account){
        //请求传过来的数据.
        System.out.println(account);
        // 对请求做相应,模拟查询数据库 然后返回数据
        account.setUserName("bbb");
        account.setMoney(120);
        return account;
    }
文件上传

准备:
首先要把form表单的enctype 取值改为: multipart/form-data 正文内容变为多个部分,每一部分都是MIME类型描述.
method属性取值必须为post 因为get限制了大小64kb
提供一个文件选择域 < input type=“file”>
借助第三方组件 解析内容. commons-fileupload commons-io


编程:
准备前端内容 : 一个提交表单,准备部分的内容.然后写要调用后台的方法.
传统方式的主要步骤: 获取路径,要存储的文件夹是否存在,解析request对象.对上传文件项进行判断,然后写入.

//获取上传路径
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断是否有该文件夹
        File file = new File(path);
        if(!file.exists()){
            file.mkdirs();
        }

        //解析request对象,获取上传文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        //解析request
        List<FileItem> fileItems = fileUpload.parseRequest(request);
        for (FileItem item : fileItems){
            //判断item对象是否为上传文件项
            if(item.isFormField()){
                //说明为普通表单项
            }else{//说明为上传文件项
                //获取上传文件名
                String filename =item.getName();
                //完成上传
                System.out.println(item.getName());
                System.out.println(path);
                item.write(new File(path,filename));
                //删除临时文件
                item.delete();
            }
        }

SpringMVC方式 上传文件.
首先:配置文件解析器 用于解析request,然后返回update 上传文件项.

    <!--配置文件解析器  id名必须为multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--大小 : 10MB-->
        <property name="maxUploadSize" value="10485760"></property>
    </bean>

然后写上传方法.

//upload 与选择文件 input 标签的 name 必须一致. 使用的是参数绑定.
 public String  testupload2(HttpServletRequest request, MultipartFile upload) throws Exception {
        System.out.println("文件上传");
        //获取上传文件到什么路径下
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断是否有该文件夹
        File file = new File(path);
        if(!file.exists()){
            file.mkdirs();
        }
        String filename =upload.getOriginalFilename();
        //文件名称设置唯一值
        String uuid = UUID.randomUUID().toString().replace("-","");
        filename = uuid+"_"+filename;
        upload.transferTo(new File(path,filename));

        return "success";
    }

跨服务器上传文件,一般开发会有各个功能专用的服务器. 如应用服务器接受请求,向文件服务器存文件.
需要用到Jersey-core 以及 Jersey-client jar包
启动两个Tomcat 即可模拟两个服务器
两个服务器出现的一个问题就是 无法写入 需要在Tomcat的配置文件web.xml下的servlet标签下
<init-param> <param-name>readonly</param-name> <param-value>false</param-value> </init-param>
需要向另一个服务器将接受的上传文件路径传过去.所以需要创建一个客户端对象.

 //定义跨服务器上传路径
        String path ="http://localhost:9090/uploads/";
        String filename =upload.getOriginalFilename();
        //文件名称设置唯一值
        String uuid = UUID.randomUUID().toString().replace("-","");
        filename = uuid+"_"+filename;
        //创建客户端对象
        Client client = Client.create();
        //连接服务器
        WebResource resource = client.resource(path + filename);
        //作为客户端向图片服务器发送文件.
        resource.put(upload.getBytes());

        return "success";
拦截器

SpringMVC的处理拦截器类似于servlet的过滤器Filter,用于对处理器进行预处理和后处理.

区别:
过滤器是servlet规范的一部分,所有java web工程都可以使用
拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的才能用
过滤器在url-pattern配置了/*后,可对所有资源进行拦截.
而拦截器只会拦截访问控制器的方法,

  • 异常处理器组件

    • 编写自定义异常类(做提示信息)
    • 编写异常处理器
    • 配置异常处理器(跳转到提示页面)
  • 拦截器

    1. 编写拦截器类,实现HandlerInterceptor
      里面有三个方法
      preHandle postHandle afterCompletion
      控制器之前 控制器之后 跳转jsp页面之后
      return true: 放行,下一个拦截器,若没有,执行controller中方法.
      return false: 不放行,用request的getRequestDispatcher方法跳转到一个页面.controller不执行.
    2. 配置拦截器
    <mvc:interceptors>
        <!--配置拦截器-->
        <mvc:interceptor>
            <!--要拦截的方法  当请求/user下的方法时,拦截器拦截.-->
            <mvc:mapping path="/user/*"/>  <!--或者/** 访问的所有方法-->
            <!--不要拦截的方法-->
            <!--<mvc:exclude-mapping path=""/>-->
            <!--拦截器对象.-->
            <bean class="com.hk.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

SSM整合

三层:
视图层 SpringMVC 业务层 Spring 持久层 Mybatis 用业务层去整合其他两个框架.

  1. 先maven,用坐标配置jar包.
  2. 配置spring, resources/applicationContext.xml 开启扫描,排除SpringMVC注释.
  3. 先写Javabean,再写Dao,Service接口,Dao的实现类由Spring实现,不需要实现类,Service要自己写实现类.
  4. 配置SpringMVC,视图层用于与页面进行交互,首先要在web.xml里面配置前端控制器,让其在服务器加载时加载springmvc.xml文件.然后写上解决中文乱码的过滤器.
  5. 配置springmvc.xml.四步: 开启注解扫描,只包含Controller; 配置视图解析器InternalResourceViewResolver,属性prefix,suffix;过滤静态资源:mvc:resources;开启SpringMVC注解支持: mvc:annotation-driven.
  6. 用Spring框架整合SpringMVC:如下图:
    首先:
    Spring自带有监听器,所以直接在web.xml下配置监听器就行.
  <!--配置spring的监听器  默认只加载WEB-INF目录下的applicationContext.xml配置文件-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!--设置配置文件路径-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  1. 当配置spring监听器以后,Controller在启动时,现在已经加载了spring的配置文件,可以用spring的IOC容器. 于是就可以依赖注入后,通过对象调用业务层方法.
  2. 整合Mybatis . 首先写SqlMapConfig.xml 配置文件. ----> 配置环境(Mysql,JDBC…)—>引入映射文件.
    1.(mappers标签,推荐用package,可以映射dao包下所有方法,以后添加也不用再修改.)
    2.(连接Mysql时,数据库字符集设为了utf8,在url后面加上 ?characterEncoding=utf8 ) 避免数据库中文显示乱码问题.
    3.对于增删改的SQL操作,需要自己进行提交事务操作 . (Spring用声明式事务管理)
  3. Spring整合Mybatis. 在spring的配置文件applicationContext.xml文件下配置. [其实就是Mybatis配置文件内容放到Spring来整合]
    1.配置连接池. [c3p0连接池,Druid连接池] c3p0 用ComboPooledDataSource. Druid用DruidDataSource.
    2.Dao层需要用到代理对象. SqlSessionFactoryBuilder—>SqlSessionFactory—>SqlSession—>Session—>xxxxDao–>调用Dao方法.要配置Factory对象,用到SqlSessionFactoryBean类,以及需要代理的Dao对象所在包,用到MapperScannerConfigurer类.
    3.声明式事务管理配置. 配置事务管理器---->配置事务通知---->配置AOP增强.(即对xxxServiceImp AOP增强,需要用到通知.)
<!--Spring整合Mybatis-->
    <!--配置连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8"></property>
        <property name="user" value="root"></property>
        <property name="password" value="dz4663479"></property>
    </bean>
    <!--配置SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置扫描Dao接口所在包-->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hk.dao"></property>
    </bean>

    <!--配置Spring框架声明式事务管理-->
    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*" isolation="DEFAULT"></tx:method>
        </tx:attributes>
    </tx:advice>
    
    <!--配置AOP增强-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.hk.service.impl.*ServiceImp.*(..))"></aop:advisor>
    </aop:config>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值