SpringMVC -- 梗概--贰

1.为什么要配置: mvc:annotation-driven

1>在springMVC的处理流程中,有两个重要组件:HandlerMapping和HandlerAdapter
  分别负责解析Handler和执行Handler
2>如果配置了<mvc:annotation-driven/>,则在项目中自动注册:
  RequestMappingHandlerMapping
  RequestMappingHanderAdapter
  且如上两个组件是对注解开发最新的最全面的支持
3>如果没有配置:<mvc:annotation-driven/>
  则默认使用:
  DefaultAnnotationHandlerMapping
  AnnotationMethodHandlerAdapter两个组件
  而如上两组间已经弃用,且其对注解的支持并不全面,
  比如@ResponseBody是不能被解析的。
*详细的springMVC流程:

2.静态资源的访问问题

配置:<mvc:default-servlet-handler/>
1>静态资源:除了Servlet、Controller之外的资源,如:js,css,png,html等
2>当请求静态资源:...xx/xx/xx.js,...xx/xx/xx.css,...xx/xx/xx.png等
 如上请求会逐步回溯到【/】,即会进入DispatcherServlet,则会有HanderMapping
 取查找Hanler,自然无法找到。此时如果没有如上配置,则404.
3>如果有如上配置,则在项目中会自动注册【/**】的一个handler,且此handler
  会在最后映射请求,如果是项目中存在指定的静态资源,则会转向静态资源。

3.RestFul收参(了解) @PathVariable

1>定制方式:
    //如下两个路径都可以访问到如下方法,请求路径不同,则name61和pwd61匹配到的值不同
    //http://localhost:8989/appname/ful/lime/123
    //http://localhost:8989/appname/ful/oracle/456
    //@PathVariable("pwd61")-->获取路径中pwd61部分匹配到的值,并存入对应参数
    @RequestMapping("/ful/{name61}/{pwd61}")
    public String testMVC(@PathVariable("name61")String name,@PathVariable("pwd61")String password){
        System.out.println("name:"+name+" password:"+password);
        return "forward:/index.jsp";
    }
    *注意:所有的/ful/xx/xx的路径都可以访问到如上方法
2>细节:如果路径名 和 参数名 一致,则可以有省略写法,如下
    @RequestMapping("/ful3/a{age}b/h{password}ilo")
    public String testMVC3(@PathVariable Integer age,@PathVariable String password){
        System.out.println("age:"+age+" password:"+password);
        return "forward:/index.jsp";
    }
    *即【@PathVariable Integer age】将路径中名为age的部分匹配到的值存于age中

4.异常管理

4.1 定制异常管理器

public class MyExceptionResolver implements HandlerExceptionResolver{
    /**
     * 主体逻辑:自动捕获Controller中的异常,每当Controller中抛出异常时,就会执行。
     * param:ex=当前抛出的异常
     *       req=请求对象
     *       res=响应对象
     *       handler=抛出异常的控制器方法
     * 返回值:ModelAndView=用来返回错误页面
     */
    public ModelAndView resolveException(HttpServletRequest req,
            HttpServletResponse res, Object handler, Exception ex) {
        ModelAndView mav=new ModelAndView();
        //识别异常
        if(ex instanceof LoginErrorException){
            mav.setViewName("redirect:/error1.jsp");
        }else if(...){}
        ...
        return mav;
    }
}

4.2 声明

<bean class="com.c61.ex.resolver.MyExceptionResolver"></bean>

4.3 异常管理器作用

作用:统一抽取了所有控制器中的异常处理逻辑
抽取前:
    public String login(String username,String password){
        try{
            us.login(username, password);
        }catch(LoginErrorException e){
            return "redirect:/login.jsp";
        }catch(AException e){
            return "redirect:/xxx.jsp";
        }catch(Exception e){

        }
        return "forward:/index.jsp";
    }
抽取后:
    public String login(String username,String password){
        us.login(username,password);
        return "forward:/index.jsp";
    }

5.拦截器:Interceptor,抽取Controller中的冗余功能

5.1 定制

public class MyInterceptor implements HandlerInterceptor{
    /**
     * 在Controller之前执行(常用)
     * 抽取Controller中的冗余功能
     */
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res,
            Object handler) throws Exception {
        //return false;//中断请求,则后续的controller,postHandle...都不再执行
        //return true;//请求继续
        if(xxx){
            String path=req.getContextPath();
            res.sendRedirect(path+"/index.jsp");//中断之前设置错误视图
            return false;
        }
        return true
    }
    /**
     * 在Controller之后,在响应之前,执行(了解)
     * 可以做视图和数据的最终定制
     */
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView mav) throws Exception {
    }
    /**
     * 在视图渲染完毕后执行(了解)
     * 资源回收
     */
    public void afterCompletion(HttpServletRequest req,
            HttpServletResponse res, Object handler, Exception ex)
            throws Exception {
    }
}

