文章目录

  • 1、文件上传
  • 2、文件下载
  • 3、用户登陆注册时的显示头像
  • 4、注解
    • 与interface的区别
    • 元注解

1、文件上传

  • 文件上传:将客户端的文件,保存到服务器端,比如在用户注册的时候要求用户上传一张图片作为该账号的头像;
  • 对表单限制:

1、提交方式method必须为post ,因为post请求提交的请求体大小不受限制;
2、表单的属性enctype必须为:multipart/form-data
enctype:指表单发送数据的编码方式;

  • application/x-www-form-urlencoded:数据进行URL编码
  • text/plain:纯文本发送
  • multipart/form-data:可以发送二进制数据,专门用于文件上传
  • 对Servlet限制:

1、request.getParameter()方法不能使用了,即使用了也获取的是null
2、使用request.getInputStream()来获取所有消息体数据,然后解析;

  • 解析消息体数据:使用commons-fileupload 组件解析消息体,它是Apache组织为了方便我们解析文件数据提供的第三方jar包;

为什么使用第三方jar包,因为使用request.getInputStream()获得的所有消息体数据,假如表单中还有文本框中的数据,我们应该怎么解析?从什么地方开始是文件的那部分字节数据都是不得而知的;

  • 步骤:

1、导入jar包,注意:还需要导入commons-io.jar

2、创建解析器工厂
3、获取解析器
4、解析request对象,返回List<FileItem> (表单项对象集合)
5、遍历集合,获取每一个表单项,获取数据

  • FileItem对象的方法:
判断是否是普通表单项:isFormField()
获取表单项name名称:getFieldName()
普通表单项的方法:
获取表单项的值:getString(String encoding)
文件表单项的方法:
获取文件名称:getName()
获取文件类型:getContentType()
获取文件大小:getSize()
获取文件关联的输出流:getOutputStream()
将文件数据写入硬盘:write(File file)

后台Java代码:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;@WebServlet(value = "/demoupload")
public class ServletUpLoad extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {try {request.setCharacterEncoding("utf-8");String realPath = request.getServletContext().getRealPath("/upload");File file = new File(realPath);//创建出我们要保存上传文件的文件夹if (!file.exists()) {file.mkdirs();}DiskFileItemFactory df = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(df);List<FileItem> list = upload.parseRequest(request);for (FileItem fileItem : list) {//判断是否为普通的表单项if (fileItem.isFormField()) {//获取键值String name = fileItem.getFieldName();String value = fileItem.getString("utf-8");request.setAttribute("username", value);} else {String name = fileItem.getFieldName();//获取上传来的文件名String fileName = fileItem.getName();fileName = UUID.randomUUID().toString().replace("-", "") + fileName;//保存传上来的文件File file1 = new File(file, fileName);fileItem.write(file1);System.out.println("上传来的文件保存在:" + file1.getAbsolutePath());}}} catch (Exception e) {e.printStackTrace();}}
}

前台JSP代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<form action="${pageContext.servletContext.contextPath}/demoupload" enctype="multipart/form-data" method="post">用户名:<input type="text" placeholder="请输入用户名" name="username" value=""><br>文件名:<input type="file" name="fileName"><br><input type="submit" value="提交">
</form>
</body>
</html>


2、文件下载

  • 文件下载:服务器端保存到客户端,比如我们在网页上下载一张图片保存在本地;
  • 下载方式:

1、超链接直接指向目标资源下载:如果浏览器可以解析目标文件,则直接在浏览器中打开;反之,则弹出下载提示框;

2、通过Servlet实现下载

  • 超链接指向servlet,传递目标资源的标识符。
  • 定义Servlet:
    1.获取文件标识,找到文件对象
    2.创建输入流,关联目标文件
    3.设置响应头:
content-disposition:消息体数据的打开方式
>content-disposition:attachment;filename=xxx
>content-type:类型

3.将输入流数据写入response输出流中;

