JavaWeb

JavaWeb

1、概念

  • 静态web
    • html ,css
    • 轮播图,点击特效:实现了伪动态
      • 伪动态技术实现:JavaScript[实际开发用的多],VBScript
  • 动态web
    • 技术栈:Servlet/JSP,ASP,PHP

ASP:

  • 微软:国内最早流行的
  • 在HTML中嵌入VB的脚本,ASP+COM;
  • 维护成本高,页面混乱
  • C#

PHP:

  • 开发速度快,跨平台
  • 无法承载大访问量的情况

JSP/Servlet:

  • sun公司主推的B/S架构
  • 可以承载高并发,高可用,高性能带来的影响;

2、Web服务器

IIS

微软的;ASP,Windows中自带的

Tomcat

实际上运行JSP页面和Servlet

2.1、Tomcat启动和配置

Tomcat核心配置文件,conf/server.xml

可以配置主机端口号,默认端口号8080;

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" 
           URIEncoding="UTF-8"/>

可以配置主机名称:

  • 默认的主机名为localhost:127.0.0.1
    • 在本地配置中System32/drivers/etc host配置文件中修改
  • 默认网站存放位置webapps
<Host name="localhost"  appBase="webapps"
      unpackWARs="true" autoDeploy="true">

面试题:

网站如何进行访问?

  • 输入域名
  • 检查本机的C:\Windows\System32\driver\etc\hosts配置文件有没有这个域名映射;
    • 若查找到对应域名映射,返回ip地址
    • 若本机没有查找到去DNS查找

2.2、HTTP

超文本传输协议,http:80,https:443

2.2.1、两个时代
  • http 1.0
    • 协议http/1.0:客户端可以与web服务器连接后,只能获得一个web资源,断开连接
  • http 2.0
    • 协议http/1.1:客户端可以与web服务器连接后,能获得多个web资源,断开连接
2.2.2、HTTP请求和响应

请求行:

  • 请求方式:Get/Post,head,delete,put,tract
    • get:请求能够携带的参数比较少,大小有限制,会显示,不安全,但是高效
    • post:请求能够携带的参数没有限制,大小无限制,不显示,安全但是不高效

消息头:

  • Accept:浏览器所支持的数据类型
  • Accept-Encoding:支持的编码格式 GBK UTF-8 GB2312 ISO8859-1
  • Accept-Language:语言环境
  • Cache-Control:缓存控制
  • Connection:请求完成是否断开连接
  • Host:主机

响应体:

  • 与消息头相同;

响应状态码:

  • 200:响应成功
  • 3**:请求重定向
  • 404:页面不存在
  • 5**:服务器代码错误

面试题:

浏览器地址栏输入并回车到页面展示都经历了什么?

3、Servlet

用于开发动态web

Servlet接口在Sun公司有两个默认的实现类:HttpServlet,GenericServlet

为什么编写Servlet映射?

  • 我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,并且还需要给他一个浏览器能够访问的路径
<!--注册servlet-->
<servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.shine.HelloServlet</servlet-class>
</servlet>
<!--一个servlet对应一个Mapping:映射-->
<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <!--请求路径-->
    <url-pattern>/shine</url-pattern>
</servlet-mapping>

3.1、Servlet原理

Servlet是由Web服务器调用,web服务器在收到浏览器的首次请求后,会将类加载为class后运行,web容器会产生请求和响应

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1rnOJlG-1654347700567)(C:\Users\阳光就在天上\Desktop\flag\Servlet请求原理.png)]

3.2、Mapping相关问题

  • 优先级问题
    • 指定了固有的映射路径优先级最高,如果找不到就会走默认的请求处理;
  • 指定后缀
    • 自定义后缀实现请求映射
<!--注意:*前不能加项目的映射路径-->
<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>*.sunshine</url-pattern>
</servlet-mapping>
  • 配置多个映射
<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/shine01</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/shine02</url-pattern>
</servlet-mapping>

3.3 、ServletContext

ServletContext是在服务器范围存在,服务器不关闭,数据一致存在。

