zoukankan      html  css  js  c++  java
  • SpringMVC框架(3)--文件上传与SpringMVC拦截器

    SpringMVC文件上传原理:

    SpringMVC文件上传步骤:

    1、pom.xml中添加坐标

    <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.1</version>
        </dependency>
        <dependency>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
          <version>2.3</version>
        </dependency>

    2、创建web层的上传网页onload.jsp:

    <form action="${pageContext.request.contextPath}/user/onload" method="post" enctype="multipart/form-data"><!--action后也可以使用相对路径,要保持与controller中的方法映射地址一致-->
            名称<input type="text" name="username"><br/><!--name与controller中的方法参数名字保持一致-->
            文件1<input type="file" name="uploadFile"><br/><!--file文件传到后台接收数据类型为MultipartFile-->
            <input type="submit" value="提交">
        </form>

    文件上传客户端表单需要满足:

    表单项type=“file”

    表单的提交方式是post

    表单的enctype属性是多部分表单形式,及enctype=“multipart/form-data”

    3、在spring-mvc中配置文件解析器:

    <!--配置文件上传解析器-->
    <bean id="multipartResolver"
                class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--上传文件的编码类型-->
        <property name="defaultEncoding" value="UTF-8"/>
        <!--文件上传的总大小(10M)-->
        <property name="maxUploadSize" value="10485600"/>
        <!--单个文件的大小(5M)-->
        <property name="maxUploadSizePerFile" value="5242800"/>
    </bean>

    还有很多条件可以设置,自行了解.

    4、在controller中接收

    @RequestMapping(value="/onload")
        @ResponseBody
        public void save22(String username, MultipartFile uploadFile) throws IOException {
            System.out.println(username);
            //获得上传文件的名称
            String originalFilename = uploadFile.getOriginalFilename();
           originalFilename = new Date().getTime() + "_" + filename;//为了防止保存的文件名一致覆盖早期文件,加上时间戳 uploadFile.transferTo(
    new File("C:\upload\"+originalFilename));//保存路径,采用transferTo方法 }

    在Controller的方法参数中,书写MultipartFile类型的参数。

    参数名字必须和表单中“文件上传项”的name属性保持一致.

    多文件上传:

    多文件上传与单文件上传基本一致,只要将前端页面和后台接收稍微改一下就行。

    表单代码:

    <form action="upload" method="post" enctype="multipart/form-data">
        姓名: <input type="text" name="name" /> <br/>
        图片1: <input type="file" name="uploadFile"><br/>
        图片2: <input type="file" name="uploadFile"><br/>
        <input type="submit" value="提交">
    </form>

    后台接收:

    @RequestMapping(value="/upload")
        @ResponseBody
        public void save(String username, MultipartFile[] uploadFile) throws IOException {
            System.out.println(username);
            for (MultipartFile multipartFile : uploadFile) {
                String originalFilename = multipartFile.getOriginalFilename();
             originalFilename = new Date().getTime() + "_" + filename;
                multipartFile.transferTo(new File("C:\upload\"+originalFilename));
            }
        }

    只需要将页面修改为多个文件上传项,将方法参数MultipartFile类型修改为MultipartFile[]即可,但是,要求数组名字,必须和表单中“文件上传项”的name属性保持一致。

    SpringMVC的拦截器:

    SpringMVC拦截器的作用:

    Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。

    将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

    关于interceptor和filter的区别:

     

    配置SpringMVC拦截器的步骤:

    ①创建拦截器类实现HandlerInterceptor接口

    定义一个类,实现HandlerInterceptor接口,重写方法

    public class MyInterceptor1 implements HandlerInterceptor {
        //在目标方法执行之前 执行
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException {
            System.out.println("preHandle.....");
    }
        //在目标方法执行之后 视图对象返回之前执行
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    System.out.println("postHandle...");
        }
        //在流程都执行完毕后 执行
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            System.out.println("afterCompletion....");
        }
    }

    一般都只使用重写preHandle方法。

    ②配置拦截器

    在SpringMVC的配置文件中配置

    <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--对哪些资源执行拦截操作-->
                <mvc:mapping path="/**"/>
                <bean class="com.itheima.interceptor.MyInterceptor1"/>
            </mvc:interceptor>
        </mvc:interceptors>

    ③测试拦截器的拦截效果

    编写Controller,发请求到controller,跳转页面

    @Controller
    public class TargetController {
    
        @RequestMapping("/target")
        public ModelAndView show(){
            System.out.println("目标资源执行......");
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("name","itcast");
            modelAndView.setViewName("index");
            return modelAndView;
        }
    
    }

    页面

    <html>
    <body>
    <h2>Hello World! ${name}</h2>
    </body>
    </html>

    注意事项:

    1.拦截器的拦截规则,针对的进入springmvc流程的那些请求.

    2.HandlerInterceptor接口中有三个方法:

    preHandler 在目标方法执行之前执行

    postHandle 在目标方法执行之后,视图对象返回之前执行

    afterCompletion 在流程都执行完毕后执行

    3.拦截器可以有多个,组成拦截器链

    可以使用拦截器去做一个用户登录权限控制代码实现:

    原理:拦截器判断用户是否登录 本质:判断session中有没有user,如果没有登陆则先去登陆,如果已经登陆则直接放行访问目标资源

    拦截器:

    public class PrivilegeInterceptor implements HandlerInterceptor {
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
            //逻辑:判断用户是否登录  本质:判断session中有没有user
            HttpSession session = request.getSession();
            User user = (User) session.getAttribute("user");
            if(user==null){
                //没有登录
                response.sendRedirect(request.getContextPath()+"/login.jsp");
                return false;
            }
            //放行  访问目标资源
            return true;
        }
    }

    然后配置该拦截器:找到项目案例的spring-mvc.xml,添加如下配置:

    <!--配置权限拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--配置对哪些资源执行拦截操作-->
                <mvc:mapping path="/**"/>
                <bean class="com.itheima.interceptor.PrivilegeInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>

    在登陆页面输入用户名密码,点击登陆,通过用户名密码进行查询,如果登陆成功,则将用户信息实体存入session,然后跳转到首页,如果登陆失败则继续回到登陆页面

    在UserController中编写登陆逻辑

    @RequestMapping("/login")
        public String login(String username,String password,HttpSession session){
            User user = userService.login(username,password);
            if(user!=null){
                //登录成功  将user存储到session
                session.setAttribute("user",user);
                return "redirect:/index.jsp";
            }
            return "redirect:/login.jsp";
        }

    service层代码如下:

    //service层
    public User login(String username, String password) {
                User user = userDao.findByUsernameAndPassword(username,password);
                return user;
    }

    dao层代码如下:

    //dao层
     public User findByUsernameAndPassword(String username, String password) throws EmptyResultDataAccessException{
            User user = jdbcTemplate.queryForObject("select * from sys_user where username=? and password=?", new BeanPropertyRowMapper<User>(User.class), username, password);
            return user;
        }

    我们还需要将登陆请求url让拦截器放行,添加资源排除的配置:

    <!--配置权限拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--配置对哪些资源执行拦截操作-->
                <mvc:mapping path="/**"/>
                <!--配置哪些资源排除拦截操作-->
                <mvc:exclude-mapping path="/user/login"/>
                <bean class="com.itheima.interceptor.PrivilegeInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>

    在业务层处理来自dao层的异常,如果出现异常service层返回null,而不是将异常抛给controller,因此改造登陆的业务层代码,添加异常的控制:

    public User login(String username, String password) {
            try {
                User user = userDao.findByUsernameAndPassword(username,password);
                return user;
            }catch (EmptyResultDataAccessException e){
                return null;
            }
        }

    测试就可以了

  • 相关阅读:
    模型层之多表操作
    模型层:表单操作
    Django模板层
    第六十课、数组类模板
    第五十九课、类模板的深度剖析
    第五十八课、类模板的概念和意义
    第五十七课、深入理解函数模板
    第五十六课、函数模板的概念和意义
    第五十五课、经典问题解析四
    第五十四课、被遗弃的多重继承(下)
  • 原文地址:https://www.cnblogs.com/j9527/p/12040800.html
Copyright © 2011-2022 走看看