美文网首页
文件上传与下载&动态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