web容器在启动时候,他会为每个web程序都创建一个对应的ServletContext对象,他代表了当前web应用:

  • 共享数据

    • 在这个Servlet中保存的数据,在另外一个Servlet中可以拿到

    • String name = "阳光就在天上";
      ServletContext context = this.getServletContext();
      context.setAttribute("name",name);
      
    • resp.setContentType("text/http");
      resp.setCharacterEncoding("utf-8");
      ServletContext context = this.getServletContext();
      String name = (String)context.getAttribute("name");
      resp.getWriter().print(name);
      
  • 获取初始化参数

    • 可以获得xml配置文件中配置的参数

    • <context-param>
          <param-name>url</param-name>
          <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
      </context-param>
      
    • ServletContext context = this.getServletContext();
      String url = context.getInitParameter("url");
      resp.getWriter().print(url);
      
  • 请求转发

    • 转发路径不会改变

    • ServletContext context = this.getServletContext();
      context.getRequestDispatcher("/gp").forward(req,resp);
      
  • 读取资源文件

    • InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
      Properties prop= new Properties();
      prop.load(stream);
      String username = prop.getProperty("username");
      String password = prop.getProperty("password");
      resp.getWriter().print(username+password);
      

资源导出问题解决:

<build>
   <resources>
       <resource>
           <directory>src/main/java</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
       <resource>
           <directory>src/main/resources</directory>
           <includes>
               <include>**/*.properties</include>
               <include>**/*.xml</include>
           </includes>
           <filtering>false</filtering>
       </resource>
   </resources>
</build>

3.4、HttpServletRequest

web服务器接收客户端请求,创建代表请求的HttpServletRequest对象

  1. 获取前端传递的参数
String username = req.getParameter("username");
String password = req.getParameter("password");

String[] hobbies = req.getParameterValues("hobby");
  1. 请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);

3.5、HttpServletResponse

负责向浏览器发送数据的方法

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;  //写中文,造成字符串损坏或丢失

负责向浏览器发送响应头

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentType(String var1);

常见应用:

  1. 向浏览器输出信息
  2. 下载文件
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取下载文件的路径
        String realPath = this.getServletContext().getRealPath("/1.png");
        System.out.println("文件下载路径"+realPath);
        //2.获取下载的文件名
        //直接获取最后一个\后面的下一位
        String filename = realPath.substring(realPath.lastIndexOf("\\")+1);
        //3.让浏览器支持下载所需要的东西
        resp.setHeader("Content-Disposition","attachment;filename="+filename);
        //4.获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
        //5.创建缓冲区
        int len=0;
        byte[] buffer = new byte[1024];
        //6.获得OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
        //7.将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区数据写至客户端
        while ((len=in.read(buffer))!=-1){
            out.write(buffer,0,len);
        }
        in.close();
        out.close();
    }
  1. 验证码实现
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //设置浏览器三秒刷新一次
    resp.setHeader("refresh","3");
    //在内存中创建图片
    BufferedImage image = new BufferedImage(80,20, BufferedImage.TYPE_INT_RGB);
    //得到图片
    Graphics2D graphics = (Graphics2D)image.getGraphics();//笔
    //设置图片背景颜色
    graphics.setColor(Color.WHITE);
    graphics.fillRect(0,0,80,20);
    //给图片写数据
    graphics.setColor(Color.BLUE);
    //设置字体
    graphics.setFont(new Font("null",Font.BOLD,20));
    graphics.drawString(makeNum(),0,20);

    //告诉浏览器这个请求用图片方式打开
    resp.setContentType("image/jpeg");
    //网站存在缓存,取消浏览器缓存
    resp.setDateHeader("expires",-1);
    resp.setHeader("Cache-Control","no-cache");
    resp.setHeader("Pragma","no-cache");

    //将图片写给浏览器
    ImageIO.write(image,"jpg",resp.getOutputStream());

}

//生成随机数
private String makeNum(){
    Random random = new Random();
    String num = random.nextInt(9999999) + "";
    //将随机数一直保持7位,不够后面填充0
    StringBuffer buffer = new StringBuffer();
    for (int i = 0; i < 7-num.length(); i++) {
        buffer.append(0);
    }
    num = buffer.toString() + num;
    return num;
}
  1. 实现重定向
/*
resp.setHeader("Location","/r/img");
resp.setStatus(302);
*/
resp.sendRedirect("/r/img");

面试题:重定向和转发的区别?

相同点:

  • 都会实现页面跳转

不同点:

  • 请求转发,url地址不会发生变化
  • 重定向,不会发生变化

4、Cookie、Session

保存会话的两种技术Cookie、Session

4.1、Cookie

req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");

PrintWriter out = resp.getWriter();

Cookie[] cookies = req.getCookies();