  • 下载细节:

1、如果文件名是中文,有的浏览器可能会乱码,怎么处理:

if (agent.contains("MSIE")) {// IE浏览器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {// 火狐浏览器BASE64Encoder base64Encoder = new BASE64Encoder();filename = "=?utf-8?B?"+ base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else if (agent.contains("Chrome")) {// google浏览器filename = URLEncoder.encode(filename, "utf-8");
} else {// 其它浏览器filename = URLEncoder.encode(filename, "utf-8");
}

后台Java代码:

import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Encoder;import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;@WebServlet(value = "/demodownload")
public class ServletDownLoad extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");//首先获取这个图片的名字,前台通过请求参数给你传递过来了String filename = request.getParameter("filename");//获取服务器端该文件的路径String realPath = this.getServletContext().getRealPath("/WEB-INF/img/" + filename);FileInputStream in = new FileInputStream(realPath);ServletOutputStream out = response.getOutputStream();//解决文件名为中文的问题String agent = request.getHeader("user-agent");if (agent.contains("MSIE")) {// IE浏览器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+", " ");} else if (agent.contains("Firefox")) {// 火狐浏览器BASE64Encoder base64Encoder = new BASE64Encoder();filename = "=?utf-8?B?"+ base64Encoder.encode(filename.getBytes("utf-8")) + "?=";} else if (agent.contains("Chrome")) {// google浏览器filename = URLEncoder.encode(filename, "utf-8");} else {// 其它浏览器filename = URLEncoder.encode(filename, "utf-8");}//设置响应头:告诉浏览器,不要默认打开,而是弹出一个下载框。response.setHeader("content-disposition", "attachment;filename="+ filename);//设置文件的类型response.setHeader("content-type", this.getServletContext().getMimeType(filename));//流的对拷IOUtils.copy(in, out);in.close();out.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}

前台JSP代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><a href="${pageContext.servletContext.contextPath}/demodownload?filename=首页.png">点击这里下载图片</a>
</body>
</html>


3、用户登陆注册时的显示头像

