JavaWeb核心四 Li.057

EL 表达式 EL (Expression Language): 表达式语言. 在JSP 2.0规范中加入的内容, 也是Servlet规范的一部分. 作用: 在JSP页面中获取数据. 让我们的JSP脱离java代码块和JSP表达式 <%--请求域中添加username数据--%> <% request.setAttribute("username","zhangsan"); %> <%--获取请求域的username 3种方式--%> <%--Java代码块--%> <% out.println(request.getAttribute("username")); %> <br/> <%--JSP表达式获取--%> <%= request.getAttribute("username")%> <br/> <%--EL表达式获取--%> ${username} EL 表达式获取数据类型 获取基本数据类型的数据 获取自定义对象类型的数据 获取数组类型的数据 获取List集合类型的数据 获取Map集合类型的数据 <%@ page import="com.lizicai.bean.Student" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.HashMap" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% pageContext.setAttribute("num",10); %> 基本数据类型 ${num} <br/> <% Student stu = new Student("李明", 23); pageContext.setAttribute("stu",stu); %> 自定义对象: ${stu} <br/> ${stu.name} ${stu.age} <br/> <% String[] arr = {"Haha", "go"}; pageContext.setAttribute("arr",arr); %> 数组: ${arr} <br/> ${arr[0]} ${arr[1]} ${arr[2]} <br/> <% ArrayList<String> list = new ArrayList<>(); list.add("aaa"); list.add("bbb"); pageContext.setAttribute( "list",list); %> List集合 ${list} ${list[0]} <br/> <% HashMap<String, Student> map = new HashMap<>(); map.put("s01",new Student("李明",20)); map.put("s02",new Student("张三",20)); pageContext.setAttribute( "map",map); %> Map 集合: ${map} <br/> 第一个学生 ${map.s01} <br> 第一个学生的姓名 ${map.s01.name} <br> </body> </html> EL 表达式注意事项 EL 表达式没有空指针异常 EL 表达式没有索引越界异常 EL 表达式没有字符串的拼接 <% Student s = null; String [] arr2 = {"Hello", "World"}; pageContext.setAttribute( "s",s); pageContext.setAttribute( "arr2",arr2); %> ${s} ${arr2[10]} ${arr2[0]}+${arr2[1]} EL 表达式运算符 关系运算符 关系运算符 作用 示例 结果 ==或eq 等于 略 略 !=或ne 不等于 略 略 <或lt 小于 略 略 >或gt 大于 略 略 <=或le 小于等于 略 略 >=或ge 大于等于 略 略 逻辑运算符 运算符 作用 示例 结果 &&或and 并且 略 略 ||或or 或者 略 略 !或not 取反 略 略 其他运算符 运算符 作用 empty 1判断对象是否为null.2判断字符串是否为空字符串.3判断窗口元素是否为0 条件?表达式1:表达式2 三元运算符 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>EL 表达式运算符</title> </head> <body> <% String ss = null; String ss2 = ""; int[] arr = {}; %> ${empty ss} <br/> ${empty ss2} <br/> ${empty arr} <br/> <% pageContext.setAttribute("gender", "man"); %> <input type="radio" name="gender" value="man" ${gender == "man" ? "checked" : ""}> 男 <input type="radio" name="gender" value="woman" ${gender == "woman" ? "checked" : ""}> 女 </body> </html> EL 表达式使用细节 EL 表达式能够获取四大域对象的数据, 根据名称从小到大在域对象中查找. 还可以获取JSP其他八个隐式对象, 并调用对象中的方法. <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% pageContext.setAttribute("username", "zhangsan1"); request.setAttribute("username", "zhangsan2"); session.setAttribute("username", "zhangsan3"); application.setAttribute("username", "zhangsan4"); %> ${username} <br> <%= request.getContextPath() %> ${pageContext.request.contextPath} </body> </html> EL 表达式隐式对象 隐式对象名称 对应JSP隐式对象 说明 pageContext pageContext 功能完全相同 applicationScope 没有 操作应用域对象数据 sessionScope 没有 操作会话域对象数据 requestScop 没有 操作请求域对象数据 pageScope 没有 操作页面域对象数据 header 没有 操作请求头数据 headerValues 没有 获取请求头数据(多个值) param 没有 获取请求参数数据 paramValues 没有 获取请求参数数据(多个值) initParam 没有 获取全局配置参数数据 cookie 没有 获取Cookie 对象 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <%-- pageContext 对象, 可以获取其他3个域对象和JSP中八个隐式对象--%> ${pageContext.request.contextPath} <br/> <%--applicationScope sessionScope requestScop pageScope--%> <% request.setAttribute("username", "zhangsan1"); %> <% pageContext.setAttribute("username", "zhangsan2"); %> ${username} <br/> ${requestScope.username} <br/> ${pageScope.username} <br/> <%--header headerValues 获取的数组--%> ${header["connection"]} <br> ${headerValues["connection"][0]} <br> <%--param paramValues 获取请求参数--%> ${param.username} <br/> ${paramValues.hobby[0]} <br/> ${paramValues.hobby[1]} <br/> <%--initParam 获取全局配置参数--%> ${initParam.pname} <br> <%--cookie--%> ${cookie} <br> ${cookie.JSESSIONID} <br> <%-- 获取集合元素--%> ${cookie.JSESSIONID.name} <br> <%-- 获取cookie对象的名称 --%> ${cookie.JSESSIONID.value} <br> <%-- 获取cookie对象的数据值 --%> </body> </html> JSTL 介绍 JSTL (Java Servler Pages Standarded Tag Library): JSP标准标签库 主要提供给开发人员一个标准通用的标签库 开发人员可以利用这些标签取代JSP页面上的Java代码, 从而提高程序的可读性, 降低程序的维护难度. 组成 作用 说明 core 核心标签库 通用的逻辑处理 fmt 国际化 不同地域显示不同语言 functions EL函数 EL表达式可以使用的方法 sql 操作数据库 了解 xml 操作XML 了解 JSTL 核心标签库 标签名称 功能分类 属性 作用 <标签名:if> 流程控制 核心标签库 用于条件判断 <标签名:choose> ifelseif流程控制 核心标签库 用于多条件判断 <标签名:when> ifelseif流程控制 核心标签库 用于多条件判断 <标签名:otherwise> ifelseif流程控制 核心标签库 用于多条件判断 <标签名:forEach> 迭代遍历 核心标签库 用于循环遍历 http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/解压lib的包导入tomcatlib中 ...