if (cookies != null){

    out.write("上次访问时间为:");

    for (int i = 0; i < cookies.length; i++) {
        Cookie cookie = cookies[i];
        //获取cookie的名字
        if (cookie.getName().equals("time")){
            //获取cookie中的值
            long l = Long.parseLong(cookie.getValue());
            Date date = new Date(l);
            //下面进行编码,这里输出就需要解码
            //out.write(URLDecoder.decode(cookie.getValue(),"utf-8"));
            out.write(date.toLocaleString());
        }

    }

}else {
    out.write("这是你第一次访问");
}
Cookie cookie = new Cookie("time", System.currentTimeMillis()+"");
//若是中文可以利用URLEncoder.encode进行编码
//cookie = new Cookie("name", URLEncoder.encode("阳光就在天上","utf-8"));
//设置cookie有效期
cookie.setMaxAge(24*60*60);
//服务器给客户端响应一个cookie
resp.addCookie(cookie);

cookie:一般会保存在本地目录下appdata;

一个cookie只能保存一个信息,

一个web站点可以给浏览器发送多个cookie,

浏览器上限为300个cookie,

每个站点最多存放20个cookie

cookie大小限制为4kb;

4.2、Session

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,不关闭浏览器Session就一直存在
  • 保存用户信息
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");

resp.setContentType("text/html;charset=utf-8");

//得到Session
HttpSession session = req.getSession();
//给Session中存放东西
session.setAttribute("name",new Person("阳光就在天上",1));

//获取Session的ID
String sessionId = session.getId();

if (session.isNew()){
    resp.getWriter().write("session创建成功");
}else {
    resp.getWriter().write("session已经在服务器中存在,他的id是:" + sessionId);
}

会话自动过期,xml配置:

<!--设置Session默认的失效时间-->
<session-config>
    <!--十五分钟Session自动失效-->
    <session-timeout>15</session-timeout>
</session-config>

4.3、Session和Cookie区别

  • Cookie是将用户的数据写给用户的浏览器,浏览器保存
  • Session是把用户的数据写到用户独占Session中。服务器端保存
  • Session对象由服务器创建

5、JSP

5.1、JSP原理

浏览器向服务器发送请求,无论访问什么资源,都是在访问Servlet,

JSP最终会被转换成一个Java类

JSP本质上就是一个Servlet

//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//JSPService
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)

内置对象

    final javax.servlet.jsp.PageContext pageContext;	//页面上下文
    javax.servlet.http.HttpSession session = null;		//session
    final javax.servlet.ServletContext application;	//application
    final javax.servlet.ServletConfig config;	//config
    javax.servlet.jsp.JspWriter out = null;		//out
    final java.lang.Object page = this;			//page当前页面
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;

5.2、JSP基础语法

JSP表达式

<%=变量或者表达式%>

<%= new java.util.Date()%>

JSP脚本片段

<%
	int sum = 2;
	out.println("<h1>Sum="+sum+"</h1>");
%>

<%
	for(int i = 0; i<5;i++){
%>
<h1>Hello,world <%=i%> </h1>

<%
	}
%>

JSP声明(全局声明)

<%!
    static{
    	System.out.pringln("阳光就在天上");
	}
    
	private int globalVar = 0;    
%>

JSP声明:会被编译到JSP生成JAVA的类中,其他的,就会被生成到_jspService方法中;

JSP注释,不会在客户端显示,HTML注释会显示;

5.3、JSP指令

<%--这个标签在底层会将两个页面合为一个--%>
<%@include ...%>


<%--这个标签会拼接页面--%>
<jsp:include ...>

5.4、9大内置对象

  • PageContext
  • Request
  • Response
  • Session
  • Application (ServletContext)
  • config(ServletConfig)
  • out
  • page
  • exception
<%
    pageContext.setAttribute("name1","阳光1");//保存的数据只在一个页面有效
    request.setAttribute("name2","阳光2");//保存的数据只在一次请求中有效,请求转发会携带数据
    session.setAttribute("name3","阳光3");//保存的数据只在一次会话中有效,打开浏览器到关闭浏览器
    application.setAttribute("name4","阳光4");//保存的数据只在服务器中有效,从服务器开启到关闭
%>

<%
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");

    pageContext.forward("/pageDemo02.jsp");
%>
    
    
<%--使用EL表达式输出--%>
<h1>取出的值为</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>
<h3><%=name5%></h3>

从底层到高层(作用域):page–>request–>session–>application(双亲委派机制)

5.5、JSP标签、JSTL标签、EL表达式

EL表达式:

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象

JSP标签:

<jsp:include page="jsptag02.jsp"/>
<%--jsp标签--%>
<jsp:forward page="jsptag02.jsp">
    <jsp:param name="name" value="阳光就在天上"/>
    <jsp:param name="age" value="18"/>
</jsp:forward>

JSTL标签库:

  • 核心标签
