JavaWeb复习笔记(学自哔哩哔哩狂神)
JavaWeb1.Servlet1.1.Servlet原理servlet是由web服务器调用的,web服务器在收到浏览器请求之后,会:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZvdHwaUh-1592392021338)(F:\Javaweb\servlet执行过程.png)]1.2.Mapping问题1.一个servlet可以指定一个路径<servl
JavaWeb
1.Servlet
1.1.Servlet原理
servlet是由web服务器调用的,web服务器在收到浏览器请求之后,会:

1.2.Mapping问题
1.一个servlet可以指定一个路径
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/hello</url-pattern>
</servlet-mapping>
2.一个servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/hello3</url-pattern>
</servlet-mapping>
3.一个servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
4.默认请求路径
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5…指定一些后缀或者前缀等,*前面不能加项目映射路径
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>*.lcy</url-pattern>
</servlet-mapping>
6.优先级问题
指定了固有的映射路径优先级最高,如果找不到会走默认的处理请求:
<!--404-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.lcy.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
1.3.ServletContext
web容器在启动的时候,会为每个web程序创建一个对应的ServletContext对象,它代表了当前的web应用。
1.共享数据
我们在这个Servlet中保存的数据,可以在另外一个servlet中拿到。

public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter(); 初始化参数
// this.getServletConfig(); Servlet配置
// this.getServletContext(); Servlet上下文
ServletContext context = this.getServletContext();
String name ="平安"; //数据
context.setAttribute("username",name); //将一个数据保存在ServletContext中 键值
}
}
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext c = this.getServletContext();
String username = (String) c.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
<!--注册servlet -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.lcy.HelloServlet</servlet-class>
</servlet>
<!--servlet请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--注册servlet -->
<servlet>
<servlet-name>get</servlet-name>
<servlet-class>com.lcy.GetServlet</servlet-class>
</servlet>
<!--servlet请求路径-->
<servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
2.获取初始化参数
<!--配置web应用初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/db_spring</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.getWriter().print(url);
}
3.请求转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了demo04");
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/demo"); //转发的请求路径
requestDispatcher.forward(req,resp); //调用forward实现请求转发
}

4.读取资源文件
Properties
1.在Java目录下创建properties
2.在resources目录下创建properties
发现:被打包到了同一个路径下:classes,俗称:classpath
思路:需要一个文件流
username=root
pwd=root
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String name = prop.getProperty("username");
String pwd = prop.getProperty("pwd");
resp.getWriter().print(name+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletRes=
ponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
访问测试即可;
1.4.HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的HttpServletResponse:
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
响应状态码
int SC_OK = 200; //请求响应成功
int SC_MULTIPLE_CHOICES = 300; //请求重定向
int SC_NOT_FOUND = 404; //找不到资源
int SC_INTERNAL_SERVER_ERROR = 500; //网关错误
2.下载文件
1.向浏览器输出信息
2.下载文件
1.获取下载文件的路径
2.下载的文件名是啥?
3.想办法让浏览器支持下载我们需要的东西
4.获取下载文件的输入流
5.创建缓冲区
6.获取OutputStream对象
7.将FileOutputStream流写入到buffer缓冲区中
8.使用OutputStream将缓冲区的数据输出到客户端!
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取下载文件的路径
String realPath = "E:\\java-web\\response\\target\\classes\\1.下载.jpg";
System.out.println("路径:"+realPath);
//2.下载的文件名是啥
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//3.设置想办法让浏览器能够支持下载我们需要的东西,中文文件名URLEncoder.encode编码
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"utf-8"));
//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))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
3.验证码功能
验证码怎么来的?
-
前端实现
-
后端实现,需要用到Java的图片类,生产一个图片
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //让浏览器2秒自动刷新一次 resp.setHeader("refresh","2"); //在内存中创建一个图片 BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); //得到图片 Graphics2D g = (Graphics2D) image.getGraphics(); //设置图片的背景颜色 g.setColor(Color.white); g.fillRect(0,0,80,20); //给图片写数据 g.setColor(Color.blue); g.setFont(new Font(null,Font.BOLD,20)); g.drawString(makeNum(),0,20); //告诉浏览器这个请求用图片的方式打开 resp.setContentType("image/png"); //网站存在缓存:不然浏览器缓存 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)+""; StringBuffer sb = new StringBuffer(); for (int j = 0; j < 7-num.length(); j++) { sb.append("0"); } num = sb.toString()+num; return num; }4.实现重定向