October 13, 2021&nbsp;·&nbsp;7 分钟&nbsp;·&nbsp;Lizicai

JavaWeb核心三 Li.056

Cookie 属性 属性名 作用 是否重要 name Cookie的名称 必须属性 value Cookie的值(不支持中文) 必须属性 path Cookie的路径 重要 domain Cookie的域名 重要 maxAge Cookie的存活时间 重要 version Cookie的版本号 不重要 comment Cookie的描述 不重要 Cookie 方法 方法名 作用 Cookie(String.name,String.Value) 构造方法创建对象 属性对应的set和get就去 赋值和获取值 Cooke 添加和获取 添加 HttpServletResponse 返回值 方法名 说明 void addCookie(Cookie.cookie) 向客户端添加Cookie 获取 HttpServletRequest 返回值 方法名 说明 Cookie[] getCookies() 获取所有的Cookie Cookie 细节 数量限制 每个网站最多只能有20个Cookie, 且大小不能超过4KB. 所有网站的Cookie总数不能超过300个 名称限制 Cookie的名称只能包含ASCCI码表中字母,数字字符. 不能包含逗号,分号,空格, 不能以$开头 Cookie的值不支持中文 存活时间限制setMaxAge()方法接收数字 负整数: 当前会放有效, 浏览器关闭则清除 0: 立即清除 正整数: 以秒为单位设置存活时间 访问路径限制 默认路径: 取自第1次访问的资源路径前缀. 只要以这个路径开头就能访问到 设置路径: setPath()方法设置指定路径 import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; @WebServlet ( value = "/demo1Cookie") public class Demo1Cookie extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); PrintWriter pw = resp.getWriter(); pw.write("欢迎访问本网站, 你的最后访问时间为:"); Cookie cookie = new Cookie("time", System.currentTimeMillis()+""); cookie.setMaxAge(10); resp.addCookie(cookie); Cookie[] arr = req.getCookies(); for(Cookie c : arr){ if("time".equals(c.getName())){ String value = c.getValue(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); pw.write(sdf.format(new Date(Long.parseLong(value)))); } } } } HttpSession 介绍 HttpSession: 服务器端会话管理技术 本质也采用客户端会话管理技术 只不过在客户保存一个特殊标识, 而共享的数据保存到了服务端的内存对象中. 第次请求时, 会将特殊标识带到服务器端, 根据这个标识来找到对应的内存空间, 从而实现数据共享. 是Servlet规范中四大域对象之一的会话域对象 作用: 可以实现数据共享 域对象 功能 作用 ServletContext 应用域 在整个应用之间实现共享数据 ServletRequest 请求域 在当前的请求或请求转发之间实现数据共享 HttpSession 会话域 在当前会话范围之间实现数据共享 HttpSession 常用方法 返回值 方法名 说明 void setAttribute(String.name,Object.value) 设置共享数据 Object getAttribute(String.name) 获取共享数据 void removeAttribute(String.name) 移除共享数据 String getId() 获取唯一标识名称 void involidate() 让session立即失效 HttpSession 获取 返回值 方法名 说明 HttpSession getSession() 获取HttpSession对象 HttpSession getSession(boolean.create) 获取HttpSession,未获取到是否自动创建 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( value = "/demo1Session") public class Demo1Session extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); HttpSession session = req.getSession(); System.out.println(session); System.out.println(session.getId()); session.setAttribute("username",username); } } 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( value = "/demo2Session") public class Demo2Session extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); System.out.println(session); System.out.println(session.getId()); Object username = session.getAttribute("username"); resp.getWriter().write(username+""); } } 禁用Cookie 就获取不到了 可以使用手动拼接链接 resp.getWriter().write("<a href='"+resp.encodeURL("http://localhost:8080/demo3Session")+"'>go to servlet</a>"); HttpSession 的细节 浏览器禁用Cookie, 禁止访问 ...

October 8, 2021&nbsp;·&nbsp;6 分钟&nbsp;·&nbsp;Lizicai

JavaWeb核心二 Li.055