<%--引入核心标签库--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:out></c:out>
<c:when></c:when>
<c:foreach></c:foreach>
<form action="coreif01.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登陆">

</form>
<%--判断提交的用户名是否是管理员--%>
<c:if test="${param.username=='admin'}" var="isadmin">
<c:out value="欢迎"></c:out>
</c:if>
<c:out value="${isadmin}"></c:out>
<%--定义变量--%>
<c:set var="score" value="12"/>

<c:choose>
    <c:when test="${score>=90}">
        成绩优秀
    </c:when>
    <c:when test="${score>=80}">
        成绩良好
    </c:when>
    <c:when test="${score<=60}">
        成绩差
    </c:when>
</c:choose>
<%
ArrayList<String> people = new ArrayList<String>();
people.add(0,"1");
people.add(1,"2");
people.add(2,"3");
people.add(3,"4");
people.add(4,"5");
people.add(5,"6");
request.setAttribute("list",people);
%>

<c:forEach var="people" items="${list}">
    <c:out value="${people}"/>
    <br>
</c:forEach>

在Tomcat中也需要导入jstl的包,否则会报:jstl解析错误

  • 格式化标签
  • SQL标签
  • XML标签

6、JavaBean

实体类:

  • 必须要有无参构造
  • 属性必须私有化
  • 必须有对应get/set方法

一般用来和数据库字段做映射 ORM(对象关系映射);

<%
//    People people = new People();
//    people.setAddress("大同");
//    people.setAge(18);
//    people.setId(3);
//    people.setName("sun");

%>

<%--等价于上面--%>
<jsp:useBean id="people" class="com.xiong.pojo.People" scope="page"/>

<jsp:setProperty name="people" property="address" value="大同"/>
<jsp:setProperty name="people" property="id" value="3"/>
<jsp:setProperty name="people" property="age" value="18"/>
<jsp:setProperty name="people" property="name" value="sun"/>

<%--<%=people.getAddress()%>--%>
姓名:<jsp:getProperty name="people" property="name"/>
ID:<jsp:getProperty name="people" property="id"/>
年龄:<jsp:getProperty name="people" property="age"/>
地址:<jsp:getProperty name="people" property="address"/>

7、MVC三层架构

  • 控制器:Controller(servlet)
    • 接收用户的请求(request、Session)
    • 交给业务层处理对应请求
    • 重定向或者转发
  • 视图层:View(JSP)
    • 展示数据
    • 提供连接发起Servlet请求
  • Model:
    • 业务处理:业务逻辑(Service)
    • 数据持久层:CRUD(Dao)

Servlet专注于处理请求,以及控制视图跳转

JSP专注于显示数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-23HI6QWS-1654347700569)(C:\Users\阳光就在天上\Desktop\flag\MVC三层架构.png)]

8、过滤器(Filter)

public class CharacterEncodingFilter implements Filter {

    //web服务器启动就初始化
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");

        System.out.println("CharacterEncodingFilter执行前");
        //让请求继续执行,若不写程序便停止
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("CharacterEncodingFilter执行后");
    }

    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>com.xiong.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

9、监听器(listener)

在线人数监听,通过session监听

public class OnlineCountListener implements HttpSessionListener {
    //一旦创建session就会触发这个事件
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");

        System.out.println(httpSessionEvent.getSession().getId());
        if (onlineCount==null){
            onlineCount = new Integer(1);
        }else {
            //装箱拆箱
            int count = onlineCount.intValue();
            onlineCount = new Integer(count+1);
        }

        servletContext.setAttribute("OnlineCount",onlineCount);

    }

    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");

        if (onlineCount==null){
            onlineCount = new Integer(0);
        }else {
            int count = onlineCount.intValue();
            onlineCount = new Integer(count-1);
        }

        servletContext.setAttribute("OnlineCount",onlineCount);

    }
}

面试题:

System.exit(0)和System.exit(1)的区别:

System.exit(0)是将你的整个虚拟机里的内容都停掉了 ,而dispose()只是关闭这个窗口,但是并没有停止整个application exit() 。无论如何,内存都释放了!也就是说连JVM都关闭了,内存里根本不可能还有什么东西System.exit(0)是正常退出程序,而System.exit(1)或者说非0表示非正常退出程序System.exit(status)不管status为何值都会退出程序。和return 相比有以下不同点:return是回到上一层,而System.exit(status)是回到最上层。

10、文件上传

