目录
1、简介
-
用于动态web
-
Servlet是一个接口
-
编写一个类、实现借口
-
部署到服务器中
-
2、创建一个Servlet项目
2.0 创建一个Maven项目
2.1在Pom.xml安装servlet依赖
在Pom.xml中进行添加依赖
-
javax.servlet-api
-
javax.servlet.jsp-api
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency>
2.2编写Servlet
1.创建一个包
2.实现Servlet接口
有两个默认实现类 HttpServlet 、GenericServlet (可以去看看源码)
我们继承HttpServlet 然后重写DoGet 和 DoPost 方法
public class helloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.println("hello world"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
2.3在Web.xml文件编写Servlet的映射
<web-app> <display-name>Archetype Created Web Application</display-name> <!-- 注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.sakura.helloServlet</servlet-class> </servlet> <!-- Servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
2.4配置Tomcat
转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消
2.5 运行
3、Servlet原理
3.1UML类图
1.抽象类HttpServlet继承抽象类GenericServlet,其有两个比较关键的方法,doGet()和doPost()
2.GenericServlet实现接口Servlet,ServletConfig,Serializable
3.MyServlet(用户自定义Servlet类)继承HttpServlet,重写抽象类HttpServlet的doGet()和doPost()方法
注:任何一个用户自定义Servlet,只需重写抽象类HttpServlet的doPost()和doGet()即可,如上图的MyServlet
3.2Servlet访问URL映射
由于客户端是通过URL地址访问Web服务器中的资源,所以Servlet程序若想被外界访问,必须把Servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用元素<servlet>和元素<servlet-mapping>完成。
<servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。
一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。
在请求http://localhost:8080/servlet2_war/hello的时候会去web.xml 的Servlet-mapping中找
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
找到Servlet-name=hello ,接着在Servlet中找
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.sakura.helloServlet</servlet-class> </servlet>
找到了Servlet -class
4.Servlet-context 对象
4.1新建子工程
-
新建一个模块 WebApp
-
补全结构
创建包
4.2 Servlet-context
note: 在 IDEA中 ctrl + alt + v 可以自动补全变量类型及其取名
web容器在启动时,会为每一个web程序都创建一个对应的Servlet-context对象,代表了当前的Web应用
4.2.1 共享数据
我在这个Servlet中保存的数据 可以在另外一个Servlet应用中获取
整体框架图
4.2.2 源码
// 上传端 public class helloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); String name="Sakura"; servletContext.setAttribute("hello",name); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
//get端 public class getServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); String hello = (String) servletContext.getAttribute("hello"); resp.getWriter().println(hello); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
<!-- web.xml--> <!-- 注册Servlet--> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.sakura.helloServlet</servlet-class> </servlet> <servlet> <servlet-name>getc</servlet-name> <servlet-class>com.sakura.getServlet</servlet-class> </servlet> <!-- Servlet的请求路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>getc</servlet-name> <url-pattern>/getc</url-pattern> </servlet-mapping>
4.2.3 运行结果
我们可以看到 /getc这个页面获取到了/hello的数据
4.2.4 测试 重启tomcat
我们可以看到 由于/hello 没有向Servlet-context发送数据 所以/getc 获取不到这个String对象
4.2.5 ServerletContext 的一些API
ServletContext servletContext = getServletContext(); //1.获取web.xml里面的参数信息 /* <context-param> <param-name>name</param-name> <param-value>sakuara</param-value> </context-param> */ String initParameter = servletContext.getInitParameter("name"); //2.设置上下文属性与获取上下文属性 不同应用中是同一个context servletContext.setAttribute("add","nanjing"); String add = (String) servletContext.getAttribute("add"); //public void removeAttribute(String name);移除一个属性 //把资源当做流获取 //public InputStream getResourceAsStream(String path); //可以用文件IO来实现 //获取重定向 public RequestDispatcher getRequestDispatcher(String path);
4.2.6 Servletconfig & ServletContext
-
每个Servlet一个ServletConfig
-
每个Web应用一个ServletContext
5.下载功能
-
获取下载文件的路径
-
获取下载文件名
-
修改response 头信息 使其支持下载
-
获取文件的输入流
-
创建缓冲区
-
获取响应的输出流
-
把输入流写入输出流
public class DownServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1. 获取下载文件的路径 String respath="/media/yqx/软件/Java/Java_web_Project/Servlet2/src/main/resources/姚谦祥.png"; //2.获取下载的文件名 String fileName=respath.substring(respath.lastIndexOf("/")+1); //3. 修改response 头信息 使文件以下载的形式下载下来; resp.setHeader("content-disposition","attachement;filename="+ URLEncoder.encode(fileName,"UTF-8")); //4.把资源转化成输入流 FileInputStream in=new FileInputStream(respath); //5.获取输出流 ServletOutputStream out=resp.getOutputStream(); //6.创建缓冲区 int len=0; byte[] buffer = new byte[1024]; //7. 输出资源流 while ((len=in.read(buffer))>0){ out.write(buffer,00,len); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
6.绘制验证码
-
生成验证码
-
生成一张图片
-
生成一串随机数
-
把随机数写入图片
-
-
输出验证码
-
设置header不去缓存该图片
-
让浏览器5秒刷新一次
-
把图片写入输出流
-
public class pictureServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 在内存中创建一张图片 BufferedImage image=new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB); Graphics2D g=(Graphics2D)image.getGraphics(); // 绘制图片底色 g.setColor(Color.white); g.drawRect(0,0,80,20); //把生成的随机数写入图片 g.setColor(Color.BLUE); g.drawString(made_random(),20,10); // 输出验证码 //2秒刷新 resp.setHeader("Refresh","2"); //设置头信息内容形式 resp.setContentType("image/jpeg"); //设置头信息缓存控制 - 不缓存 resp.setHeader("Catch-Control","no-catch"); // 把图片写入输出流 ImageIO.write(image, "jpg",resp.getOutputStream()); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } //生成随机数 public static String made_random(){ Random r=new Random(); String num=r.nextInt(9999)+""; StringBuffer buf=new StringBuffer(); for (int i=0;i<4-num.length();i++){ buf.append("0"); } String s=buf.toString()+num; return s; } }
7.页面重定向SentRedirection
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取到提交的表单信息 getParameter String usr = req.getParameter("usr"); String pwd = req.getParameter("pwd"); System.out.println("success!"+usr+":"+pwd); /*重定向等价于如下两行代码 *resp.setStatus(302); //302 重定向 *resp.setHeader("Location","./img"); //重定向的地址 * */ resp.sendRedirect("./img"); }
jsp 页面代码
<form action="./red" method="post"> 用户名:<input type="text" name="usr"“”“”></br> 密码:<input type="password" name="pwd"></br> <input type="submit"> </form>
8.HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器
我们可以拿到request请求的数据信息
req.getParameter(String s); //String req.getParameterValues(String s); //String[]
8.1获取表单信息
//点击登录后调用/lg的方法 <form action="./lg" method="post"> 用户名:<input type="text" name="usr"“”“”></br> 密码:<input type="password" name="pwd"></br> <input type="checkbox" name="like" value="a">a <input type="checkbox" name="like" value="b">b <input type="checkbox" name="like" value="c">c <input type="checkbox" name="like" value="d">d <input type="checkbox" name="like" value="e">e <input type="submit"> </form>
// 用户点击登录 控制台输出用户的登录信息 public class login extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String pwd = req.getParameter("pwd"); String usr = req.getParameter("usr"); String[] like=req.getParameterValues("like"); System.out.println(usr+" "+pwd); System.out.println(Arrays.toString(like)); //登录成功后重定向到其他界面 resp.sendRedirect("./lg.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
控制台会输出用户提交的信息
9.COOKIE
9.1 保存用户上一次访问的时间
-
获取到request的cookie(key,value)
-
遍历这些cookie
-
如果存在cookie的key与本地的key相等,则输出cookie的value
-
更新cookie的值
输出当前时间
Date date=new Date(); System.out.println(“现在的时间是:”+date.toString());
//保存用户上一次访问的时间 //1. 获取到request的cookie(key,value) //2. 遍历这些cookie //3. 如果存在cookie的key与本地的key相等,则输出cookie的value //4. 更新cookie的值 public class COOKIEdemo extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 保存 req.setCharacterEncoding("UTF-8"); // 存在多个cookie Cookie[] cookies = req.getCookies(); if(cookies!=null){ for (Cookie c:cookies) { String cName = c.getName(); if(cName.equals("last_time")){ //输出cookie中的value resp.getOutputStream().println("你上一次访问的时间为:"+c.getValue()); } } } else { resp.getOutputStream().println("这是你第一次访问"); } // 更新cookie Date date=new Date(); Cookie cookie = new Cookie("last_time", date.toString()); resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
可以看到我们现在遇到了一个500服务器错误
经过排查在更新cookie这里
Date date=new Date(); Cookie cookie = new Cookie("last_time", date.toString());
存在一点问题
Cookie cookie = new Cookie("last_time", System.currentTimeMillis()+"");
改成这样就正确了
在这里 对于java获取当前时间的API我们有两种获取方式
-
System.currentTimeMillis()
-
Date date=new Date();
System.currentTimeMillis()产生一个当前的毫秒,这个毫秒其实就是自1970年1月1日0时起的毫秒数
Date()其实就是相当于Date(System.currentTimeMillis());
9.2 cookie的一些参数
setMaxAge(int); //设置cookie的存活时间 单位秒 setDomain(String domain); //设置cookie可见域 setPath(String uri); //通常的cookie只能在一个应用中共享,即一个cookie只能由创建它的应用获得。 //可在同一应用服务器内共享方法:设置cookie.setPath("/App_File/"); //跨域共享cookie的方法:设置cookie.setDomain(".jszx .com");
10.session(重点)
-
服务器会给每个用户创建一个session
-
只要浏览器没有关闭,这个Session就存在
-
用户登录后,整个网站都可以访问
10.1 session的方法
-
实例
1.得到session
HttpSession session = req.getSession();
2.往session中写东西(Key,Value) Value 可以是一个对象
Person sakura = new Person(21, "Sakura"); session.setAttribute("name",sakura);
3.修改session
session.removeAttribute("name");
IDEA快捷键 Alt+Insert 快速构建一个类 包括构造 Setter Getter ToString 等等
10.2 session注销的两种方式
-
直接注销session (类似于用户退出登陆)
session.invalidate();//注销该session
-
在web.xml 配置文件中修改session的存活时间timeout
<session-config> <!-- 15分钟后 session自动失效--> <session-timeout>15</session-timeout> </session-config>
11.JSP
11.1 JSP -- JAVA Server Page
JSP是如何执行的?
-
服务器内部工作
tomcat中有一个work目录
在IDEA的系统文件夹中也有一个tomcat目录!
我们进去发现和tomcat目录下的文件结构基本相同
转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消转存失败重新上传取消
这个是我们的index.jsp转化成的java文件和源文件对比
原JSP的内容如下
我们可以看到这样一个对象HttpJspBase 它就是继承了HttpServlet的
我们分析一下由jsp转化过来的Java文件
public void _jspInit() {//初始化一个JSP } public void _jspDestroy() {//销毁一个JSP } //req 和 resq public void _jspService(HttpServletRequest request, HttpServletResponse response)
final javax.servlet.jsp.PageContext pageContext;//页面上下文 javax.servlet.http.HttpSession session = null; //session final javax.servlet.ServletContext application; //applicationContext final javax.servlet.ServletConfig config; //config 配置文件 javax.servlet.jsp.JspWriter out = null; //out输出 final java.lang.Object page = this; //当前页面. HttpServletRequest request; HttpServletResponse response;
结论!!!JSP本质就是一个Servlet 每当一个页面被访问的时候 就会生成这么一个Java文件
我们可以在JSP的Java代码中直接使用这么几个常量和变量
在Jsp文件中 只要是Java代码就会被原封不动的转化,而HTML代码则会被转化成这样的代码
out.write("<h2>Hello World!</h2>\n");
11.2 JSP项目构建
-
创建一个Web项目方法二
-
先创建一个Maven新的空项目
-
在项目目录右键添加新的框架支持
-
我们可以把这个新建的web文件夹移到src文件下 但是要修改JSP-Project.xml
<webroots> <root url="file://$MODULE_DIR$//src//web" relative="/" /> </webroots>
最终的文件目录关系如下转存失败重新上传取消转存失败重新上传取消
在JSP的依赖中 我们要在pom.xml中新增两个依赖包
<!-- JSTL表达式依赖包 --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> <!-- 标签库依赖包--> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
11.3 JSP基础语法
-
HTML注释
<!-- 实现页面访问计数 -->
-
JSP注释
<%-- 实现页面访问计数 --%>
-
变量的声明
<%! int visit1 = 1; //声明变量visit1,初始值为1 int visit2 = 1; //声明变量visit2,初始值为1 %>
-
表达式的实现 (直接输出变量)
你是本页面第<%= visit1++ %>个访客(JSP表达式实现)<br>
-
JSP Scriptlets实现(通过Java输出变量)
你是本页面第<% out.println(visit2++); %>个访客
11.4 JSP指令
-
page
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.*" %>
-
include (公共页面)
<%@include file="common/header.jsp"%> <%= new java.util.Date()%> <%@include file="common/foot.jsp"%>
-
jsp标签
<jsp:include page="common/header.jsp"></jsp:include> <%= new java.util.Date()%> <jsp:include page="common/foot.jsp"></jsp:include>
尽量用jsp标签 不要用include (虽然两个的实现是一样的)
我们可以分析一下源码有什么不一样
-
这是jsp标签的转化代码
static { _jspx_dependants = new java.util.HashMap<java.lang.String,java.lang.Long>(2); _jspx_dependants.put("/common/header.jsp", Long.valueOf(1582294308000L)); _jspx_dependants.put("/common/foot.jsp", Long.valueOf(1582294308000L)); } ... //调用 org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "common/header.jsp", out, false); ... out.print( new java.util.Date()); ... org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "common/foot.jsp", out, false);
-
这是include的代码
... out.write("<h1>this is header</h1>"); out.write('\n'); out.write(' '); out.write(' '); out.print( new java.util.Date()); ... out.write("<h1>this is foot</h1>\n");
可以看到 include是直接把引用的页面复制到源码中
这样在两个页面中使用同名变量就会报错!!!所以还是使用jsp标签
11.5 自定义错误页面
在web.xml中进行配置
<error-page> <error-code>404</error-code> <location>/error/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/error/500.jsp</location> </error-page>
12.JavaBean
也叫作实体类entity
Javabean有特定的写法
-
必须要有一个无参构造
-
属性必须私有
-
必须有相应的Get、set写法
ORM 对象关系映射
-
表--类
-
字段--属性
-
行记录--对象
13.MVC三层架构
model - view - control转存失败重新上传取消转存失败重新上传取消
View
-
负责页面数据的展示
-
提供用户操作
-
发起Servlet请求
Control (Servlet)
-
接收用户消息
-
提供页面跳转
-
具体业务的逻辑实现交给Service model层
Model
-
业务处理:实现具体的逻辑(service)
-
数据持久层:操作数据库(Dao)
14.Filter
-
过滤信息
-
解决乱码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("你好呀!"); }
可以看到 这里是乱码的 我们需要给response设置编码
resp.setCharacterEncoding("utf-8");//只有这样设置才不会乱码
但是如果每一个页面的每一条消息都这样处理 难免会很繁杂
我们可以新建一个类 实现过滤器接口
import javax.servlet.*;//导包不要导错了 public class FilterServlet implements Filter { //初始化 public void init(FilterConfig filterConfig) throws ServletException { } //过滤 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //在这里设置编码 request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); System.out.println("before"); chain.doFilter(request,response);//让我们的请求继续走因为可能不止一个过滤器 System.out.println("after"); } //销毁 public void destroy() { } }
然后再在web.xml里面配置过滤器
<filter> <filter-name>encode</filter-name> <filter-class>com.sakura.FilterServlet</filter-class> </filter> <filter-mapping> <filter-name>encode</filter-name> <url-pattern>/filter/*</url-pattern> </filter-mapping>
这样所有/filter/下面的页面呢都会以UTF-8进行编码
15.Listen
-
实现监听器接口
-
在web.xml中注册监听器
16.用户登录实例
-
利用Filter和Session验证用户是否已经登录
-
如果没有登录 禁止访问xx页面
-
注销后也不让进入页面
登录界面 login.jsp
就是一个很简单的表单 跳转向/login (是login.java 在web.xml中的映射路径)
<form action="./login" method="post"> <input name="username"> <input type="submit"> </form>
成功登录界面 inner/success.jsp
包括一个注销按钮 跳转向../logout (是logout.java 在web.xml中的映射路径)
<body> <h1>成功登录</h1> <a href="../logout">退出登录</a> </body>
未登录成功的错误页面 error/error.jsp
<body> <h1>您未登录</h1> <a href="../login.jsp">登录</a> </body>
过滤器 logincheck.java
public class logincheck implements Filter { public void init(FilterConfig filterConfig) throws ServletException {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //HttpServletRequest 继承自ServletRequest 可以进行强转化 HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; //获取到请求的Session HttpSession reqSession = req.getSession(); //获取到Session的‘USER’属性 String username = (String) reqSession.getAttribute("USER"); //若username 为null或 不为‘Admin’的时候 跳转向错误页面 if(username==null||!username.equals("Admin")) { //注意错误页面的路径 当前路径为/inner/* 错误页面在同级的/error/下,所以要返回上一级 resp.sendRedirect("../error/error.jsp"); } else { System.out.println("login Success!!!"); } chain.doFilter(request,response); } public void destroy() {} }
登录请求业务实现 Login.java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取到请求参数 String username = req.getParameter("username"); //在这里我们写死了 这里就是验证用户 if(username.equals("Admin")) {//验证成功 //写入到Session中 req.getSession().setAttribute("USER", username); //重定向 resp.sendRedirect("./inner/success.jsp"); } else//验证失败 resp.sendRedirect("./error/error.jsp"); }
注销请求业务实现 Logout.java
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = (String) req.getSession().getAttribute("USER"); if (username!=null){ //我们不去删除这个Session 而是移除“USER”这个属性 req.getSession().removeAttribute("USER"); } //重定向到登录界面 resp.sendRedirect("./login.jsp"); }
17.上传文件 -- Mark
文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。
17.1 前端表单要求
为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器;
对表单中的 enctype 属性做个详细的说明:
-
application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
-
multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
-
text/plain:除了把空格转换为 "+" 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post"> <input type="file" name="file"/> <input type="submit"> </form>
一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。
17.2 导入Jar包
-
方法一 直接在Maven中写入依赖
<!--文件上传--> <!--Maven会自动帮我们导入他的依赖包 commons-io包--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency> <!--servlet-api导入高版本的--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency>
-
方法二 手动导入jar包
在IDEA中可以手动导入Jar包,首先建立一个lib文件夹,把所需要的jar包放入lib文件夹中
方法一:右键文件夹,添加到类库
方法二:右上角项目结构,选择类库 选择指定的文件夹