  • 需求:用户在注册的时候上传一张图片作为头像,在用户登陆的时候,使用Ajax异步请求,判断用户是否存在,如果存在从数据库中取出该用户头像的路径,通过服务器传给客户端;如果用户不存在,展示一张默认的图片;

后台代码:

----登陆:

import org.westos.domain.User;
import org.westos.service.userServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;@WebServlet(name = "LoginServlet", value = "/login")
public class LoginServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {try {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");//从前台取出数据String username = request.getParameter("username");String pwd = request.getParameter("pwd");//判断用户是否勾选了记住密码String remember = request.getParameter("remember");//创建user对象User user = new User();user.setUsername(username);user.setPassword(pwd);//System.out.println(user);userServiceImpl userService = new userServiceImpl();boolean flag = userService.loginUser(user);//如果登陆成功if (flag) {//创建session对象HttpSession session = request.getSession();//如果勾选了保存密码,下次帮用户自动填写if (remember != null && remember.equals("yes")) {session.setAttribute("username", username);session.setAttribute("pwd", pwd);}//如果用户先注册,再登陆,即使没有选择保存密码,之前的代码也给你保存了,你这里移除一下数据,他下次不会帮你自动补上if (remember == null && session.getAttribute("username") != null && session.getAttribute("pwd") != null) {session.removeAttribute("username");session.removeAttribute("pwd");}//内部转发session.setAttribute("name",username);request.getRequestDispatcher("index.jsp").forward(request, response);} else {//将错误信息放在请求域对象当中request.setAttribute("msg", "用户名或密码错误");//页面内部转发到当前页面request.getRequestDispatcher("login.jsp").forward(request, response);}} catch (Exception e) {e.printStackTrace();}}
}

-----注册:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.westos.domain.User;
import org.westos.service.userService;
import org.westos.service.userServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;@WebServlet(name = "RegisterServlet", value = "/register")
public class RegisterServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//注册的逻辑:/** 1、前台提交之后,仍然判断用户是否存在、验证码是否正确以及图像是否符合要求* 2、将符合要求的用户信息存入user对象当中,如果用户注册成功,跳转到登陆页面,否则跳转到注册页面* 3、都是使用内部转发的方式跳转* */try {//设置请求的编码格式request.setCharacterEncoding("utf-8");//使用第三方工具解析带有文件的表单数据DiskFileItemFactory df = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(df);List<FileItem> list = upload.parseRequest(request);//创建user对象User user = new User();//创建该对象,方便二次校验userService userService = new userServiceImpl();//调用方法,帮我们判断表单项是否符合要求,最终返回user对象,如果不为 null,就表示用户注册成功User getUser = userService.parseListGetUser(list, request);//如果用户不存在、验证码正确、文件符合要求,就注册该用户if (getUser != null) {//如果用户返回的不为null,代表注册成功//保存session信息,这样用户在登录的时候直接展示了个人信息HttpSession session = request.getSession();session.setAttribute("username", user.getUsername());session.setAttribute("pwd", user.getPassword());session.setAttribute("imgUrl", user.getPicture());//内部转发到登陆页面request.getRequestDispatcher("login.jsp").forward(request, response);} else {//如果有一个出现了差错,内部转发到空页面request.getRequestDispatcher("empty.jsp").forward(request, response);}} catch (Exception e) {e.printStackTrace();}}
}

前台代码:

----登陆页面:

<%--Created by IntelliJ IDEA.User: lenovoDate: 2020/8/18Time: 21:32To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>用户登陆</title><link rel="icon" href="${pageContext.servletContext.contextPath}/aa.ico"mce_href="${pageContext.servletContext.contextPath}/aa.ico"type="image/x-icon"><link rel="shortcut icon" href="${pageContext.servletContext.contextPath}/aa.ico"mce_href="${pageContext.servletContext.contextPath}/aa.ico" type="image/x-icon"><style type="text/css">input[type="submit"] {background-color: #0d65d0;color: white;border: 0px;width: 100px;height: 40px;font-size: 18px;}input {height: 30px;}td {font-family: Microsoft YaHei;}span {font-size: 14px;}</style>
</head>
<body>
<center><h1>登陆页面</h1><form action="${pageContext.servletContext.contextPath}/login" method="post" onsubmit="return check()"><table border="0" cellspacing="0" cellpadding="0" width="500px" height="300px"><tr><td colspan="2"><div style="border: 0px black solid;margin: auto; width: 20%;height: 40px;"><img src="${pageContext.servletContext.contextPath}/upload/google.png"style="max-width: 100%;max-height: 100%;" id="myPicture"></div></td></tr><tr><td style="text-align: right;">用户名:</td><td><input type="text" name="username" placeholder="请输入用户名" style="width: 60%;" onchange="checkName()"id="username" value="${sessionScope.username}"/><span id="myspan1" style="color: #ff0000"></span></td></tr><tr><td style="text-align: right;">密码:&nbsp;&nbsp;&nbsp;</td><td><input type="password" name="pwd" placeholder="请输入密码" style="width: 60%;" id="pwd"onchange="checkPwd()"value="${sessionScope.pwd}"/><spanid="myspan2" style="color: red"></span></td></tr><tr><td colspan="2"><input type="checkbox" name="remember" value="yes" id="remember"style="text-align:right;vertical-align: middle;margin-left: 70%;"><label style="font-size: 14px;cursor: pointer" for="remember">记住密码</label></td><td></td></tr><tr><td colspan="2"><input type="submit" value="登陆" style="margin-left: 40%"/><a href="${pageContext.servletContext.contextPath}/register.jsp"style="font-size: 13px;margin-left: 10px;">没有账号,请先注册</a></td><td></td></tr><tr><td colspan="2"><div style="color: red;margin-left: 40%;">${requestScope.msg}</div></td><td></td></tr></table></form>
</center>
</body>
<script>//之前的用户名和密码都是通过域对象取出来的,但是这里src已经被占用了,你页面一加载,就调用一次方法//如果用户名已经填写了,它会自动根据用户名加载getPicture();/*onblur 事件处理程序:当元素或窗口失去焦点时触发该事件onchange事件处理程序:当表单元素获取焦点,并且内容发生改变时,触发该事件*/function checkName() {var uname = document.getElementById("username");var span1 = document.getElementById("myspan1");if (!uname.value.trim()) {span1.innerText = "用户名不能为空!";uname.focus();return false;} else {span1.innerText = "";//如果用户名已经填入,光标一离开,//我们做Ajax异步请求,将数据传给后台,查询数据库,是否存在该用户//我们下来进行异步提交//1、创建Ajax请求对象xmlhttp = new XMLHttpRequest();//post请求的请求参数,不能拼接在地址栏后面//http://localhost:8080/login 绝对路径//2、自己服务器里面的前台页面,请求自己服务器里面的后台Servlet 不需要写绝对路径xmlhttp.open("POST", "${pageContext.servletContext.contextPath}/judgeName", true); //相对路径//3.设置请求头信息xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded');//4、发送请求post请求的参数传递给请求体带给后台//ES6语法字符串中填充变量// alert(uname.value.trim());xmlhttp.send("uname=" + uname.value.trim());xmlhttp.onreadystatechange = function () {//200 响应状态码 200表示后台成功响应你了if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {//5、接收后台响应的字符串var jsonStr = xmlhttp.responseText;//6、解析json字符串var jsonObj = JSON.parse(jsonStr);//7、判断返回结果并展示页面if (jsonObj.hasUser == 'no') {span1.innerText = "用户不存在";//清空input框中的文本,并获取光标//给图片的src任然置为默认的图片document.getElementById("myPicture").src = "${pageContext.servletContext.contextPath}/upload/google.png";uname.innerText = "";uname.focus();return false;} else if (jsonObj.hasUser == 'yes') {getPicture();span1.innerText = "";}}}}return true;}function getPicture() {//alert("进来没?");//发送Ajax,根据用户名获得头像var uname = document.getElementById("username");var picture = document.getElementById("myPicture");//alert(picture.src);//1、创建Ajax请求对象xmlhttp = new XMLHttpRequest();//post请求的请求参数,不能拼接在地址栏后面//http://localhost:8080/login 绝对路径//2、自己服务器里面的前台页面,请求自己服务器里面的后台Servlet 不需要写绝对路径xmlhttp.open("POST", "${pageContext.servletContext.contextPath}/getPicture", true); //相对路径//3.设置请求头信息xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded');//4、发送请求post请求的参数传递给请求体带给后台// alert(uname.value.trim());xmlhttp.send("uname=" + uname.value.trim());xmlhttp.onreadystatechange = function () {//200 响应状态码 200表示后台成功响应你了if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {//alert(xmlhttp.responseText);//5、接收后台响应的字符串var jsonStr = xmlhttp.responseText;//alert(jsonStr+"json字符串本来的样子");//6、解析json字符串var jsonObj = JSON.parse(jsonStr);//7、判断返回结果并展示页面//alert(jsonObj.myfilename+"JSON解析后");picture.src = "${pageContext.servletContext.contextPath}" + jsonObj.myfilename;//alert(picture.src)}}}function checkPwd() {var pwd = document.getElementById("pwd");var span2 = document.getElementById("myspan2");if (!pwd.value.trim()) {span2.innerText = "密码不能为空!";pwd.focus();return false;} else {span2.innerText = "";}return true;}function check() {return checkName() && checkPwd();}
</script>
</html>

-----注册页面:

<%--Created by IntelliJ IDEA.User: lenovoDate: 2020/8/18Time: 21:33To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>用户注册</title><link rel="icon" href="/myLogin_Register_war_exploded/aa.ico" mce_href="/myLogin_Register_war_exploded/aa.ico"type="image/x-icon"><link rel="shortcut icon" href="/myLogin_Register_war_exploded/aa.ico"mce_href="/myLogin_Register_war_exploded/aa.ico"type="image/x-icon"><script src="jquery-3.3.1.js"></script><style type="text/css">input[type="submit"] {background-color: #0d65d0;color: white;border: 0px;width: 100px;height: 40px;font-size: 18px;}input {height: 30px;}td {font-family: Microsoft YaHei;}span {font-size: 14px;}</style>
</head>
<body>
<center><h1>注册页面</h1><form action="${pageContext.servletContext.contextPath}/register" enctype="multipart/form-data" method="post"onsubmit="return check()"><table border="0" cellspacing="0" cellpadding="0" width="520px" height="500px"><tr><td>用户名:</td><td><input type="text" name="username" placeholder="请输入用户名" style="width: 70%;" id="username"onchange="checkName()"/><spanid="myspan1" style="color: red"></span></td></tr><tr><td>密码:</td><td><input type="password" name="pwd" placeholder="请输入密码" style="width: 90%;" id="pwd"onchange="checkPwd()"/></td></tr><tr><td>确认密码:</td><td><input type="password" name="repwd" placeholder="请重复输入密码" style="width: 90%;" id="repwd"onchange="checkRepwd()"/></td></tr><tr><td>电话:</td><td><input type="tel" name="tel" value="" placeholder="请输入电话号码" style="width: 90%;"onchange="checkTel()" id="tel"/></td></tr><tr><td>邮箱:</td><td><input type="email" name="email" placeholder="请输入邮箱" style="width: 90%;" onchange="checkEmail()"id="email"/></td></tr><tr><td>性别:</td><td><input type="radio" name="sex" id="0" value="男" style="vertical-align: middle;"checked="checked"/><label for="0">男</label>&nbsp;<input type="radio" name="sex" id="1" value="女" style="vertical-align: middle;"/><labelfor="1">女</label></td></tr><tr><td>出生日期:</td><td><input type="date" name="birthday" value="" style="width: 90%;"/></td></tr><tr><td>爱好:</td><td><input type="checkbox" name="hobby" id="song" value="唱歌" style="vertical-align: middle;"checked="checked"/><labelfor="song">唱歌</label><input type="checkbox" name="hobby" id="sport" value="运动" style="vertical-align: middle;"/><labelfor="sport">运动</label><input type="checkbox" name="hobby" id="read" value="阅读" style="vertical-align: middle;"/><labelfor="read">阅读</label></td></tr><tr><td>上传头像:</td><td colspan="0"><input type="file" name="file" id="picture" value="" onchange="checkPicture()"/><spanid="myspan2" style="color: red"></span></td></tr><tr><td>验证码:</td><td colspan="3"><input type="text" name="code" placeholder="请输入验证码" id="code" onchange="checkCode()"/><img src="${pageContext.servletContext.contextPath}/code"style="width: 100px;height: 30px;border: 1px black solid;margin-bottom: -10px;"id="img" onclick="switchCode()"><a href="#" style="font-size: 15px;font-family: Microsoft YaHei;margin-left: 10px;"onclick="switchCode()">看不清?换一张</a></td></tr><tr><td colspan="2"><center><input type="submit" value="注册"/></center></td><td></td></tr></table></form>
</center>
</body>
<script>function switchCode() {var img = document.getElementById("img");//欺骗服务器img.src = "${pageContext.servletContext.contextPath}/code?" + new Date().getTime();}function check() {//alert("进来没?");return checkName() && checkPwd() && checkRepwd() && checkEmail() && checkTel() && checkCode() && b;}function checkName() {var name = document.getElementById("username");var span1 = document.getElementById("myspan1");if (name.value.trim().length == 0) {alert("用户名不能为空!");name.focus();return false;} else {//我们下来进行异步提交//1、创建Ajax请求对象xmlhttp = new XMLHttpRequest();//post请求的请求参数,不能拼接在地址栏后面//http://localhost:8080/login 绝对路径//2、自己服务器里面的前台页面,请求自己服务器里面的后台Servlet 不需要写绝对路径xmlhttp.open("POST", "${pageContext.servletContext.contextPath}/judgeName", true); //相对路径// xmlhttp.open("POST", "/LoginAndRegister_war_exploded/judge?uname=" + name.value.trim(), true);//3.设置请求头信息xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded');//4、发送请求post请求的参数传递给请求体带给后台//ES6语法字符串中填充变量// alert(name.value.trim());xmlhttp.send("uname=" + name.value.trim());xmlhttp.onreadystatechange = function () {//200 响应状态码 200表示后台成功响应你了if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {//5、接收后台响应的字符串var jsonStr = xmlhttp.responseText;//6、解析json字符串var jsonObj = JSON.parse(jsonStr);//7、判断返回结果并展示页面if (jsonObj.hasUser == 'no') {span1.innerText = "";} else if (jsonObj.hasUser == 'yes') {span1.innerText = "用户已经存在";//清空input框中的文本,并获取光标name.innerText = "";name.focus();return false;}}}}return true;}function checkPwd() {var pwd = document.getElementById("pwd");if (pwd.value.trim().length == 0) {alert("密码不能为空!");pwd.focus();return false;}return true;}function checkRepwd() {var pwd = document.getElementById("pwd");var repwd = document.getElementById("repwd");if (repwd.value.trim().length == 0 || repwd.value != pwd.value) {alert("两次输入的密码不一致!");repwd.focus();return false;}return true;}function checkTel() {var re = /^1\d{10}$/;var tel = document.getElementById("tel");if (!re.test(tel.value.trim())) {alert("电话号码格式错误!");tel.focus();return false;}return true;}function checkEmail() {var re = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/;var email = document.getElementById("email");if (!re.test(email.value.trim())) {alert("邮箱格式错误!");email.focus();return false;}return true;}function checkCode() {var code = document.getElementById("code");if (code.value.trim().length == 0) {alert("请输入验证码!");code.focus();return false;} else {//我们下来进行异步提交//1、创建Ajax请求对象xmlhttp = new XMLHttpRequest();//post请求的请求参数,不能拼接在地址栏后面//http://localhost:8080/login 绝对路径//2、自己服务器里面的前台页面,请求自己服务器里面的后台Servlet 不需要写绝对路径xmlhttp.open("POST", "${pageContext.servletContext.contextPath}/judgeCode", true); //相对路径//3.设置请求头信息xmlhttp.setRequestHeader('content-type', 'application/x-www-form-urlencoded');//4、发送请求post请求的参数传递给请求体带给后台//ES6语法字符串中填充变量:有问题!xmlhttp.send("code=" + code.value.trim());xmlhttp.onreadystatechange = function () {//200 响应状态码 200表示后台成功响应你了if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {//5、接收后台响应的字符串var jsonStr = xmlhttp.responseText;//6、解析json字符串var jsonObj = JSON.parse(jsonStr);//7、判断返回结果并展示页面if (jsonObj.codeIsRight == 'no') {alert("验证码错误");//重新申请一个验证码switchCode();//清空input框中的文本,并获取光标、code.innerText = "";code.focus();return false;}}}}return true;}var b = false;function checkPicture() {var picture = document.getElementById("picture");var span2 = document.getElementById("myspan2");if (picture.value == '') {alert("请选择头像!");return false;} else {const formData = new FormData();formData.append("file", picture.files[0]);//alert(formData);$.ajax({url: "${pageContext.servletContext.contextPath}/judgePicture",type: "POST",data: formData,dataType: "json",processData: false,  // 告诉jQuery不要去处理发送的数据contentType: false,   // 告诉jQuery不要去设置Content-Type请求头success: function (res) {// console.log(res);if (res.pictureIsRight == 'no') {//如果图片不符合要求span2.innerText = "图片不符合要求,请重新选择";} else if (res.pictureIsRight == 'yes') {//如果图片符合要求//alert("res.pictureIsRight == 'yes'");span2.innerText = "";b = true;}}});}return b;}
</script>
</html>

4、注解

  • 注解(Annotation),也叫元数据,一种代码级别的说明,注解是给程序看的;
  • 它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。
  • 它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
  • 格式:
@interface 注解名{}
  • 作用:

编译检查
替代配置文件,框架中很多注解为了简化配置;
定义注解(元注解:注解上的注解)

  • Java中3个常见的注解:

1、@Override注解

他是用来声明该方法是重写了父类的方法,执行编译期的检查;

2、@SuppressWarnings

抑制警告,值有很多,只需要知道一个 all,抑制所有的警告

@SuppressWarnings("all")
public class MyTest {public static void main(String[] args) {int a;}
}


3、@Deprecated

用于声明该方法不赞成使用,标志过时;

  • 注解属性:

注解本身使用@interface来定义;

注解本质就是一个接口,可以用javap这个命令反编译一下,注解的字节码文件,例如javap myan.class

在接口中可以有常量和抽象方法,抽象方法在注解中就称之为注解属性;

public @interface MyAnnotation {//注解本质上是一个接口,那接口中的抽象方法,其实就是注解中的属性public abstract String name(); //注解的属性,前面的public abstract 可以省略int hehe();  //前面的数据类型,不是所有类型都支持Class haha();
}


由上图可知,注解本身是一个接口类,继承自Annotation类;

  • 注解属性支持的类型如下:
基本类型
String
Class
Annotation
Enum:枚举
以上类型对应的一维数组
  • 注意:

一旦注解有属性了,使用注解的时候必须赋值,(除非这个注解属性有默认值)

public @interface MyAnnotation {int hehe();  //注意我这个注解有属性了
}

那么我在另一个类上添加我自定义的注解就会报错,因为我注解中的属性没有赋值

@MyAnnotation()  //报错,要不报错括号里面要赋值,除非有默认值
public class Test {}

下面就是正确的:

 @MyAnnotation(hehe=100)   //给注解中属性赋值,就不报错了
public class Test {}

注解中有多个属性,在给属性赋值时,用逗号隔开;并且一个注解也可以赋多个属性值,这时候使用大括号包裹属性值,属性值之间使用逗号隔开;

public @interface MyAnnotation {int hehe();  //注意我这个注解有属性了String haha();int[] num();
}
//多个属性赋值
@MyAnnotation(hehe=100,haha='abc',num={10,20})
//给注解中属性赋值,就不报错了
public class Test {}

赋值的格式:

@注解名(属性名=属性值)
若注解类型为数组,且只有一个值的时候,可以有两种写法方式1:属性名 = { 值 }方式2:属性名=属性值

注意特殊情况若属性名为value的时候,且只需要为这个value属性赋值的时候,value可以省略;

public @interface MyAnnotation {String value(); //这个属性名叫value 比较特殊
}

注解中的属性名为value时,赋值时可以省略value;

@MyAnnotation("zhangsan")  //属性名为value时可以省略value//@MyAnnotation(value="zhangsan") 当然不省略也可以public class Test {}

使用 default 关健字给属性赋上默认值

public @interface MyAnnotation {int num() default 100;String name() default "zhangsan";
}
@MyAnnotation()  //因为注解的属性中有默认值,我们可以不用赋值
public class Test {}

与interface的区别

  • 注解基本要求:

注解是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。Java语言解释器在工作时会忽略这些annotation,因此在JVM中这些annotation是“不起作用”的,只能通过配套的工具才能对这些annontaion类型的信息进行访问和处理。

  • Annotation与interface的异同:

1、Annotation类型使用关键字@interface而不是interface。继承了java.lang.annotation.Annotation接口,并非声明了一个interface;
2、Annotation类型、方法定义是独特的、受限制的。Annotation类型的方法必须声明为无参数、无异常抛出的。这些方法定义的是annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。注解方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用default和一个默认数值来声明成员的默认值,null不能作为成员默认值,与非annotation类型中定义方法有很大不同。Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic;

元注解

  • 使用注解:就是注解可以加在哪里,我们可以通过元注解,来标识我们自己定义的注解可以加在什么位置;
  • 元注解:定义在注解上的注解;

@Retention:规定注解保留到什么阶段,值为RetentionPolicy的三个枚举值

SOURCE:只在代码中保留,在字节码文件中就删除了,不会留在Class文件中。
CLASS:在代码和字节码文件中保留,但是在运行的时候,JVM不会读取。
RUNTIME:所有阶段都保留,所以它能够通过反射调用,所以正常运行时注解都是使用这个参数

@Target:规定注解作用在什么上面,值为ElementType的枚举值

TYPE:作用在类 接口 等上面
METHOD:作用方法上面
FIELD:作用字段上面
例如:
@Target(ElementType.METHOD)  //这个表示我们自定义的注解只能加在方法上
@Retention(RetentionPolicy.RUNTIME) //表示我们的注解保留到运行阶段
@interface MyAnnotation {int num() default 100;String name() default "zhangsan";
}使用注解:
public class Test {@MyAnnotation() 这个注解只能加在方法上public void add(){}
}

需求:

通过配置四个参数获取与数据库连接的工具类;

步骤分析:

1、自定义一个注解JDBCInfo,添加元注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;//表示该注解用在运行期间
@Retention(value = RetentionPolicy.RUNTIME)
//表示该注解用在方法上
@Target(value = ElementType.METHOD)
public @interface JDBCInfo {String driverClass() default "com.mysql.cj.jdbc.Driver";String url() default "jdbc:mysql://localhost:3306/mydb?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false";String user() default "root";String password() default "123456";
}

2.在jdbcutils工具类中提供一个getConnection,在方法上面添加一个注解@JDBCInfo(...)

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class JDBCUtils {@JDBCInfopublic static Connection getConnection() throws NoSuchMethodException, ClassNotFoundException, SQLException {//获取当前类的字节码文件对象Class<JDBCUtils> jdbcUtilsClass = JDBCUtils.class;//获取方法对象Method method = jdbcUtilsClass.getMethod("getConnection");//判断上述方法是否有注解,如果有的话获取注解,并拿到注解的属性值//参数是注解的class对象boolean b = method.isAnnotationPresent(JDBCInfo.class);//获取注解if(b){JDBCInfo info = method.getAnnotation(JDBCInfo.class);//获取注解的属性值String driverClass = info.driverClass();String url = info.url();String user = info.user();String password = info.password();//加载数据库驱动Class.forName(driverClass);return DriverManager.getConnection(url,user,password);}return null;}
}

3.运行的时候可以通过getConnection获取一个连接

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class MyTest3 {public static void main(String[] args) throws NoSuchMethodException, SQLException, ClassNotFoundException {Connection conn = JDBCUtils.getConnection();PreparedStatement statement = conn.prepareStatement("select * from dallas_dept");ResultSet resultSet = statement.executeQuery();while (resultSet.next()) {String dept_no = resultSet.getString(1);String dept_name = resultSet.getString(2);System.out.println(dept_no + "-----------" + dept_name);/*d1-----------Researchd3-----------Sales*/}conn.close();statement.close();}
}
  • servlet 3.0开始,支持注解开发,没有web.xml这个文件了,内嵌了文件上传功能;比如我们创建servlet,在Servlet类上面添加 @WebServlet(urlPatterns="/demo2"),一个Servlet也可以配置多个映射路径,访问哪一个都行,urlPatterns这个注解属性是个数组,所以可以配置多个值@WebServlet(urlPatterns={ "/demo2", "/demo21" },loadOnStartup=2);它的作用与value的作用是一样的;但是注解不能完全替代配置文件,它只是起到了一个简化的作用;
@WebServlet(name = "ServletDemo1",urlPatterns = {"/demo1","/demo2","/demo3"},initParams = {@WebInitParam(name = "num",value = "100")},loadOnStartup = 0)
  • 在servlet的注解@WebServlet中,有一个参数也是注解,意味着如果要给这个参数赋值,必须给定一个注解类型:


代码:

import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet(name = "MyServlet", value = "/my",initParams = {@WebInitParam(name = "init",value = "/init"),@WebInitParam(name = "init2",value = "/init2")})
public class MyServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取注解的值String init = this.getInitParameter("init");System.out.println(init);String init2 = this.getInitParameter("init2");System.out.println(init2);/*/init/init2*/}
}

Java web文件的上传和下载、注解相关推荐

  1. java中文件的上传和下载:文件上传和下载原理

    在TCP/IP中,我们知道最早的上传机制为FTP,它是指将文件由客户端发送到服务器的标准机制.然而我们在jsp编程中不能使用FTP来上传文件,这是由于jsp运行机制决定的.               ...

  2. 初学Java Web(7)——文件的上传和下载

    文件上传 文件上传前的准备 在表单中必须有一个上传的控件 <input type="file" name="testImg"/> 因为 GET 方式 ...

  3. nginx java文件上传_Nginx实现文件的上传和下载

    文件的上传只要保证特殊的地址先到达Nginx,然后通过Nginx指定至指定的服务器即可,目前配置是本机.文件的下载的做法就是把本机的当前目录下面的文件给返回回去. server { listen ; ...

  4. java struts2下载文件_Struts2下多文件的上传与下载

    Struts2下多文件的上传与下载 目录 多文件 上传 下载 随意文件java Struts2单例 配置 动态读取 李顺利 在网络上,对于Java处理文件上传和下载的技术比较多,而Struts作为一款 ...

  5. java图片上传下载_java实现文件的上传和下载

    1. servlet 如何实现文件的上传和下载? 1.1上传文件 参考自:http://blog.csdn.net/hzc543806053/article/details/7524491 通过前台选 ...

  6. java实现ftp文件的上传与下载

    最近在做ftp文件的上传与下载,基于此,整理了一下资料.本来想采用java自带的方法,可是看了一下jdk1.6与1.7的实现方法有点区别,于是采用了Apache下的框架实现的... 1.首先引用3个包 ...

  7. FastDFS:Java客户都实现文件的上传、下载、修改、删除

    FastDFS:Java客户都实现文件的上传.下载.修改.删除 <project xmlns="http://maven.apache.org/POM/4.0.0" xmln ...

  8. Hadoop环境下用java代码实现hdfs远程文件的上传和下载

    Hadoop环境下用java代码实现hdfs远程文件的上传和下载 文章目录 Hadoop环境下用java代码实现hdfs远程文件的上传和下载 一.新建maven工程 二.文件的上传 三.文件的下载 四 ...

  9. Java ftp实现文件的上传和下载ftp,sftp sun.net.ftp.FtpProtocolException:Welcome message: SSH-2.0-OpenSSH_5.1

    Java ftp实现文件的上传和下载 ftp,sftp 运行后发现很长时间没有反应,很久以后抛出如下异常:sun.net.ftp.FtpProtocolException:Welcome messag ...

最新文章

  1. 【网站汇总】论文相关
  2. 在线作图|2分钟画一张堆叠面积图
  3. 瞧!老师的屏幕是如何被学生的弹幕玩坏的......
  4. 人均奖金300万,2021年“科学探索奖”名单揭晓:高会军周昆上榜,女性获奖人8位创纪录...
  5. 蓝桥杯-矩阵相乘(java)
  6. git的常用的使用方法
  7. linux下memcache安装
  8. git-创建版本仓库-创建版本-查看版本
  9. 全能App研发助手!滴滴开源DoraemonKit
  10. GBK 汉字内码扩展规范编码表
  11. 探讨基于球谐函数的全局光照
  12. BackTrack5(BT5)各版本下载
  13. 毕业论文系列-公式编号-等号对齐及编号
  14. Vs2010中文版MSDN 安装方法
  15. 如何关闭wps热点,如何关闭wpscenter,如何关闭我的wps
  16. Android实战开发--制作圆形头像(简易篇)
  17. 超全超详细的安装nvidia显卡驱动教程
  18. html背景渐变蓝色,CSS3网页渐变色背景,适用于IE
  19. ★如何引导客户需求?几个经…
  20. android 仿微信聊天气泡显示图片,怎么实现微信聊天时的气泡图(一)

热门文章

  1. PR不支持导入MKV【Influx插件】
  2. 艾司博讯:拼多多千人千面含义及作用
  3. 物联网养殖智能系统优势盘点
  4. 呵呵哒学习笔记:《计算机网络》第二章 物理层
  5. INT 21H 指令说明及使用方法(汇编语言学习)
  6. 全球与中国荧光增白剂CXT市场深度研究分析报告
  7. JS 输出指定格式的时间
  8. 用计算机来弹洪荒之力,如果不会支撑,纵使有“洪荒之力”也弹不强
  9. 虚幻引擎中文教学福利:使用 C++ 开发多人游戏
  10. endnote转化成纯文本后_纯文本+ EndNote + Word 处理参考文献