美文网首页
文件上传与下载&动态SQL

文件上传与下载&动态SQL

作者: sunboximeng | 来源:发表于2018-12-24 01:01 被阅读9次

    框架重点:

    1. springMVC实现文件的上传与下载,其实也没什么special,只是数据格式不一样了。前后台交互的数据格式可分为Json、xml以及二进制数据。
        1.1 SpringMVC提供了这样的一个机制,允许控制器返回的数据不经过正常的视图处理流程,而是直接将返回的数据写入响应体中(response body)。
        1.2 springMVC和mybatis一样都会自动封装数据到对象中。还记得没有这些框架时候的样子吗?
            request对象的getParameter方法获得参数后,才能放在对象里。
                String username = req.getParameter("username");
                String password = req.getParameter("password");
                User loginUser = new User();
                loginUser.setUsername(username);
                loginUser.setPassword(password);
            jdbcTemplate:
                String sql = "select * from user where username = ? and password = ?";
                User user = template.queryForObject(sql,
                                new BeanPropertyRowMapper<User>(User.class),
                                loginUser.getUsername(), loginUser.getPassword()); 
    2. mybatis实现一对多查询。条件查询的动态SQL。日期处理。
        建立的实体类要反应一对多的关系。但是实体类分两种,一种用于封装数据库数据,另一种用于返回给前端,避免暴露属性,阉割版。
    3. spring感觉没啥重点,提供容器、AOP(事务管理)。
    

    登录的实现:filter、AOP、专用框架。用户的token是怎么生成的?

    filter的例子课程有,项目也是这么用的。此外,还可实现统一编码处理、敏感字符过滤(动态代理的好场景)。
        过滤器和servlet一样,都要配置拦截路径。只是过滤器是个接口,规定了必须实现的方法。它的核心是doFilter方法,就像servlet的核心是sevice方法。
    AOP是微信点餐
    框架就是spring-security
    

    IO流,java web的技术。

    springMVC框架所需要的依赖:
    文件上传下载:Apache提供Commons FileUpload组件jar包。
    json处理:
    方式一:使用jackson。
    jackson-annotations-2.8.9.jar
    jackson-core-2.8.9.jar
    jackson-databind-2.8.9.jar
    方式二:使用fastjson
    fastjson-1.2.35.jar
    springmvc的配置文件需要配置:

    <mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">

    <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
    <property name="supportedMediaTypes">
    <list>
    <value>text/html;charset=UTF-8</value>
    <value>application/json</value>
    </list>
    </property>
    <property name="features">
    <list>

                                <value>QuoteFieldNames</value> <!-- 输出key时是否使用双引号,默认为true -->
                                <value>WriteMapNullValue</value>  <!-- 是否输出值为null的字段,默认为false -->
        
                                <!-- 
                                <value>DisableCircularReferenceDetect</value>
                                <value>WriteDateUseDateFormat</value> 
                                <value>WriteNullStringAsEmpty</value>  字符类型字段如果为null,输出为"",而非null 
                                <value>WriteNullNumberAsZero</value>  数值字段如果为null,输出为0,而非null 
                                <value>WriteNullBooleanAsFalse</value>  Boolean字段如果为null,输出为false,而非null 
                                <value>WriteNullListAsEmpty</value>    List字段如果为null,输出为[],而非null
                                -->
        
                            </list>
                        </property>
                    </bean>
                </mvc:message-converters>
            </mvc:annotation-driven>
    

    文件上传:

    ​ 文件上传是项目开发中最常见的功能。为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。
    上传的文件其实也是一个表单域。nothing special。
    上传的本间可以保存在本地的/WEB-INF/upload文件夹下,还可以放在文件服务器下。

        1. 获得真实目录:request.getServletContext()..getRealPath() //服务器在保存文件的时候要用到
        获取请求行数据: * GET /day14/demo1?name=zhangsan HTTP/1.1
        2. (*)获取虚拟目录:/day14
            * String getContextPath()
            * jsp页面form表单的action路径的写法:虚拟目录+Servlet的路径。 但是ajax使用的都是相对路径啊,貌似这是因为springMVC自动加上的。
        3. 获取Servlet路径: /demo1
            * String getServletPath()
        4. 获取get方式请求参数:name=zhangsan
            * String getQueryString()
        5. (*)获取请求URI:/day14/demo1
            * String getRequestURI():       /day14/demo1
            * StringBuffer getRequestURL()  http://localhost/day14/demo1
    

    配置文件


    ​ <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    ​ <property name="maxUploadSize" value="200000"/>
    ​ </bean>

    用于上传的表单页面/WEB-INF/jsp/upload.jsp

    <%@ page language="java" pageEncoding="UTF-8"%>

    <form method="POST" enctype="multipart/form-data">

    ​ yourfile: <input type="file" name="myfiles"/>

    yourfile: <input type="file" name="myfiles"/>

    yourfile: <input type="file" name="myfiles"/>

    <input type="submit" value="上传文件"/>

    </form>

    核心的UploadController.java

    /**
    SpringMVC中的文件上传步骤:

        @第一步:由于SpringMVC使用的是commons-fileupload实现,故将其组件引入项目中,这里用到的是commons-fileupload-1.2.2.jar和commons-io-2.0.1.jar  
    
        @第二步:在####-servlet.xml中配置MultipartResolver处理器。可在此加入对上传文件的属性进行限制  
    
        @第三步:在Controller的方法中添加MultipartFile参数。该参数用于接收表单中file组件的内容  
    
        @第四步:编写前台表单。注意enctype="multipart/form-data"以及<input type="file" name="**"/> name要和后台接收参数时的名字相同 
    

    */

    @Controller

    public class TestController {

    ​ @RequestMapping(value="/uploadfile",method=RequestMethod.GET)

    ​ public String upLoadFile() { return "upload"; }

    ​ @RequestMapping(value="/uploadfile",method=RequestMethod.POST)

    ​ public String upLoadFile(@RequestParam MultipartFile[] myfiles, HttpServletRequest request) throws IOException {

    ​ //如果只是上传一个文件,则只需要MultipartFile类型接收文件即可,而且无需显式指定@RequestParam注解

    ​ //如果想上传多个文件,那么这里就要用MultipartFile[]类型来接收文件,并且还要指定@RequestParam注解

    ​ //并且上传多个文件时,前台表单中的所有<input type="file"/>的name都应该是myfiles,否则参数里的myfiles无法获取到所有上传的文件

    ​ for(MultipartFile myfile : myfiles) {

    ​ if(myfile.isEmpty()) {

    ​ System.out.println("文件未上传");

    ​ continue;

    ​ }

    ​ else {

    ​ System.out.println("文件长度: " + myfile.getSize());

    ​ System.out.println("文件类型: " + myfile.getContentType());

    ​ System.out.println("文件名称: " + myfile.getName());

    ​ System.out.println("文件原名: " + myfile.getOriginalFilename());

    ​ System.out.println("===================");

    //如果用的是Tomcat服务器,则文件会上传到\%TOMCAT_HOME%\webapps\YourWebProject\WEB-INF\upload\文件夹中                  
    

    ​ String realPath = request.getSession().getServletContext().getRealPath("/WEB-INF/upload");

    //这里不必处理IO流关闭的问题,因为FileUtils.copyInputStreamToFile()方法内部会自动把用到的IO流关掉,我是看它的源码才知道的

    FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath + "/" +myfile.getOriginalFilename())); } } return " success_fileupload "; } }

    条件查询,动态SQL。

    1. 根据对象查询

    List<User> findByUser(User user);

    <select id="findByUser" resultType="user" parameterType="user">

    select * from user where 1=1
    
    <if test="username!=null and username != '' ">
        and username like #{username}
    </if>
    
    <if test="address != null">
        and address like #{address}
    </if>
    

    </select>


    <sql id="defaultSql">
    select * from user
    </sql>

    使用<where>进行改进
    <select id="findByUser" resultType="user" parameterType="user">

    <include refid="defaultSql"></include>
    
    <where>
        <if test="username!=null and username != '' ">
            and username like #{username}
        </if>
        <if test="address != null">
            and address like #{address}
        </if>
    </where>
    

    </select>

    1. 根据集合查询

    需求:SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
    List<User> findInIds(QueryVo vo); //参数的属性是一个集合,username也可以作为属性放在这个对象里面吗?


    <select id="findInIds" resultType="user" parameterType="queryvo">

    <include refid="defaultSql"></include>
    <where>
    <if test="ids != null and ids.size() > 0">
    <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
    #{uid}
    </foreach>
    </if>
    </where>
    </select>

    <foreach>标签用于遍历集合,它的属性:
    collection:代表要遍历的集合元素,注意编写时不要写#{}
    open:代表语句的开始部分
    close:代表结束部分
    item:代表遍历集合的每个元素,生成的变量名
    sperator:代表分隔符

    一对多,多里面就要做标记。
    User--Account

    1. 利用账户查用户
      方式一:SQL查询结果可能需要定义一个新的实体类来进行封装。
      <select id="findAll" resultType="accountuser">
      select a.,u.username,u.address from account a,user u where a.uid =u.id;
      </select>
      方式二:“多”持有“一”的引用。较方式一更灵活。弊端是需要制定映射关系,因为要制定封装方法。
      SQL关键字:association*。

      <resultMap type="account" id="accountMap">
      <id column="aid" property="id"/>
      <result column="uid" property="uid"/>
      <result column="money" property="money"/>

       <!-- 它是用于指定从表方的引用实体属性的 -->
       <association property="user" javaType="user">
           <id column="id" property="id"/>
           <result column="username" property="username"/>
           <result column="sex" property="sex"/>
           <result column="birthday" property="birthday"/>
           <result column="address" property="address"/>
       </association>
      

      </resultMap>

      <!--sql语句-->
      <select id="findAll" resultMap="accountMap">
      select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;
      </select>

    2. 利用用户查询账户
      用户信息和他的账户信息为一对多关系,并且查询过程中如果用户没有账户信息,此时也要将用户信息
      查询出来,我们想到了左外连接查询比较合适。
      一持有多的集合。
      SQL关键字collection
      <resultMap type="user" id="userMap">
      <id column="id" property="id"></id>
      <result column="username" property="username"/>
      <result column="address" property="address"/>
      <result column="sex" property="sex"/>
      <result column="birthday" property="birthday"/>

       <!-- collection 是用于建立一对多中集合属性的对应关系
       ofType 用于指定集合元素的数据类型-->
       <collection property="accounts" ofType="account">
           <id column="aid" property="id"/>
           <result column="uid" property="uid"/>
           <result column="money" property="money"/> 
       </collection>
      

      </resultMap>

      <select id="findAll" resultMap="userMap">
      select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
      a on u.id =a.uid
      </select>

    3. 多对多。比如权限管理里面全是多对多。三表等值连接。
      需求:实现查询所有对象并且加载它所分配的用户信息。
      多对多也是要被拆分成一对多的。只不过谁持有谁的集合的引用是不确定的。

    页面上传文件,关键是文件的保存位置。
    图片服务器:这就简单了,调用API即可。后两者都需要找到文件夹的路径。下面两者需要获取物理路径。
    项目里面
    webapps里面
    页面下载文件
    向页面返回什么?对于页面识别的类型还需要进行强制下载。

    没有request怎么获取项目IP和端口?场景:定时任务、向注册中心注册自己

    相关文章

      网友评论

          本文标题:文件上传与下载&动态SQL

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