B一个web资源收到客户端请求,B会通知A客户端去访问另外一个web资源,这个过程重定向
常见场景:
* 用户登陆
```Java
void sendRedirect(String var1) throws IOException;
```
测试:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
*resp.setHeader("Location","/response/img");
* resp.setStatus(302);
*/
resp.sendRedirect("/response/img"); //重定向
}
面试题:重定向和转发的区别
相同点:
* 页面会实现跳转
不同点:
-
请求转发时,url不会发生变化
-
重定向的时候,url地址栏会发生变化
测试:重定向
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //处理请求 String name = req.getParameter("username"); String pwd = req.getParameter("password"); System.out.println(name+":"+pwd); //重定向的时候一定要注意路径问题,否则404 resp.sendRedirect("/response/index2.jsp"); }<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>登陆成功</h1> </body> </html><html> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <body> <h2>Hello World!</h2> <%--这里提交的路径,需要寻找到项目的路径--%> <%--${pageContext.request.contextPath} 代表当前的项目--%> <form action="${pageContext.request.contextPath}/login" method="get"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit"> </form> </body> </html>
1.5.HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
1.获取前端传递的参数,并且请求转发
String getParameter(String var1);
Enumeration<String> getParameterNames(); //不常用
String[] getParameterValues(String var1);
Map<String, String[]> getParameterMap(); //不常用
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println("=========================================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbies));
System.out.println("============================================");
System.out.println(req.getContextPath());
//通过请求转发
//这里的/代表当前的web项目
req.getRequestDispatcher(req.getContextPath()+"/login.jsp").forward(req,resp);
}
重定向和转发的区别:
相同点:
* 页面都会实现跳转
不同点:
-
请求转发的时候,url不会产生变化,307
-
重定向的时候,url地址栏会发生变化,302
2.session cookie
2.1 会话
**会话:**用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器。这个过程为 会话
**有状态会话:**一个同学来过教室,下次再来的时候,我们会知道这个同学曾经来过
例子:你怎么证明你是清华的学生?
你 清华
1.发票 清华给你的发票
2.学校登记 清华标记你来过了
一个网站证明证明你来过?
客户端 服务端
1.服务端给客户端一个信件,客户端下次访问的时候带上信件就ok; cookie
2.服务器登记你来过了,下次你来的时候我匹配你; session
2.2 保存会话的两种技术
cookie
客户端技术(响应,请求)
session
服务器技术,利用这个技术,可以保存用户的会话信息?我们可以把信息或者数据放在session中。
常见应用:网站登陆后,下次不用再登陆了。第二次直接上去了。
2.3 Cookie

Cookie[] cookies = req.getCookies(); //从请求中获取cookie
cookie.getName(); //获取cookie的key
cookie.getValue(); //获取cookie的值
cookie.setMaxAge(24*60*60); //设置cookie的有效期
Cookie cookie = new Cookie("time",System.currentTimeMillis()+"");//创建一cookie
resp.addCookie(cookie); //响应cookie给客户端
删除Cookie
不设置有效期,关闭浏览器,自动失效
设置有效期时间为0
编码解码
URLEncoder.encode("平安","utf-8");
URLDecoder.decode(cookie.getValue(), "utf-8");
2.4 Session(重点)