public class FileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //判断上传文件的表单(普通表单还是带文件的表单)
        if (!ServletFileUpload.isMultipartContent(req)){
            return;//终止方法运行,说明是一个普通表单
        }

        //创建上传文件的保存路径,建议保存再WEB-INF路径下,安全,用户无法直接访问上传的文件
        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(uploadPath);
        if (!uploadFile.exists()){
            uploadFile.mkdirs();//若不存在则创建这个目录
        }

        //缓存(临时文件)
        //临时路劲,假如文件超过了预期的大小,我们就将其放再一个临时文件中,过几天自动删除,或者提醒用户转存为永久
        String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
        File tmpFile = new File(tmpPath);
        if (!tmpFile.exists()){
            tmpFile.mkdirs();//若不存在则创建这个临时目录
        }

        //处理上传文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,解析流,很麻烦
        //但是我们建议使用Apache的文件上传组件来实现,common-fileupload,

        //1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制
        DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);

        //2.获取ServletFileUpload
        ServletFileUpload upload =getServletFileUpload(factory);

        //3.处理上传文件
        try {
            String msg = uploadParseRequest(upload,req,uploadPath);

            //servlet请求转发
            req.setAttribute("msg",msg);
            req.getRequestDispatcher("info.jsp").forward(req,resp);

        } catch (FileUploadException e) {
            e.printStackTrace();
        }



    }


    public static DiskFileItemFactory getDiskFileItemFactory(File tmpFile) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //创建这个工厂设置一个缓冲区,当文件大于这个缓冲区的时候,将他放入临时文件中
        factory.setSizeThreshold(1024*1024);//大小为1M
        factory.setRepository(tmpFile);

        return factory;
    }

    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload upload = new ServletFileUpload(factory);
        //监听文件的上传进度
        upload.setProgressListener(new ProgressListener() {
            public void update(long l, long l1, int i) {
                System.out.println("总大小:"+ l1 + "已上传" + l);
            }
        });
        //处理乱码问题
        upload.setHeaderEncoding("UTF-8");
        //设置单个文件的最大值
        upload.setFileSizeMax(1024*1024*10);
        //设置总共能够上传文件的大小
        upload.setSizeMax(1024*1024*10);

        return upload;
    }

    public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest req, String uploadPath) throws IOException, FileUploadException {
        String msg = "";

        //将前端请求解析,封装成一个FileItem对象
        //通过upload对象解析请求进行封装
        List<FileItem> fileItems=upload.parseRequest(req);

        for (FileItem fileItem:fileItems){
            if (fileItem.isFormField()){ //判断上传文件的表单(普通表单还是带文件的表单)判断里面的每一项
                //getFiledName指的是前端表单控件的name
                String name = fileItem.getFieldName();
                String value = fileItem.getString("UTF-8");//处理乱码
                System.out.println(name + ":" + value);
            }else {//判断为是上传文件

                //===================处理文件=======================
                //拿到文件名字
                String uploadFileName = fileItem.getName();
                System.out.println("上传文件的名字是:"+uploadFileName);

                if (uploadFileName.trim().equals("")||uploadFileName==null){
                    continue;//文件名不合法直接判断下一个
                }

                //获取上传的文件名 /images/girl/2.png
                String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                //获得文件的后缀名
                String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                /*
                    如果文件后缀名不是我们所需要的就直接return,不处理,告诉用户文件类型错误
                 */
                System.out.println("文件信息[文件名" + fileName + "文件类型" + fileExtName + "]");

                //可以使用UUID(唯一识别的通用码),保证文件名唯一
                //UUID.randomUUID(),随机生成一个唯一识别的通用码
                String uuidPath = UUID.randomUUID().toString();

                //=====================文件存放地址=======================
                //文件真实存在路径 realPath
                String realPath = uploadPath+"/"+uuidPath;
                //给每一个文件创建一个对应的文件夹
                File realPathFile = new File(realPath);
                if (!realPathFile.exists()){
                    realPathFile.mkdirs();
                }

                //=====================文件传输================
                //获得文件上传的流
                InputStream inputStream = fileItem.getInputStream();

                //创建一个文件输出流
                //realPath = 真实的文件夹
                //差了一个文件;加上输出文件的名字+"/"uuidFileName
                FileOutputStream fos = new FileOutputStream(realPath+"/"+fileName);

                //创建一个缓冲区
                byte[] buffer = new byte[1024*1024];

                //判断文件是否读取完毕
                int len = 0;
                while ((len=inputStream.read(buffer))>0){
                    fos.write(buffer,0,len);
                }
                //关闭流
                fos.close();
                inputStream.close();

                msg = "文件上传成功!";
                fileItem.delete();//上传成功,清除临时文件

            }
        }
        return msg;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值