请求对象 返回值 方法名 说明 String getContextPath() 获取虚拟目录名称 String getServletPath() 获取Servlet映射路径 String getRemoteAddr() 获取访问者ip地址 String getQueryString() 获取请求的消息数据 String getRequestURI() 获取统一资源标识符 String getRequestURL() 获取统一资源定位符 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.IOException; @WebServlet(name = "demo1GetPath", value = "/demo1GetPath") public class Demo1GetPath extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String contextPath = req.getContextPath(); System.out.println(contextPath); String servletPath = req.getServletPath(); System.out.println(servletPath); String remoteAddr = req.getRemoteAddr(); System.out.println(remoteAddr); String queryString = req.getQueryString(); System.out.println(queryString); String requestURI = req.getRequestURI(); System.out.println(requestURI); StringBuffer requestURL = req.getRequestURL(); System.out.println(requestURL); } } 请求头信息 返回值 方法名 说明 String getHeader(String.name) 根据请求头名获取一个值 Enumeration<String> getHeaders(String.name) 根据请求头名获取多个值 Enumeration<String> getHeaderNames() 获取所有请求头名称 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.IOException; import java.util.Enumeration; @WebServlet(name = "demo2GetPath", value = "/demo2GetPath") public class Demo2GetPath extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String host = req.getHeader("Host"); System.out.println(host); Enumeration<String> headers = req.getHeaders("Accept-Encoding"); System.out.println("----------------------------------------------"); while (headers.hasMoreElements()){ String header = headers.nextElement(); System.out.println(header); } Enumeration<String> headerNames = req.getHeaderNames(); System.out.println("================================"); while (headerNames.hasMoreElements()){ String headerName = headerNames.nextElement(); System.out.println(headerName+"...."+ req.getHeader(headerName)); } } } 获取请求参数信息 返回值 方法名 说明 String getParameter(String.name) 根据名称获取数据 String[] getParameterValues(String.name) 根据名称获取所有数据 Enumeration<String> getParameterNames() 获取所有名称 Map<String,String[]> getParameterMap() 获取所有参数的键值对 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.IOException; import java.util.Enumeration; import java.util.Map; @WebServlet(name = "Demo3GetRequestParamter", value = "/demo3GetRequestParamter") public class Demo3GetRequestParamter extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(name+"..."+password); System.out.println("----------------"); String[] hobbies = req.getParameterValues("hobby"); for(String hobby:hobbies){ System.out.println(hobby); } System.out.println("===================="); Enumeration<String> parameterNames = req.getParameterNames(); while (parameterNames.hasMoreElements()){ String pname = parameterNames.nextElement(); System.out.println(pname); } System.out.println("==================="); Map<String, String[]> parameterMap = req.getParameterMap(); for(Map.Entry<String,String[]> parameter : parameterMap.entrySet()){ System.out.print(parameter.getKey()); for(String s:parameter.getValue()){ System.out.print(","+s); } System.out.println(); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } } 获取请求参数并封装对象 手动封装方式 反射封装方式 工具类封装方式 手动封装的方式 ...

September 29, 2021&nbsp;·&nbsp;10 分钟&nbsp;·&nbsp;Lizicai

JavaWeb核心一 Li.054

1. IDEA 创建 JavaWeb 项目 1.1 选择JavaEE 项目 1.2 Project tempate中选择 Web Application 1.3 一路创建 1.4 在Edit Configurations 设置tomcat, 下面为brew 安装的tomcat地址 /usr/local/Cellar/tomcat@9/9.0.53/libexec 1.5 设置On update action: update resources, On frame deactivation: update resources 1.6 设置第二栏Deployment: Application text: /web_demo 1.7 启动tomcat 即可自动在浏览器上预览 2. 打包JavaWeb 项目 2.1 在本地wepapp文件夹内, 使用jar -cvf myweb.war .打包 jar -cvf myweb.war . 2.2 上传到tomcat服务器中的webapps中, 重启tomcat即可看到发布结果 scp myweb.war webserver:tomcat9.0/webapps/ ./shutdown.sh ./startup.sh 3. 更改Tomcat 端口 conf中server.xml 8080更改为80端口 4. 在server.xml中添加其它目录做为tomcat项目 **在Host中间添加 <Context path="/myweb" docBase="/Users/lizicai/IdeaProjects/web_demo/src/main/webapp" /> 访问ip:8080/myweb 即可 ...

September 26, 2021&nbsp;·&nbsp;7 分钟&nbsp;·&nbsp;Lizicai

Linux下Java的JDK安装设置和Tomcat安装 Li.053

1. 卸载原有JDK rpm -qa | grep "java" yum remove 上面筛选内容 2. 下载JDK8, 解压 进入 官网Java JDK8下载地址 右键选择linux x64 jdk-8u301-linux-x64.tar.gz的下载地址 使用wget下载, 并解压 wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" https://download.oracle.com/otn/java/jdk/8u301-b09/d3c52aa6bfa54d3ca74e617f18309292/jdk-8u301-linux-x64.tar.gz tar -zxvf jdk-8u301-linux-x64.tar.gz 3. root用户移动文件, 并设置JAVA_HOME环境变量 3.1 移动文件夹 mv jdk1.8.0_301 /usr/local 3.2 设置JAVA_HOME环境变量 vim /etc/profile 可以对所有用户生效 对当前用户生效则可放在.bashrc中 添加下列信息 export JAVA_HOME=/usr/local/jdk1.8.0_301 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib/dt.JAVA_HOME/lib/tools.jar:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:${PATH} 3.3 重新生效/etc/profile或.bashrc source /etc/profile # source ~/.bashrc 3.4 检测Java安装成功 java -version 弹出java的版本, 即是安装成功 4 Tomcat 安装 4.1 Tomcat官网下载 **以Tomcat 9.0 版本为例 wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.53/bin/apache-tomcat-9.0.53.tar.gz 4.2 解压 tar -zxvf apache-tomcat-9.0.53.tar.gz 4.3 启动Tomcat, 依赖Java 环境设置 cd apache-tomcat-9.0.53/bin/ ./startup.sh 4.4 添加安全组端口, 如腾讯云 阿里云 来源 协议端口 策略 备注 0.0.0.0/0 TCP:8080 允许 tomcat 4.5 添加防火墙端口 firewall-cmd --zone=public --add-port=8080/tcp --permanent firewall-cmd --reload 4.6 浏览器访问 ip:8080 访问http:ip:8080 ...

September 26, 2021&nbsp;·&nbsp;1 分钟&nbsp;·&nbsp;Lizicai

Java的反射 Li.049