session和coolie的区别:
-
Cookie是把用户的数据写给用户的浏览器,浏览器保存(客户端可以保存多个)
-
Session把用户的数据写到用户独占的Session中,在服务器端保存(保存重要的东西,减少服务器的资源)
-
Session对象由服务器创建
使用场景:
- 保存一个登陆用户的信息
- 购物车信息
- 在整个网站中,经常使用的数据,保存在session中;(不用去new新的对象,取就可以了,方便)
使用session
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
//得到session
HttpSession session = req.getSession();
//给session中存东西
session.setAttribute("name", new Stu(3,"陆沉"));
//获取session的Id
String id = session.getId();
//判断是不是新创建的session
if (session.isNew()){
resp.getWriter().write("session创建成功,Id为"+id);
}else {
resp.getWriter().write("已经存在,id"+id);
}
//session在创建的时候做了什么事情
// Cookie jsessionid = new Cookie("JSESSIONID", id);
// resp.addCookie(jsessionid);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
//得到session
HttpSession session = req.getSession();
//获取
Stu name = (Stu) session.getAttribute("name");
System.out.println(name);
resp.getWriter().write(String.valueOf(name));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
//得到session
HttpSession session = req.getSession();
//移除name
session.removeAttribute("name");
//手动注销session
session.invalidate();
}
会话自动过期: web.xml配置
<!--设置session的默认失效时间-->
<session-config>
<!--分钟为单位,自动失效-->
<session-timeout>1440</session-timeout>
</session-config>
3.JSP
3.1 什么是jsp
Java Server Page:Java服务器页面,和servlet一样,用于动态web技术
最大的特点:
-
写jsp就像在写HTML
-
区别
-
HTML只给用户提供静态的数据
-
JSP页面可以嵌入Java代码,为用户提供动态数据
-
3.2 JSP原理
思路:JSP到底怎么执行的:


浏览器向服务器发送请求,不管访问什么资源,其实都是在访问servlet!
jsp最后也会被转换为Java类
JSP本质上就是一个Servlet
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//JSPService
public void _jspService(HttpServletRequest request,HttpServletResponse response)
_jspService干了什么
1.判断是什么请求
2.内置一些对象
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
HttpServletRequest request //请求
HttpServletResponse response //响应
3.输出页面前增加的代码
response.setContentType("text/html"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
4.以上这些对象我们可以直接在JSP页面中使用
jsp执行过程

在jsp页面中:
只要是Java代码就会原封不动的输出;
out.print(name);
HTML代码就会被转换为以下格式输出到前端
out.write("<html>\r\n");
3.3 JSP基础语法
JSP声明会被编译到_jspService方法之外,其他的被生成到_jspService方法中
<%=变量或者表达式%> //原来将程序的输出,输出到客户端
<%Java代码%> //jsp脚本片段
<%! %> //jsp声明
JSP指令:破解语法
<jsp:include page="work.jsp"/> //更灵活
<%@include file="index.jsp"%>
3.4 九大内置对象
-
PageContext 存东西
-
Request 存东西
-
Response 响应
-
Session 存东西
-
Application (ServletContext)存东西
-
Config (ServletConfig)
-
out
-
page
-
exception
<!--四个可以存储东西的内置对象 --> //存 pageContext.setAttribute("name1","陈平安1",3); //保存的数据只在一个页面有效 request.setAttribute("name2","陈平安2"); //保存的数据只在一次请求中有效,请求转发会携带资格数据 session.setAttribute("name3","陈平安3"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器 application.setAttribute("name4","陈平安4"); //保存的数据值在服务器中有效,从打开服务器到关闭服务器
request:客户端向服务器,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的
session:客户端向服务端发送请求,产生的数据,用户用完一会还会用,比如:购物车
application:客户端向服务端发送请求,产生的数据,一个用户用完了,其他用户可能还会使用,比 如聊天数据
3.5 Filter过滤器
Filter:过滤器,用来过滤网站的数据
- 处理中文乱码
- 登陆验证…

过滤器的使用
-
导包
servlet下的Filter包
-
编写过滤器
@Override
//初始化,和web服务器一起启动,随时等待过滤器对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("已经初始化");
}
@Override
/**
* chain
* 1.过滤中的所有代码,在过滤特定请求的时候都会执行
* 2.必须要让过滤器继续执行 chain.doFilter(req,resp);
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println("执行前");
chain.doFilter(req,resp); //如果不写,程序到此拦截停止
System.out.println("执行后");
}
@Override
//web服务器关闭时一同销毁
public void destroy() {
System.out.println("已经销毁");
}
- 在web.xml中配置Filter
<servlet>
<servlet-name>show</servlet-name>
<servlet-class>servlet.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>show</servlet-name>
<url-pattern>/servlet/show</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>show</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
<filter>
<filter-name>filter1</filter-name>
<filter-class>filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<!--只要是/servlet的任何请求,会经过这个过滤器 -->
<url-pattern>/servlet/*</url-pattern>
<!--<url-pattern>/*</url-pattern>全过滤-->
</filter-mapping>
登陆拦截实现
- 用户登陆之后,向Session中放入用户的数据
- 进入主页的时候判断用户是否已经登陆
- 登陆失败或者输入失败
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取前端请求的参数
String username = req.getParameter("username");
if (username.equals("admin")){
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
resp.sendRedirect("/sys/result.jsp");
}else {
resp.sendRedirect("/error.jsp");
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//转换成HttpServletRequest HttpServletResponse
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (request.getSession().getAttribute(Constant.USER_SESSION) == null) {
response.sendRedirect("/error.jsp");
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
if (user_session != null) {
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect("/login.jsp");
}else {
resp.sendRedirect("/login.jsp");
}
}
3.3 JDBC事务
要么都成功,要么都失败
ACID原则:保证数据的安全
-
开启事务
-
事务提交
-
事务回滚
-
关闭事务
4.文件上传
4.1 文件上传的调优
- 保证服务器安全,上传文件放在外界无法直接访问的目录下,WEB-INF
- 防止文件覆盖,要为上传文件产生一个唯一的文件名(时间戳,-uuid)
- 限制上传文件的最大值
- 限制上传文件的类型,收到上传文件名,判断后缀名是否合法
代码:
servlet代码
package com.lcy.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* @ClassName: UploadHandleServlet
* @Description: TODO(这里用一句话描述这个类的作用)
* @author: 孤傲苍狼
* @date: 2015-1-3 下午11:35:50
*
*/
public class UploadHandleServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//上传时生成的临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
//创建临时目录
tmpFile.mkdir();
}
//消息提示
String message = "";
try{
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
//设置上传时生成的临时文件的保存目录
factory.setRepository(tmpFile);
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
/**
* 文件大小为:14608,当前已处理:4096
文件大小为:14608,当前已处理:7367
文件大小为:14608,当前已处理:11419
文件大小为:14608,当前已处理:14608
*/
}
});
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(1024*1024*10);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024*1024*10);
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
//value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
}else{//如果fileitem中封装的是上传文件
//得到上传的文件名称,
String filename = item.getName();
System.out.println(filename);
if(filename==null || filename.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename.substring(filename.lastIndexOf("\\")+1);
//得到上传文件的扩展名
String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
System.out.println("上传的文件的扩展名是:"+fileExtName);
//获取item中的上传文件的输入流
InputStream in = item.getInputStream();
//得到文件保存的名称
String saveFilename = makeFileName(filename);
//得到文件的保存目录
String realSavePath = makePath(saveFilename, savePath);
//创建一个文件输出流
FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int len = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((len=in.read(buffer))>0){
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
out.write(buffer, 0, len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//删除处理文件上传时生成的临时文件
//item.delete();
message = "文件上传成功!";
}
}
}catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "单个文件超出最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}catch (FileUploadBase.SizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}catch (Exception e) {
message= "文件上传失败!";
e.printStackTrace();
}
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
/**
* @Method: makeFileName
* @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
* @Anthor:孤傲苍狼
* @param filename 文件的原始名称
* @return uuid+"_"+文件的原始名称
*/
private String makeFileName(String filename){ //2.jpg
//为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
return UUID.randomUUID().toString() + "_" + filename;
}
/**
* 为防止一个目录下面出现太多文件,要使用hash算法打散存储
* @Method: makePath
* @Description:
* @Anthor:孤傲苍狼
*
* @param filename 文件名,要根据文件名生成存储目录
* @param savePath 文件存储路径
* @return 新的存储目录
*/
private String makePath(String filename,String savePath){
//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
int hashcode = filename.hashCode();
int dir1 = hashcode&0xf; //0--15
int dir2 = (hashcode&0xf0)>>4; //0-15
//构造新的保存目录
String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5
//File既可以代表文件也可以代表目录
File file = new File(dir);
//如果目录不存在
if(!file.exists()){
//创建目录
file.mkdirs();
}
return dir;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
jsp页面
<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
上传文件1:<input type="file" name="file1"><br/>
上传文件2:<input type="file" name="file2"><br/>
<input type="submit" value="提交">
</form>
web.xml配置
<servlet>
<servlet-name>UploadHandleServlet</servlet-name>
<servlet-class>com.lcy.servlet.UploadHandleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadHandleServlet</servlet-name>
<url-pattern>/servlet/UploadHandleServlet</url-pattern>
</servlet-mapping>
javaWeb发送邮件
servlet
package com.lcy.servlet;
import com.lcy.bean.User;
import com.lcy.util.SendEmail;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//接收用户请求,封装成对象
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
System.out.println(email);
User user = new User(username, password, email);
//用户注册成功之后,给用户发送一封邮件
//我们使用线程来专门发送邮件,防止出现耗时和网站注册人数过多的情况
SendEmail send = new SendEmail(user);
//启动线程,线程启动之后会执行run方法来发送邮件
send.start();
//注册用户
req.setAttribute("message","注册成功,请注意查收邮件");
req.getRequestDispatcher("info.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
util封装邮件发送异步处理方法
package com.lcy.util;
import com.lcy.bean.User;
import com.sun.mail.util.MailSSLSocketFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
import java.util.UUID;
//网站三秒原则:用户体验
//多线程实现用户体验 异步处理
public class SendEmail extends Thread {
//用于给用户发送邮件的邮箱
private String from = "1151788973@qq.com";
//邮箱的用户
private String username = "1151788973@qq.com";
//邮箱的密码
private String password = "utsgwcbpugougfbh";
//发送邮件的服务器地址
private String host = "smtp.qq.com";
private User user;
public SendEmail(User user) {
this.user = user;
}
@Override
public void run() {
try {
Properties prop = new Properties();
prop.setProperty("mail.host", host); //设置qq邮件服务器
prop.setProperty("mail.transport.protocol", "smtp"); //邮件发送协议
prop.setProperty("mail.smtp.auth", "true"); //需要验证用户名密码
//关于qq邮箱,设置ssl加密
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
//1.创建定义整个应用程序所需要的环境信息的session对象
Session session = Session.getDefaultInstance(prop, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//发件人邮件用户名,授权码
return new PasswordAuthentication("1151788973@qq.com", "utsgwcbpugougfbh");
}
});
//开启session的debug模式,可以看到email发送的运行状态
session.setDebug(true);
//2.通过session得到transport对象
Transport ts = session.getTransport();
//3.使用邮箱的用户名和授权码连上邮件服务器
ts.connect(host, username, password);
//4.创建邮件
MimeMessage message = new MimeMessage(session);
//4.1指明邮件的发件人
message.setFrom(new InternetAddress(from));
//4.2指明收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
//4.3邮件主题
message.setSubject("用户注册");
//5.邮件内容
String text = "恭喜您注册成功,您的用户名:"+user.getUsername()+"您的密码:"+user.getPassword()+".请妥善保管";
message.setContent(text,"text/html;charset=UTF-8");
message.saveChanges();
//6.发送邮件
ts.sendMessage(message, message.getAllRecipients());
//7.关闭连接
ts.close();
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
web.xml
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.lcy.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/RegisterServlet.do</url-pattern>
</servlet-mapping>
实体类
private String username;
private String password;
private String email;
jsp页面
<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
邮箱:<input type="text" name="email"><br/>
<input type="submit" value="注册">
</form>
//4.2指明收件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
//4.3邮件主题
message.setSubject("用户注册");
//5.邮件内容
String text = "恭喜您注册成功,您的用户名:"+user.getUsername()+"您的密码:"+user.getPassword()+".请妥善保管";
message.setContent(text,"text/html;charset=UTF-8");
message.saveChanges();
//6.发送邮件
ts.sendMessage(message, message.getAllRecipients());
//7.关闭连接
ts.close();
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
web.xml
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.lcy.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/RegisterServlet.do</url-pattern>
</servlet-mapping>
实体类
private String username;
private String password;
private String email;
jsp页面
<form action="${pageContext.request.contextPath}/RegisterServlet.do" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
邮箱:<input type="text" name="email"><br/>
<input type="submit" value="注册">
</form>
更多推荐



所有评论(0)