Maven
maven由于它的约定大于配置,如果遇到配置文件无法被导出或者生效的问题,解决方案:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
Servlet简介
- Servlet就是sun公司开发动态web的一门技术
- Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个步骤:
- 编写一个类,实现Servlet接口
- 把开发好的Java类部署到web服务器中
Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会走一下流程:
ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用;
1.共享数据
在这个Servlet中保存数据,可以在另外一个servlet中拿到;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter();
writer.println("Hello,Servlet");
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name","张飞");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req, resp);
}
}
public class HiServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
ServletContext servletContext = this.getServletContext();
PrintWriter writer = resp.getWriter();
writer.println("Hello," + servletContext.getAttribute("name"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req, resp);
}
}
2.获取初始化参数
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>sd</servlet-name>
<servlet-class>com.release.servlet.ServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd</servlet-name>
<url-pattern>/sd</url-pattern>
</servlet-mapping>
</web-app>
public class ServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().println(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req, resp);
}
}
3.转发请求
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
ServletContext servletContext = this.getServletContext();
servletContext.getRequestDispatcher("/sd").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
doGet(req, resp);
}
}
4.读取资源文件
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
InputStream inputStream = this.getServletContext().getResourceAsStream("WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(inputStream);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
resp.getWriter().println(username + ":" + password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
doGet(req, resp);
}
}
HttpservletResponse
1.简单分类
负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
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_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2.常见应用
- 向浏览器输出消息
- 下载文件
- 要获取下载文件路径
- 下载文件名是什么
- 设置浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String path = this.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()) {
realPath.mkdir();
}
// 1.要获取下载文件路径
String downPath = this.getServletContext().getRealPath("/upload");
System.out.println("下载文件路径:"+downPath);
// 2.下载文件名是什么
String fileName = "a.png";
// 3.设置浏览器能够支持下载我们需要的东西
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
// 4.获取下载文件的输入流
File file = new File(downPath, fileName);
FileInputStream inputStream = new FileInputStream(file);
// 5.创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6.获取OutputStream对象
ServletOutputStream outputStream = resp.getOutputStream();
// 7.将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
while ((len = inputStream.read(buffer))>0){
outputStream.write(buffer,0,len);
}
inputStream.close();
outputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req, resp);
}
}
- 验证码功能
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//让浏览器3秒自动刷新一次
resp.setHeader("refresh", "3");
//在内存中创建一张图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics graphics = 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());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
doGet(req, resp);
}
/**
* 生产随机数
*
* @return
*/
private String makeNum() {
Random random = new Random();
String num = random.nextInt(999999) + "";
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 6 - num.length(); i++) {
stringBuffer.append("0");
}
num = stringBuffer.toString() + num;
return num;
}
}
- 实现重定向
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.sendRedirect("/image");
}
HttpservletRequest
转发
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
//转发
req.getRequestDispatcher("/image").forward(req, resp);
}
重定向和转发的区别:
- 相同点
- 页面都会实现跳转
- 不同点
- 请求转发的时候,url不会产生变化 307
- 重定向的时候,url地址栏会发生变化 302
Cookie、Session
会话
会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,关闭浏览器,这个过程可以称之为会话
保存会话的两种技术
Cookie
- 客户端技术(响应,请求)
Session - 服务器技术,利用这个技术我们可以把用的信息或者数据放在Session中
Cookie
- 从请求中拿到cookie信息
- 服务器响应给客户端 cookie
Cookie[] cookies = req.getCookies();
cookie.getName()
cookie.getValue()
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
cookie.setMaxAge(24 * 60 * 60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端一个cookie
cookie:一般会保存在本地的用户目录下appdata
一个网站cookie是否存在上线
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- cookie大小有限制4kb
- 300个cookie浏览器上限
Session
- 服务器会给每个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
- 用户登录之后,整个网站它都可以访问!
使用场景:
- 保存一个登录用户信息
- 购物车信息
- 在整个网站中经常使用的数据,我们将它保存的session中
Session和Cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建
JSP
Java Server Pages: Java服务器端页面,也和Servlet一样,用于动态Web技术
最大的特点:
- 写jsp就像在写HTML
- 区别:
- HTML只给用户提供静态的数据
- JSP页面中可以嵌入JAVA代码,为用户提供动态数据
Filter
public class CharacterEncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("==========init==========");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("=============执行前=================");
filterChain.doFilter(request, response);
System.out.println("=============执行后=================");
}
@Override
public void destroy() {
System.out.println("==========destroy==========");
}
}
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>com.release.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
监听器
public class OnlineCountListener implements HttpSessionListener {
/**
* 一旦创建Session就会触发一次这个事件
* @param httpSessionEvent
*/
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
ServletContext servletContext = httpSessionEvent.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if (onlineCount == null){
onlineCount = new Integer(1);
}else {
int i = onlineCount.intValue();
onlineCount = new Integer(i+1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
@Override
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 i = onlineCount.intValue();
onlineCount = new Integer(i-1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
}
<!--注册监听器-->
<listener>
<listener-class>com.release.listener.OnlineCountListener</listener-class>
</listener>
JDBC
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
String url = "jdbc:mysql://localhost:3306/DB01?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&autoReconnect=true";
String username = "root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象Statement:CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from dept";
//5.执行查询SQL,返回一个ResultSet : 结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("deptno = "+rs.getObject("deptno"));
System.out.println("dname = "+rs.getObject("dname"));
System.out.println("db_source = "+rs.getObject("db_source"));
}
//6.关闭连接,释放资源,先开后关
rs.close();
statement.close();
connection.close();
}
}
JDBC事务
public class TestJdbc3 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
String url = "jdbc:mysql://localhost:3306/DB01?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&rewriteBatchedStatements=true&autoReconnect=true";
String username = "root";
String password = "123456";
Connection connection = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection(url, username, password);
//通知数据库开启事务,false 开启
connection.setAutoCommit(false);
String sql = "update dept set db_source = 'db03' where deptno = 1";
connection.prepareStatement(sql).executeUpdate();
// int i = 1 / 0;
String sql2 = "update dept set db_source = 'db03' where deptno = 2";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();
System.out.println("提交成功");
} catch (Exception e) {
try {
//如果出现异常,就通知数据库回滚事务
connection.rollback();
}catch (SQLException e1){
e1.printStackTrace();
}
}finally {
try {
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
文件上传
<dependencies>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="/upload.do" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
<p><input type="file" name="file1"></p>
<p><input type="file" name="file1"></p>
<p><input type="submit"> |<input type="reset"> </p>
</form>
</body>
</html>
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
//判断上传的文件是普通表单还是文件表单
if (!ServletFileUpload.isMultipartContent(req)) {
return;//如果是普通表单,则终止
}
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdir();
}
//缓存临时文件
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tempFile = new File(tempPath);
if (!tempFile.exists()) {
tempFile.mkdir();
}
//处理上传的文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
//但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于common-io组件;
try {
//1.创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
DiskFileItemFactory factory = getDiskFileItemFactory(tempFile);
//2.获取ServletFileUpload
ServletFileUpload upload = getServletFileUpload(factory);
//3.处理上传的文件
String msg = uploadParseRequest(upload, req, uploadPath);
//servlet请求转发消息
req.setAttribute("msg", msg);
req.getRequestDispatcher("info.jsp").forward(req, resp);
} catch (FileUploadException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
doGet(req, resp);
}
/**
* 创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的
*
* @param tempFile
* @return
*/
private DiskFileItemFactory getDiskFileItemFactory(File tempFile) {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 1024);//缓存区大小为1M
factory.setRepository(tempFile);//临时目录的保存目录
return factory;
}
/**
* 获取ServletFileUpload
*
* @param factory
* @return
*/
private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
DecimalFormat df = new DecimalFormat("#.##");
df.setRoundingMode(RoundingMode.HALF_UP);
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener((pByteRead, pContentLength, pItems) ->
System.out.println("总大小:" + pContentLength + " 已上传:" + pByteRead + " 上传百分比:" + df.format((float) pByteRead / pContentLength * 100) + "%")
);
//处理乱码
upload.setHeaderEncoding("utf-8");
//设置单个文件的最大值
upload.setFileSizeMax(1024 * 1024 * 10);
//设置总共能够上传文件的大小
upload.setSizeMax(1024 * 1024 * 10);
return upload;
}
/**
* 处理上传的文件
*
* @param upload
* @param req
* @param uploadPath
* @return
*/
private String uploadParseRequest(ServletFileUpload upload, HttpServletRequest req, String uploadPath) throws FileUploadException, IOException {
String msg = "";
//解析前端的请求,封装成一个FileItem对象
List<FileItem> fileItems = upload.parseRequest(req);
for (FileItem fileItem : fileItems) {
//判断上传的文件是普通表单还是带文件的表单
if (fileItem.isFormField()) {
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
System.out.println("name:" + name + " value:" + value);
} else {
//判断它是上传的文件
//==========================处理文件============================
//拿到文件名字
String uploadFileName = fileItem.getName();
System.out.println("上传的文件名:" + uploadFileName);
if (uploadFileName.trim().equals("") || uploadFileName == null) {
continue;
}
//获得上传的文件名
String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
//获得文件的后缀名
String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
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.mkdir();
}
//==========================文件传输============================
//获得文件上传的流
InputStream inputStream = fileItem.getInputStream();
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
//创建一个缓冲区
byte[] buffer = new byte[1024 * 1024];
//判断是否读取完毕
int len = 0;
//如果大于0说明还存在数据
while ((len = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
//关闭流
fos.close();
inputStream.close();
msg = "文件上传成功!";
fileItem.delete();//上传成功,清除临时文件
}
}
return msg;
}
}