5.2配置

<mvc:interceptors>
    <mvc:interceptor>
        <!-- 定义要拦截的路径 -->
        <mvc:mapping path="/inter/test"/>
        <mvc:mapping path="/inter/a"/>
        <mvc:mapping path="/inter/b"/>
        <!-- 声明拦截器 -->
        <bean class="com.c61.interceptor.MyInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <!-- 定义要拦截的路径 -->
        <mvc:mapping path="/inter/**"/>
        <mvc:exclude-mapping path="/inter/test/**"/>
        <!-- 声明拦截器 -->
        <bean class="com.c61.interceptor.MyInterceptor2"/>
    </mvc:interceptor>
 </mvc:interceptors>
 *注意:
    1>当有多个拦截器同时拦截时,先配置的先拦截。如过Controller1 先后被inter1和inter2拦截,则具体的拦截路程为:
      pre1==pre2==contorller==post2==post1==after2==after1
    2>/* 只能匹配一级路径:/a  /b  /c  /xxxxxx
.     却不能匹配:/a/b  /e/d/c 
      /** 能匹配任意多级路径:/a  /b  /a/b/c  /xxs/xxx/xxx/xx
    3>mvc:exclude-mapping 不能单独使用,必须配合 mvc:mapping 使用
.     作用是在mvc:mapping的基础上排除一些路径

6.上传

6.1 定制上传表单

1>method="post"
2>enctype="multipart/form-data"
<form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/up/test">
    <input type="file" name="file61"/>
    <input type="submit" value="上传"/>
</form>

6.2 定制接收文件的Controller

public String testUP(MultipartFile file61,HttpSession s) throws IllegalStateException, IOException{
    //file61.transferTo(new File("d:/abc/abc.txt"));
    //获取虚拟路径:/up61 对应部署到服务器后的具体的磁盘路径
    String realPath=s.getServletContext().getRealPath("/up61");
    //获取文件名 xxx.txt  xxx.png
    String fileName=file61.getOriginalFilename();
    //拼接写出路径
    String path=realPath+File.separator+fileName;
    //将文件写出到指定目录位置
    file61.transferTo(new File(path));
    return "forward:/index.jsp";
}

6.3 在springMVC容器中注册文件上传解析器

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 最大允许的上传大小    byte -->
    <property name="MaxUploadSize" value="2097152"></property>
 </bean>
 *ID必须为:multipartResolver

6.4 导包:commons-fileupload-1.3.jar commons-io-2.0.1.jar

6.5 生成唯一的文件名

//32长度 由16进制字符组成的全球唯一的字符串
UUID uuid=UUID.randomUUID();
System.out.println(uuid);
//uuid.toString()可以作为文件名使用,注意要拼接后缀

6.6 回显上传的图片

<!-- target="c61" 将响应展示在名为c61的iframe中(不再用一张新页面承载响应)  -->
<form target="c61" method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/up/test">
    <input type="file" name="file61"/>
    <input type="submit" value="上传"/>
</form>
<iframe name="c61" width="200px" height="200px" frameborder="0"></iframe>

7.下载 (了解)

7.1 定制超链接

<a href="${pageContext.request.contextPath}/down/test?name=html教程全.ppt">免费下载</a>

7.2 定制下载的Controller

public String testDown(String name,HttpSession s,HttpServletResponse res) throws FileNotFoundException, IOException{
    String path=s.getServletContext().getRealPath("/up61");
    String filePath=path+File.separator+name;
    //如果文件名中有中文:
    String name2=URLEncoder.encode(name, "utf-8");
    //设置响应头,实现附件形式下载文件(告知浏览器,需要以附件形式接收)
    res.setHeader("content-disposition", "attachment;filename="+name2);
    //输入流读取所有字节,输出流将所有读取到的字节写出
    IOUtils.copy(new FileInputStream(filePath),res.getOutputStream());
    return null;//如上语句,已经响应了请求,则必须return null;
}

8.验证码 见:第三阶段springMVCgoogle_验证码使用.txt

9.与spring集成

1>只是将代码累加在一起而已
2>当SpringMVC的Controller需要Spring的Service时,可以平行获取
3>唯一的注意点:防止容器之间相互污染
  *容器污染防止手段:springMVC扫描控制机器相关组件,spring扫描剩余的
   <context:component-scan base-package="com.c61">...
  *解决方案一:use-default-filters="true"(true=默认值),则默认扫描所有的@Controller,@Service,@Repository
    <context:component-scan base-package="com.c61" use-default-filters="true">
        <!-- 排除某些注解,被排除的注解将不会扫描 -->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
.   </context:component-scan>
. *解决方案二:use-default-filters="false" 不再主动扫描任何注解,在配合上include-filter,实现只扫描某个/些注解
    <context:component-scan base-package="com.c61" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
原文地址:https://www.cnblogs.com/ClassNotFoundException/p/6046759.html