反射 反射概述 Java的反射机制是在运行状态中, 对于任意一个类, 都能知道这个类的所有属性和方法 对于任意一个对象, 都能够调用它的任意一个方法和属性 这种动态获取信息以及动态调用对象的方法的功能称为Java语文的反射机制 想要解剖一个类, 必需先要获取到该类的字节码文件对象 而解剖使用的就是Class类中的方法, 所以先要获取到每一个字节码文件对应的Class类型的对象 反射的三种方式 Object烦的getClass()方法, 判断2个对象是否是同一个字节码文件 静态属性class, 锁对象(Person.class) Class类中静态方法forName(), 读取配置文件 import com.lizicai.bean.Person; public class Demo1_Reflect { public static void main(String[] args) throws ClassNotFoundException { Class clazz1 = Class.forName("com.lizicai.bean.Person"); Class clazz2 = Person.class; Person p = new Person(); Class clazz3 = p.getClass(); System.out.println(clazz1 == clazz2); System.out.println(clazz2 == clazz3); } } 反射(Class.forName()读取配置文件举例) import java.io.*; public class Demo2_Reflect { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { // nouseReflect(); String str = null; BufferedReader br = new BufferedReader(new FileReader("config.properties")); str = br.readLine(); Class clazz = Class.forName(str); Fruit f = (Fruit) clazz.newInstance(); Juier j = new Juier(); j.run(f); } private static void nouseReflect() { Juier j = new Juier(); Apple apple = new Apple(); j.run(apple); j.run(new Orange()); } } interface Fruit{ public void squeeze(); } class Apple implements Fruit { @Override public void squeeze(){ System.out.println("苹果汁"); } } class Orange implements Fruit{ @Override public void squeeze(){ System.out.println("橙汁"); } } class Juier{ public void run(Fruit fruit){ fruit.squeeze(); } public void run(Orange orange){ orange.squeeze(); } } com.lizicai.reflect.Orange 通过反射获取带参构造方法并使用 构造函数必须public, 否则报NoSuchMethodException 异常. import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Demo3_Reflect { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class clazz = Class.forName("com.lizicai.bean.Person"); // Person p = (Person) clazz.newInstance(); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("张三",23); System.out.println(p); } } public class Person { private String name; private int age; public Person(String name, int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } @Override public String toString() { return this.getName() + this.getAge(); } } 通过反射获取成员变量并使用 import com.lizicai.bean.Person; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; public class Demo4_Reflect { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class clazz = Class.forName("com.lizicai.bean.Person"); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("张三",23); // Field f = clazz.getField("name"); // 暴力反射 Field f = clazz.getDeclaredField("name"); // 去除私有权限 f.setAccessible(true); f.set(p,"李四"); System.out.println(p); } } 通过反射获取方法并使用 import com.lizicai.bean.Person; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Demo5_Reflect { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException { Class clazz = Class.forName("com.lizicai.bean.Person"); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("张三",23); Method m = clazz.getMethod("eat"); m.invoke(p); Method m2 = clazz.getMethod("eat", int.class); m2.invoke(p,10); } } 通过反射越过泛型检查 泛型编译时检查, 运行时没有检查 import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; public class Test1 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); Class clazz = Class.forName("java.util.ArrayList"); Method m = clazz.getMethod("add",Object.class); m.invoke(list,"test"); System.out.println(list); } } 通过反射写一个通用的设置某个对象的某个属性为指定的值 Person对象仍然是上面的 import java.lang.reflect.Field; public class Tool { public void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException { Class clazz = obj.getClass(); Field f = clazz.getDeclaredField(propertyName); f.setAccessible(true); f.set(obj,value); } } import com.lizicai.bean.Person; public class Test2 { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Person p = new Person("小明",23); System.out.println(p); Tool t = new Tool(); t.setProperty(p,"name","小红"); System.out.println(p); } } 练习 import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test3 { public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { File file = new File("demo.properties"); BufferedReader br = new BufferedReader(new FileReader(file)); String clazzName = br.readLine(); br.close(); Class clazz = Class.forName(clazzName); DemoClass dc = (DemoClass) clazz.newInstance(); Method m = clazz.getMethod("run"); m.invoke(dc); } } public class DemoClass { public void run(){ System.out.println("大王叫我来巡山"); } } com.lizicai.test.DemoClass 动态代理的概述和实现 写好了代理, 就能在所有类前后进行一些处理 public interface User { public void add(); public void delete(); } public class UserImp implements User{ @Override public void add() { // System.out.println("权限校验"); System.out.println("添加"); // System.out.println("日志记录"); } @Override public void delete() { // System.out.println("权限校验"); System.out.println("删除"); // System.out.println("日志记录"); } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限检验"); method.invoke(target,args); System.out.println("日志记录"); return null; } } import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { User ui = new UserImp(); ui.add(); ui.delete(); MyInvocationHandler m = new MyInvocationHandler(ui); User u = (User) Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(),m); u.add(); u.delete(); } } 模版(Template)设计模式概述和使用 模版设计模式概述 模版方法模式就是定义一个算法模版, 而将具体的算法延迟到子类中实现 优点 缺点 使用模版方法模式, 在定义骨架的同时, 可以很灵活实现具体的方法, 满足用户灵活多变的需求 如果算法有修改, 则需要修改抽象类 public class Demo1_Template extends TestTime{ public static void main(String[] args) { Demo1_Template d = new Demo1_Template(); System.out.println(d.getTime()); } @Override public void code() { for(int i=0;i<100000;i++){ System.out.println(i); } } } abstract class TestTime{ final public long getTime(){ long start = System.currentTimeMillis(); code(); long end = System.currentTimeMillis(); return end - start; } public abstract void code(); } 自己实现枚举类 概述 是指将变量的值一一列举出来, 变量的值仅限于列举出来的值的范围内 单例模式, 只有一个实例 多例类就是一个类有多个实例, 但不是无限多个实例, 是有限个数的实例, 这才是枚举类. 枚举类有下例3种形式 public class Week { final static Week MON = new Week(); final static Week TUE = new Week(); final static Week WED = new Week(); private Week(){} } public class Week2 { final static Week2 MON = new Week2("星期一"); final static Week2 TUE = new Week2("星期二"); final static Week2 WED = new Week2("星期三"); String name; private Week2(String name){ this.name = name; } @Override public String toString() { return this.name; } } public abstract class Week3 { final static Week3 MON = new Week3("星期一"){ @Override public void show() { System.out.println("星期一"); } }; final static Week3 TUE = new Week3("星期二"){ @Override public void show() { System.out.println("星期二"); } }; final static Week3 WED = new Week3("星期三") { @Override public void show() { System.out.println("星期三"); } }; String name; private Week3(String name){ this.name = name; } @Override public String toString() { return this.name; } public abstract void show(); } public class Demo1_Enum { public static void main(String[] args) { Week mon = Week.MON; System.out.println(mon); Week2 Mon = Week2.MON; Week2 Tue = Week2.TUE; Week2 Wed = Week2.WED; System.out.println(Mon); System.out.println(Tue); System.out.println(Wed); Week3 MON = Week3.MON; Week3 TUE = Week3.TUE; Week3 WED = Week3.WED; MON.show(); TUE.show(); WED.show(); } } 通过enum实现枚举类 public enum Week { MON,TUE,WED; } public enum Week2 { MON("星期一"),TUE("星期二"),WED("星期三"); private String name ; Week2(String name){ this.name = name; } public String getName() { return name; } } public enum Week3 { MON("星期一"){ @Override public void show() { System.out.println("星期一"); } },TUE("星期二"){ @Override public void show() { System.out.println("星期二"); } },WED("星期三"){ @Override public void show() { System.out.println("星期三"); } }; private String name ; Week3(String name){ this.name = name; } public String getName() { return name; } public abstract void show(); } public class Demo1_Enum { public static void main(String[] args) { Week mon = Week.MON; Week tue = Week.TUE; System.out.println(mon); System.out.println(tue); Week2 Mon = Week2.MON; Week2 Tue = Week2.TUE; System.out.println(Mon); System.out.println(Tue.getName()); Week3 MON = Week3.MON; Week3 TUE = Week3.TUE; Week3 WED = Week3.WED; System.out.println(MON); System.out.println(TUE.getName()); System.out.println(WED.getName()); } } switch 使用枚举 public static void demo1(){ Week2 MON = Week2.TUE; switch (MON){ case MON: System.out.println("星期一"); break; case TUE: System.out.println("星期二"); break; case WED: System.out.println("星期三"); break; } } 常用的枚举方法 public final int ordinal() 获取枚举的位置 public final int compareTo(E o) 比较枚举位置, 返回差 public final String name() 获取枚举实例的名字 public static <T extends Enum> T valueOf(Class enumType, String name) 字节码对象获取枚举项 values 获取枚举的数组 public class Demo2_Enum { public static void main(String[] args) { Week2 mon = Week2.MON; Week2 tue = Week2.TUE; Week2 wed = Week2.WED; System.out.println(mon.ordinal()); System.out.println(tue.ordinal()); System.out.println(wed.ordinal()); System.out.println(mon.compareTo(tue)); System.out.println(mon.compareTo(wed)); System.out.println(mon.name()); System.out.println(tue.name()); System.out.println(mon); System.out.println(tue.toString()); // 字节码对象获取枚举项 Week2 TUE = Week2.valueOf(Week2.class,"TUE"); System.out.println(TUE); Week2[] arr = Week2.values(); for(Week2 w:arr){ System.out.println(w); } } } JDK 1.7 新增内容 switch支持字符串 异常catch多个异常, 用|隔开 try-whith-resources 自动关流 import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class Demo3_AutoClose { public static void main(String[] args) { File file = new File("config.properties"); //资源放在try()中, 会自动关闭资源, 不用在finally 中关闭了 try ( FileInputStream fis = new FileInputStream(file)){ int b; while ( ( b = fis.read() ) != -1){ System.out.println(b); } } catch (IOException e){ System.out.println(e.getMessage()); } } } JDK 1.8 新增内容 接口可以支持default修饰, 有方法体 接口也可以有静态方法了 内部类可访问的变量默认是final修饰 public class Demo4_JKD18 { // JDK1.8新特性 public static void main(String[] args) { Demo d = new Demo(); d.show(); Inter.test(); d.run(); } } interface Inter{ public default void show(){ System.out.println("显示"); } public static void test(){ System.out.println("测试"); } } class Demo implements Inter{ public void run(){ // num 默认是final int num = 20; class Inner{ public void fun(){ System.out.println("fun"); } } Inner i = new Inner(); i.fun(); } }

September 19, 2021&nbsp;·&nbsp;7 分钟&nbsp;·&nbsp;Lizicai

Java的网络编程 Li.048

网络通信 ip 电脑地址 UDP TCP 端口号 socket 插座, 数据流间的插座, 用来联通 类似电脑是港口ip, socket是航线用来发货, 端口号是港口停放船的泊位, UDP TCP是小船还是大船来运送数据箱子 DatagramSocket 与 DatagramPacket DatagramSocket 创建一条航线 DatagramPacket 指定电脑ip(港口), 端口号(泊位), 运送的数据(集装箱) import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; public class Demo1_Send { public static void main(String[] args) throws IOException { String msg = "中午一起吃饭"; DatagramSocket datagramSocket = new DatagramSocket(); DatagramPacket datagramPacket = new DatagramPacket (msg.getBytes(StandardCharsets.UTF_8),msg.getBytes().length, InetAddress.getByName("127.0.0.1"),2000); datagramSocket.send(datagramPacket); datagramSocket.close(); } } import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class Demo2_Receive { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(2000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println(new String(arr,0,len)); socket.close(); } } 能够不断录入的版本 import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class Demo3_Send { public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); DatagramSocket datagramSocket = new DatagramSocket(); while (true){ String msgLine = sc.nextLine(); if( "quit".equals(msgLine)){ break; } System.out.println(msgLine); DatagramPacket packet = new DatagramPacket (msgLine.getBytes(StandardCharsets.UTF_8), msgLine.getBytes().length, InetAddress.getByName("127.0.0.1"), 2000); datagramSocket.send(packet); } datagramSocket.close(); } } import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class Demo3_Receive { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(2000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while (true){ socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println("信息" + new String(arr,0,len)); } } } 多线程发送和接收信息 import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class Demo4_MoreThread { public static void main(String[] args) { MyReceive myReceive = new MyReceive(); MySend mySend = new MySend(); myReceive.start(); mySend.start(); } } class MyReceive extends Thread{ @Override public void run() { try { DatagramSocket socket = null; socket = new DatagramSocket(2000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while (true){ socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println("信息" + new String(arr,0,len)); } } catch (IOException e) { e.printStackTrace(); } } } class MySend extends Thread{ @Override public void run() { Scanner sc = new Scanner(System.in); DatagramSocket datagramSocket = null; try { datagramSocket = new DatagramSocket(); while (true){ String msgLine = sc.nextLine(); if( "quit".equals(msgLine)){ break; } DatagramPacket packet = new DatagramPacket (msgLine.getBytes(StandardCharsets.UTF_8), msgLine.getBytes().length, InetAddress.getByName("127.0.0.1"), 2000); datagramSocket.send(packet); } } catch (IOException e) { e.printStackTrace(); } datagramSocket.close(); } } GUI 聊天 import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; public class Demo5_GUIChat extends Frame{ private TextField textField; private TextArea viewText; private TextArea sendText; private Button send; private Button log; private Button clear; private Button shake; private DatagramSocket socket; // private BufferedReader br; private FileInputStream fis; private BufferedWriter bw; public Demo5_GUIChat() throws SocketException,IOException{ init(); southPanel(); centerPanel(); event(); Receive r = new Receive(); r.start(); this.setVisible(true); } public void event() { this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { try { bw.close(); } catch (IOException ex) { ex.printStackTrace(); } socket.close(); System.exit(0); } }); send.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { send(); } catch (SocketException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } }); log.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { logFile(); } catch (IOException ex) { ex.printStackTrace(); } } }); clear.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { viewText.setText(""); } }); shake.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // shake(); try { send(new byte[]{-1},textField.getText()); } catch (IOException ex) { ex.printStackTrace(); } } }); sendText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ENTER ){ try { send(); } catch (IOException ex) { ex.printStackTrace(); } } } }); } public void shake(){ int x = this.getX(); int y = this.getY(); for(int i=0;i<20;i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(i % 2 == 0){ this.setLocation(x+3,y+3); } else { this.setLocation(x,y); } } } public void logFile() throws IOException { // br = new BufferedReader(new InputStreamReader(new FileInputStream("chat.log"))); // br = new BufferedReader(new FileReader("chat.log")); // viewText.setText(""); // int len ; // char [] arr = new char[1024]; // while ( ( len =br.read(arr)) != -1){ // viewText.append(new String(arr,0,len)); // } // br.close(); fis = new FileInputStream("chat.log"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int len; byte[] arr = new byte[8192]; while ( (len = fis.read(arr)) != -1){ bos.write(arr,0,len); } viewText.setText(bos.toString()); bos.close(); } public void send(byte[] arr,String ip) throws IOException { DatagramPacket packet = new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), 9999); socket.send(packet); } public void send() throws IOException { String msg = sendText.getText(); if( "".equals(msg.trim()) || null ==msg){ return; } else { String ip = textField.getText(); if( ip.equals(null) || ip.trim().equals("")){ ip = "255.255.255.255"; } String time = getTime(); send(msg.getBytes(StandardCharsets.UTF_8),ip); String chatlog = time+" "+"我对:"+(ip.equals("255.255.255.255")? "所有人":ip)+"说:"+"\n"+ msg +"\n"+"\n"; viewText.append(chatlog); bw.write(chatlog); bw.flush(); sendText.setText(""); } } public String getTime(){ Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); return sdf.format(date); } public void centerPanel() { Panel center = new Panel(); viewText = new TextArea(); sendText = new TextArea(5,2); viewText.setEditable(false); viewText.setBackground(Color.WHITE); center.setLayout( new BorderLayout()); center.add(sendText, BorderLayout.SOUTH); center.add(viewText, BorderLayout.CENTER); sendText.setFont(new Font("xxx", Font.PLAIN,20)); viewText.setFont(new Font("xxx", Font.PLAIN,16)); this.add(center, BorderLayout.CENTER); } public void southPanel() { Panel south = new Panel(); textField = new TextField(15); textField.setText("127.0.0.1"); send = new Button("发送"); log = new Button("记录"); clear = new Button("清除"); shake = new Button("振动"); south.add(textField); south.add(send); south.add(log); south.add(clear); south.add(shake); this.add(south, BorderLayout.SOUTH); } private void init() throws IOException { this.setLocation(500,10); this.setSize(500,800); socket = new DatagramSocket(); // bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("chat.log",true))); bw = new BufferedWriter(new FileWriter("chat.log",true)); } public static void main(String[] args) throws SocketException,IOException { Demo5_GUIChat guiChat = new Demo5_GUIChat(); } private class Receive extends Thread{ //发送 接收同时进行 @Override public void run() { try { DatagramSocket socket = new DatagramSocket(9999); DatagramPacket packet = new DatagramPacket(new byte[8192], 8192); while (true){ socket.receive(packet); byte[] arr = packet.getData(); int length = packet.getLength(); if( length == 1 && arr[0] == -1){ shake(); continue; } String msg = new String(packet.getData(), 0, packet.getLength()); String chatlog = getTime()+" "+textField.getText()+" "+"对我说:"+"\n"+msg+"\n\n" ; viewText.append(chatlog); bw.write(chatlog); bw.flush(); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } } TCP协议 (重要) TCP 三次握手 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); Socket socket = server.accept(); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); os.write("明天还上班不".getBytes(StandardCharsets.UTF_8)); byte[] arr = new byte[8192]; int len; len = is.read(arr); System.out.println(new String(arr,0,len)); } } import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.nio.charset.StandardCharsets; public class Demo1_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); byte[] arr = new byte[8192]; int len = is.read(arr); os.write("吃了".getBytes(StandardCharsets.UTF_8)); System.out.println(new String(arr,0,len)); } } 服务端 客户端TCP 优化 import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); Socket socket = server.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); OutputStream out; PrintStream ps = new PrintStream(socket.getOutputStream()) ; ps.println("快乐, 放假了"); System.out.println(br.readLine()); ps.println("出来玩吧"); System.out.println(br.readLine()); } } import java.io.*; import java.net.Socket; public class Demo2_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()) ; System.out.println( br.readLine()); ps.println("是的, 放假了"); System.out.println( br.readLine()); ps.println("起飞"); } } 服务增加多线程 import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); while (true){ final Socket socket = server.accept(); new Thread(){ @Override public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); OutputStream out; PrintStream ps = new PrintStream(socket.getOutputStream()) ; ps.println("快乐, 放假了"); System.out.println(br.readLine()); ps.println("出来玩吧"); System.out.println(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } } 服务端反转字符并写给客户端 import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Demo3_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); while (true){ final Socket socket = server.accept(); new Thread(){ @Override public void run() { while (true){ try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()) ; StringBuilder sb = new StringBuilder( br.readLine()); ps.println(sb.reverse()); } catch (IOException e) { e.printStackTrace(); } } } }.start(); } } } import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class Demo3_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()) ; Scanner sc = new Scanner(System.in); String s = null; while (true){ s = sc.nextLine(); ps.println(s); System.out.println( br.readLine()); } } } 上传文件到服务端 import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Demo4_Server_SaveFiles { public static void main(String[] args) throws IOException{ ServerSocket server = new ServerSocket(2000); while (true){ final Socket socket = server.accept(); new Thread(){ @Override public void run() { while (true){ try { InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream(socket.getOutputStream()) ; File dir = new File("update"); if(!dir.exists()){ dir.mkdir(); } String fileName = br.readLine(); System.out.println(fileName); File file = new File(dir, fileName); if( file.exists()){ ps.println("已存在"); return; }else { ps.println("不存在"); } byte[] arr = new byte[8192]; int len; FileOutputStream fos = new FileOutputStream(file); while ( ( len = is.read(arr)) != -1){ fos.write(arr,0,len); } fos.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }.start(); } } } import java.io.*; import java.net.Socket; import java.util.Scanner; public class Demo4_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream(socket.getOutputStream()) ; Scanner sc = new Scanner(System.in); String s = null; int len; byte[] arr = new byte[8192]; while (true){ s = sc.nextLine(); File file = new File(s); if( !file.exists()){ System.out.println("文件不存在"); } else if( file.isDirectory()){ System.out.println("文件夹, 请重新输入文件"); } else if (file.isFile()){ ps.println(s); String flag = br.readLine(); if( "已存在".equals(flag)){ System.out.println(flag); return; } else { InputStream inputStream = new FileInputStream(file); while ( (len = inputStream.read(arr)) != -1){ ps.write(arr,0,len); } ps.flush(); } } } } }

September 17, 2021&nbsp;·&nbsp;8 分钟&nbsp;·&nbsp;Lizicai

Java的多线程二 Li.047

单例设计模式(重要) 保证类在内存中只有一个对象 饿汉式, 空间换时间, 类创建的时候就创建对象, 线程安全的 懒汉式, 双叫单例加载模式, 使用的时候才创建对象, 存在线程安全问题 区别, 饿汉式空间换时间, 懒汉式时间换空间, 多线程访问时, 饿汉式不会创建多个对象, 懒汉式可能创建多个对象 public class Demo1_Singleton { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1); System.out.println(s2 == s1); } } class Singleton{ // 1. 私有化构造函数, 就不能随意实例类了 private Singleton (){} // 2. 创建实例 private static Singleton s = new Singleton(); // 3. 饿汉式 public static Singleton getInstance() { return s; } } class SingletonLazy{ private SingletonLazy (){} private static SingletonLazy s ; public static SingletonLazy getInstance() { if(s == null){ s = new SingletonLazy(); } return s; } } class SingletonFinal{ private SingletonFinal(){} public static final SingletonFinal s = new SingletonFinal(); } Runtime 类 Process exec(String command) throws IOException 执行命令 import java.io.IOException; public class Demo2_Runtime { public static void main(String[] args) throws IOException { Runtime runtime = Runtime.getRuntime(); runtime.exec("ls"); } } Timer ( 可以被ScheduledExecutorService取代 ) 一种工具, 线程用其安排以后在后台线程中执行的任务, 可安排任务执行一次, 或者定期重复执行 private static void demo1() { Timer t = new Timer(); // t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01); // 定时 执行 // 循环执行, 每3秒执行一次 t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01),3000); while (true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date()); } } ScheduledExecutorService Time的缺陷, 单线程多个任务排队, 一个任务执行时间长了, 后面任务受影响, 一个任务挂了, 后面的任务无法执行, 强依赖系统时间, 系统时间更改则会更改 ScheduledExecutorService 多线程, 则没有上述问题 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) 延时initialDelay, 开始周期delay执行 import java.util.Date; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Demo3_Timer { public static void main(String[] args) throws InterruptedException { // 一个任务出现 异常, 不影响其他任务 ScheduledExecutorService ses = Executors.newScheduledThreadPool(2); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("===" + Thread.currentThread().getName() + "==="); } } , 0, 3, TimeUnit.SECONDS); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { int i = 1/0; System.out.println("***" + Thread.currentThread().getName() + "***"); } } , 0, 3, TimeUnit.SECONDS); } private static void demo2(){ // 一个任务执行时间长了, 也不会任务其他任务 ScheduledExecutorService ses = Executors.newScheduledThreadPool(2); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("===" + Thread.currentThread().getName() + "==="); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } , 0, 3, TimeUnit.SECONDS); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("***" + Thread.currentThread().getName() + "***"); } } , 0, 3, TimeUnit.SECONDS); } private static void demo1() { Timer t = new Timer(); // t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01); // 定时 执行 // 循环执行, 每3秒执行一次 t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01),3000); while (true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date()); } } } class MyTimerTask extends TimerTask{ @Override public void run() { System.out.println("起来上班"); } } 多个线程的通信(重要) this.notify() 随机唤醒单个等待线程 public class Demo1_Notify { public static void main(String[] args) { Printer p = new Printer(); new Thread(){ @Override public void run() { while (true){ try { p.method1(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true){ try { p.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } class Printer{ private int flag = 1; public void method1() throws InterruptedException { synchronized (this){ if(flag != 1){ this.wait(); } System.out.println("aaaa"); flag = 2; this.notify(); } } public void method2() throws InterruptedException { synchronized (this){ if(flag != 2){ this.wait(); } System.out.println("bbbbbbbb"); flag = 1; this.notify(); } } } 三个或三个以上间的线程通信 public class Demo2_Notify3 { public static void main(String[] args) { Printer2 p = new Printer2(); new Thread(){ @Override public void run() { while (true){ try { p.method1(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true){ try { p.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true){ try { p.method3(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } class Printer2{ private int flag = 1; public void method1() throws InterruptedException { synchronized (this){ while (flag != 1){ this.wait(); } System.out.println("aaaa"); flag = 2; this.notifyAll(); } } public void method2() throws InterruptedException { synchronized (this){ while (flag != 2){ this.wait(); } System.out.println("bbbbbbbb"); flag = 3; this.notifyAll(); } } public void method3() throws InterruptedException { synchronized (this){ while (flag != 3){ this.wait(); } System.out.println("cccccccccccccc"); flag = 1; this.notifyAll(); } } } 线程间通信注意的问题 1.在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法 2.为什么wait方法和notify方法定义在Object这类中? 因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中 3.sleep方法和wait方法的区别? a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来 wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待 b,sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡 wait方法在同步函数或者同步代码块中,释放锁 互斥锁(重要) ReentrantLock Condition import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Demo3_ReentrantLock { public static void main(String[] args) { Printer3 p = new Printer3(); new Thread(){ @Override public void run() { while (true) { try { p.method1(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true) { try { p.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true) { try { p.method3(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } class Printer3{ private int flag = 1; private ReentrantLock r = new ReentrantLock(); Condition c1 = r.newCondition(); Condition c2 = r.newCondition(); Condition c3 = r.newCondition(); public void method1() throws InterruptedException { r.lock(); if (flag != 1){ c1.await(); } System.out.println("aaaa"); flag = 2; c2.signal(); r.unlock(); } public void method2() throws InterruptedException { r.lock(); if (flag != 2){ c2.await(); } System.out.println("bbbbbbbb"); flag = 3; c3.signal(); r.unlock(); } public void method3() throws InterruptedException { r.lock(); if(flag != 3){ c3.await(); } System.out.println("cccccccccccccc"); flag = 1; c1.signal(); r.unlock(); } } 线程组 public class Demo4_ThreadGroup { public static void main(String[] args) { // demo1(); ThreadGroup threadGroup = new ThreadGroup("自造线程组"); Mythread mythread = new Mythread(); Runnable target; Thread t1 = new Thread(threadGroup, mythread); Thread t2 = new Thread(threadGroup,mythread,"线程1"); Thread t3 = new Thread(threadGroup,mythread,"线程2"); System.out.println(t1.getName()); System.out.println(t2.getName()); System.out.println(t3.getName()); System.out.println(t1.getThreadGroup().getName()); System.out.println(t2.getThreadGroup().getName()); System.out.println(t3.getThreadGroup().getName()); System.out.println(t1.getThreadGroup().getParent().getName()); } private static void demo1() { Mythread mythread = new Mythread(); Thread t1 = new Thread(mythread); Thread t2 = new Thread(mythread); ThreadGroup tg1 = t1.getThreadGroup(); ThreadGroup tg2 = t2.getThreadGroup(); System.out.println(tg1.getName()); System.out.println(tg2.getName()); } } class Mythread implements Runnable{ @Override public void run() { } } 线程的5种状态 新建线程.start() -> 线程就绪状态, 有执行权->抢到CPU执行权限执行->死亡状态, run执行完了 抢到CPU执行权限执行->wait或sleep线程阻塞->叫醒线,程线程就绪状态, 有执行权 线程池 程序创建一个线程成本比较高, 为了方便使用线程池, 使用后再返给JVM import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo5_Executors { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(2); pool.submit(new Mythread()); pool.submit(new Mythread()); pool.shutdown(); } } 实现Callable的线程 import java.util.concurrent.*; public class Demo6_Callable { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(2); Future<Integer> f1 = pool.submit(new MyCallable(10)); Future<Integer> f2 = pool.submit(new MyCallable(20)); System.out.println(f1.get()); System.out.println(f2.get()); pool.shutdown(); } } class MyCallable implements Callable<Integer>{ private int num; public MyCallable(int num){ this.num = num; } @Override public Integer call() throws Exception { int sum = 0; for(int i=1;i<num;i++){ sum = sum + i; } return sum; } } 简单工厂模式 概述 静态工厂方法模式, 它定义一个具体的工厂类负责创建一些类的实例 优点 客户端不负责对象的创建, 从而明确各类的职责 缺点 静态工厂负责所有类的创建, 如果有新的对象或者新对象创建方式不同, 就需要不断修改工厂类, 不利于后期维护. public abstract class Animal { public void eat(){}; } public class AnimalFactory { public static Dog createDog(){ return new Dog(); } public static Cat createCat(){ return new Cat(); } public static Animal createAnimal(String animal){ if( "dog".equals(animal)){ return new Dog(); } else if( "cat".equals(animal)){ return new Cat(); } return null; } } public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } } public class Dog extends Animal{ @Override public void eat() { System.out.println("单身狗儿吃狗粮"); } } `` ...

September 12, 2021&nbsp;·&nbsp;9 分钟&nbsp;·&nbsp;Lizicai