【javaWeb项目】基于网页形式,通过浏览器访问的java应用程序,就称为javaweb程序

news/2024/9/22 22:54:22/

JavaWeb前端

第一章

1、javaWeb是什么

java">	//基于网页形式,通过浏览器访问的java应用程序,就称为javaweb程序

2、web程序的分类

java">	//1、静态web程序特点:网页上的内容是固定不变的,不能动态加载,例如web前端//2、动态web程序特点:1、页上的内容可以根据请求的不同,动态加载数据,例如javaweb程序2、动态web程序可以与用户动态交互3、企业开发涉及到的应用程序主要是动态web程序

3、不同点

	1、静态web无法与用户动态加载数据,动态web程序则可以与用户交互,根据请求加载不同数据2、静态web程序用浏览器打开页面即可直接运行,web动态程序必须在一个特定的环境中才能运行,环境称为web容器(web服务器)

4、web服务器

web服务器用于给web程序提供一个运行环境,只要将web程序(静态或动态都可以)放入到web服务器中,就能通过网络进行访问常用服务器:
1、tomcat/*应用最多*/
2、jboss
3、weblogic
......Tomcat的特点:1、tomcat免费2、不需要解压缩,配置简单3、小巧灵活
tomacat版本tomacat版本需要与jdk版本对应,jdk是1.8,推荐8.5的版本

5、开发工具

idea的版本以年份为版本:个人推荐2018.2

6、idea使用

1、psvm----生成主函数main
2、sout----输出语句
3、alt+insert------生成get,set,tostring//右键 grnreate
4、选中报错位置,然后alt-----处理异常

在这里插入图片描述

get set tostring

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

推荐插件: rainbow(彩虹)

​ 作用:如果代码有很多括号,每一对括号的颜色不同

7、idea的相关设置

1、局部设置--只对当前空间有效,切换项目需要重新配置
2、全局配置---配置一次,对所有项目都有效(推荐)

8、tomcat服务器配置文件

要将项目部署到tomcat中,只需要把项目拷贝到tomcat/webapps目录下即可
在这里插入图片描述

9、启动tomcat服务器

	1、单独启动tomcat,不借助idea//找到tomcat的文件位置 进入bin 启动startup.bat  停止shutdown.bat注意:如果启动了tomcat就不能再次启动,否则会报错如果tomcat无法启动,原因是没有配置Java_HOME变量
	2、在idea中启动服务器Web项目的目录结构:src:存放java原文件web:存放html,jsp,css,img,jsWEB-INFweb.xml-------------核心配置文件lib-----------------放依赖,也就是jar

第二章

主要内容:jsp的基本应用 servlet的使用

jsp_147">1、HTML页面与jsp页面有什么区别
主要区别:1、HTML是静态页面,无法动态加载数据,不能与用户交互2jsp的动态页面,可以加载数据,能交互jsp的本质:jsp:Java server page它是由运行服务器端的java程序动态生成的页面jsp本质上是一个java类,只不过它是以页面的形式呈现数据
2、简易登录案例

如果要在jsp页面编写java代码,只需要在页面写下标记

java"><%java脚本
%>
java脚本的作用,用于在jsp页面中嵌入java代码  

重要方法

1、设置编码格式

默认情况下,表单提交数据会采用latin文编,格式为iso-8859-1,这种不支持中文解决方案:在取值之前,设置请求(request)的编码格式request.setCharacterEncoding("utf-8");//在取值之前设置string name=request.getParameter("user");

2、获取表单数据

获取表单提交的数据string val=request.getParameter("表单中控件的name的名称")//request:请求//Parameter:参数示例:string name=request.getParameter("user");//获取表单中的用户名System.out.println("姓名"+name);//输出到控制台out.println("姓名"+name+"<br>");//输出到页面//br:换行显示

3、跳转页面

	跳转页面的方法(固定写法)request.getRequestDispatcher("/xxx.jsp").forward(request,response)

4、存储

存值将数据存储在request中,跳转页面中可以取到存储的数据request.setAttribte("消息的key",);//键:必须是字符串类型//值:可以为任意类型(string 对象 集合)示例:request.setAttribte("err","用户或密码错误");取值在jsp页面中,获得存储request中的消息要获得存储在request中的数据,显示在页面,我们需要使用"EL表达式"格式:${消息的key}示例:${err}

5、使用request没有提示,是因为没有导包
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

jspI_262">3、jsp模型I

如果jsp页面即作为视图组件与用户交互,又作为控制器组件处理程序流程,这样的架构称为jsp模型

jsp模型缺点:视图显示与流程控制的代码都是在jsp页面中完成,随着功能的增加,可读性变差

搞错了,数据库被遗忘了,等我看完数据库再回来看

2023.4.14 学完数据库归来

开发中提供一种:“单一性原则”,一个组件只做一件事为了解决该问题,jsp提供了另一种模型:“jsp模型2
jspII_283">4、jsp模型II

jsp模型II中,jsp只作为视图组件呈现界面与用户交互,它不在作为控制器,控制程序流程

程序中的控制器组件由一个java类:servlet类servlet作为控制器类,用于控制程序

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5、servlet

什么是servlet?

servlet是一个运行在服务端的java组件,它一般作为控制器,用于接受用户的请求,对请求做出响应响应:根据请求处理的不同结果,呈现不同的页面给客户端
6、servlet配置方式

方式1:采用注释

@webServlet("/login")

方式2:隐射的方式

java">    <servlet><!--3、匹配别名--><servlet-name>abc</servlet-name><!--4、找到对应的servlet进行处理--><servlet-class>com.arjunna.web.loginServlet</servlet-class></servlet><servlet-mapping><!--2、生成别名--><servlet-name>abc</servlet-name><!--1、配置映射,指定如何匹配请求--><url-pattern>/first</url-pattern></servlet-mapping>

在这里插入图片描述

第三章 servlet

1、一个类要成为servlet必须满足下列条件

1、servlet必须是HttpServlet的子类2、必须重写父类的doGet或doPost方法,运行重写两个,最少一个如果请求方式是get会进入doget如果请求方式是post会进入doPost3、方法必须接受两个参数HttpServletRequest	-------请求对象通过它可以获得与本次请求相关的所有信息HttpServletResponse	-------响应对象通过它可以执行与响应相关的操作4、方法必须要抛出两种异常ServletExceptionIoException

普通类成为servlet处理请求的要求:

在这里插入图片描述

2、配置servlet

I、在web.xml中配置
    <servlet><!--3、匹配别名-->
<servlet-name>abc</servlet-name> 第三步<!--4、找到对应的servlet进行处理-->第四步<servlet-class>com.arjunna.web.loginServlet</servlet-class></servlet><servlet-mapping><!--2、生成别名--><servlet-name>abc</servlet-name>  第二步<!--1、配置映射,指定如何匹配请求--> 第一步<url-pattern>/first</url-pattern></servlet-mapping>
II、采用注解配置
java">@webServlet("/login")
public class loginServlet extends HttpServlet {
}

3、servlet将数据输出显示在控制台

java"> request.setCharacterEncoding("UTF-8");--只能处理表单提交数据的乱码//        设置响应的编码格式,防止输出流产生中文乱码response.setContentType("text/html;charset=utf-8");//产生输入流,用于将数据显示在客户端浏览器上PrintWriter out =response.getWriter();//输出内容到客户端浏览器out.write("<h1>你好,世界</h1>");//刷新流,保证所有内容都可以被输出out.flush();//关闭流out.close();

4、解决中文乱码

如果表单提交的数据有中文,会产生乱码request.setCharacterEncoding("UTF-8");String xx=request.getParameter("xx");如果用流输入的内容有中文response.setContentType("text/html;charset=utf-8");PrintWriter out =response.getWriter();

5、有哪些方式进入servlet

只要表单可以发送post请求

I、表单提交可以进入servlet
默认get方式,但这种不安全,所有信息会显示在地址栏中建议采用method="post"表单提交时既可以发送get请求,也可以发送post请求
II、超链接可以进入servlet
jsp">超链接只能发送get请求,只能进入doGet方法
<a href="second">超链接</a>
III、直接在浏览器地址中输入请求名
这种只能发送get请求
jspforward_467">IIII、通过jsp:forward标签跳转
jsp"><jsp:forward page="first">在jsp页面中,只要遇到此标记,系统就会自动发出请求进行跳转这种方式只能发送get请求

6、向servlet传递参数的方式

I、表单提交传递参数
<form action="login" method="post">姓名:<input type="text" name="user"><br>密码:<input type="password" name="pwd"><br><input type="submit" value="提交">
</from>
II、超链接传递参数
java">1、超链接传递一个参数<a href="请求名称?参数名=值">超链接</a><a href="second?id=1">在servlet中取参数的写法是String val=request.getParameter("参数名");String id=request.getParameter("id");注意:?只能用一次2、超链接传递多个参数要求:第一个参数用?连接,后面的所有参数都要&连接<a href="请求名称?参数名1=值&参数名2=值">超链接</a><a href="second?id=12&name=jack">在servlet中取参数的写法是String val=request.getParameter("参数名");String id=request.getParameter("id");String name=request.getParameter("name");

7、处理增删改查

I、针对每一个操作编写一个servlet进行处理
		<a href="add">增加<a><a href="del">删除<a><a href="update">修改<a><a href="sel">查询<a>这种写法会导致产生大量冗余代码
不会使用的
II、将增删改查写在同一个servlet类中
一般servlet中仅包含doGet与doPost方法,如果要包含其他方法,其他方法的格式要满足下列条件:protected void 方法名(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		    IOException {}只有方法名可以自己写
解决方案:所有请求先进入doGet方法或doPost方法,用户要调用哪一个方法,就把该方法名称,作为参数传递进来,取到该参数然后手动调用自定义方法
jsp">		<a href="op?method=add">增加<a><a href="op?method=del">删除<a><a href="op?method=update">修改<a><a href="op?method=sel">查询<a>
java">package com.arjunna.web;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("/op")
public class opServlet extends HttpServlet {protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//调用doPost方法doPost(request,response);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//设置编码格式request.setCharacterEncoding("UTF-8");//接受参数的值String op=request.getParameter("method");//判断switch (op){case "add":add(request,response);break;case "del":del(request,response);break;case "update":update(request,response);break;case "sel":sel(request,response);break;}}protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("添加");}protected void del(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("删除");}protected void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("修改");}protected void sel(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("查询");}}

在这里插入图片描述

java_633">8、java中的反射机制

我们希望servlet类中的每一个方法,可以自动调用,不再手动判断,手动调用
答:要实现这个效果,我们可以通过java中的反射机制来实现
I、反射的使用
作用:JAVA反射机制是在运行状态中对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
II、什么是反射
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
III、要执行反射的前提条件
要对一个对象进行反射操作,前提条件是要获得当前类字节码文件所应的对象Class
IIII、获得class的三种方式
java">    //方式1:直接获取public void one(){Class clazz= userInfo.class;System.out.println(clazz);}//方式2:通过类的实例获得class对象public void two(){userInfo user=new userInfo();Class clazz= user.getClass();System.out.println(clazz);}//方式3:通过类的全路径获取classpublic void three() throws ClassNotFoundException {Class clazz= Class.forName("com.arjunna.enty.userInfo");System.out.println(clazz);}
IIIII、通过class对象,获得类中的属性
java">  
//区分修饰符
public void one(){//获得class对象Class clazz= userInfo.class;//通过class获得当前类中的属性(字段:field)//此方法只能获得类中public修饰的属性Field[] arrs=clazz.getFields();for(Field f:arrs){System.out.println(f.getName());}}-----------------------------------------------
//不区分修饰符public void two(){//获得class对象Class clazz= userInfo.class;//通过class获得当前类中的属性(字段:field)//此方法获得所有声明的属性(不区分修饰符)Field[] arrs=clazz.getDeclaredFields();for(Field f:arrs){System.out.println(f.getName());}}
IIIIII、通过class获得类中的方法
java">    //获取当前类以及上一级类中的所有方法(不区分修饰符)public void one(){//获得class对象Class clazz= userInfo.class;//获得类中的方法Method[] methods=clazz.getMethods();for (Method method:methods){System.out.println(method.getName());}}-----------------------------------------------//获得当前类的所有方法(不区分修饰符)public void two(){//获得class对象Class clazz= userInfo.class;//获得类中的方法Method[] methods=clazz.getDeclaredMethods();for (Method method:methods){System.out.println(method.getName());}}-----------------------------------------------//根据方法名,获得类中的指定方法(不带参数)public void there() throws NoSuchMethodException {//获得class对象Class clazz= userInfo.class;//获得类中的方法Method methods=clazz.getDeclaredMethod("getPwd");System.out.println(methods.getName());}-----------------------------------------------//根据方法名,获得类中的指定方法(带参数)public void four() throws NoSuchMethodException {//获得class对象Class clazz= userInfo.class;//获得类中的方法Method methods=clazz.getDeclaredMethod("test", int.class, String.class);System.out.println(methods.getName());}
IIIIIII、通过class对象执行类中的指定方法
java">    //执行类中的public方法public void one() throws Exception {//获得class对象Class clazz= userInfo.class;//获得要执行的public的方法Method method=clazz.getDeclaredMethod("add");//通过class获得当前类的实例Object obj=clazz.newInstance();//在对象上执行特定的方法method.invoke(obj);}-----------------------------------------------//默认情况下,只能访问public方法,如果要访问其他修饰符,需要进行暴力反射public void two() throws Exception {//获得class对象Class clazz= userInfo.class;//获得要执行的public的方法Method method=clazz.getDeclaredMethod("del");//通过class获得当前类的实例Object obj=clazz.newInstance();//配置暴力反射(忽略访问修饰符,强制调用方法)method.setAccessible(true);//在对象上执行特定的方法method.invoke(obj);}-----------------------------------------------(重点关注)//执行类中的带参方法public void there() throws Exception {//获得class对象Class clazz= userInfo.class;//获得要执行的public的方法Method method=clazz.getDeclaredMethod("test", int.class, String.class);//通过class获得当前类的实例Object obj=clazz.newInstance();//配置暴力反射(忽略访问修饰符,强制调用方法)method.setAccessible(true);//在对象上执行特定的方法//(对象实例,参数1,参数2)method.invoke(obj,1,"李白");}-----------------------------------------------(重点关注)//执行带返回值的方法public void four() throws Exception {//获得class对象Class clazz= userInfo.class;//获得要执行的public的方法Method method=clazz.getDeclaredMethod("test2", int.class, int.class);//通过class获得当前类的实例Object obj=clazz.newInstance();//配置暴力反射(忽略访问修饰符,强制调用方法)method.setAccessible(true);//在对象上执行特定的方法//接受返回的参数Object val = method.invoke(obj,2,3);System.out.println("返回值是:"+val);}

9、使用反射简化servlet操作

I、编写BaseServlet
java">要求:BaseServlet需要继承HttpServletpackage com.arjunna.web;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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;/*
* 反射的应用
* */
public class BaseServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {try {//获得当前类的class对象Class clazz=this.getClass();//获得客户端请求的方法String methodName=req.getParameter("method");//通过class对象,获得当前类中指定名称的方法Method method=clazz.getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);//配置暴力反射(忽略访问修饰符,强制调用方法)method.setAccessible(true);//通过反射执行指定的方法method.invoke(this,req,resp);}catch (Exception e){e.printStackTrace();}}}
II、让子类继承于BaseServlet类
java">@WebServlet("/op")
public class opServlet extends BaseServlet {protected void add(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		IOException {System.out.println("添加");}protected void del(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		IOException {System.out.println("删除");}protected void update(HttpServletRequest request, 				HttpServletResponse response) throws ServletException, 		IOException {System.out.println("修改");}protected void sel(HttpServletRequest request, 					HttpServletResponse response) throws ServletException, 		IOException {System.out.println("查询");}/*         如果子类继承父类,子类就自动拥有父类的方法         */
}

在这里插入图片描述

第四章

项目步骤

1、创建项目
2、导入相关依赖(jar)
3、导入配置文件conf--->druid.properties
4、创建包结构utildaoentyweb
5、导入公共类1、JDBCUtil类2、BaseServlet类
6、编写实体类,与数据表的结构对应
7、编写infoDao类
8、编写InfoServlet类
9、编写jsp页面
10、导入jsp标签库的依赖  简化jsp的编码jstl.jarstandard.jar
11、在jsp页面中引入
<%@ taglib prefix="c"  uri="http://java.sun.com/jstl/core_rt" %>
12、使用c:forEach遍历数据即可

1、简单的前后端交互

java">在java代码中,向request中存储数据request.setAttribute("键",值);-----必须是string类型值-----可以是任何类型(objcet)request.setAttribute("list",list)java代码中,从request中取数据数据类型  变量名 = (数据类型) request.getAttribute("键");List<userInfo> list =(List<userInfo>) request.getAttribute("list");//要强制转换

jsp页面中,对request中存储的List的集合遍历,显示成表格

jspjava_996">方式1:在jsp页面中,采用java脚本的方式遍历
jsp">方式1:在jsp页面中,采用java脚本的方式遍历<table border="1" style="margin:0 auto;width: 60%;text-align: center"><tr><th>编号</th><th>姓名</th><th>密码</th><th>余额</th></tr><%//接受交互层传递的requestList<userInfo> list= (List<userInfo>) request.getAttribute("list");//遍历打印在页面上for (userInfo u:list) {out.write("<tr>");out.write("<td>"+u.getId()+"</td>");out.write("<td>"+u.getName()+"</td>");out.write("<td>"+u.getPwd()+"</td>");out.write("<td>"+u.getBalance()+"</td>");out.write("</tr>");}%></table>缺点:当代码稍微复杂一点,代码的可读性会变的非常差
方式2:使用JSTL标签库

jstl:jsp标准标签库

javaweb中,把jsp页面经常会使用的一些功能,封装成了标签,通过标签可以简化jsp页面的编码,避免在jsp页面中编写java脚本,简化页面编码<c:forEach items="${存储的集合的名称}" var="从集合中取到的每一个对象"><c:forEach>

使用便签库遍历数据

jsp">    <table border="1" style="margin:0 auto;width: 60%;text-align: center"><tr><th>编号</th><th>姓名</th><th>密码</th><th>余额</th></tr><c:forEach items="${list}" var="u" varStatus="st"><tr><td>${u.id}</td><td>${u.name}</td><td>${u.pwd}</td><td>${u.balance}</td></tr></c:forEach></table>items-----它用于指定要遍历的集合名称var-------它用于指定变量,保存从集合遍历出来的每一个对象varStatus------它用于指定变量,只在当前对象在集合中的状态信息${st.index}-------得到当前对象在集合中的下标(从0开始)${st.count}-------得到当前对象在集合中的第几个对象(从1开始计数)${st.first}-------判断当前是否是集合的第一对象${st.last}-------判断当前是否是集合的最后一对象

在这里插入图片描述

修改数据的思路:

1、点击连接,将要修改的id传回到后台
2、在后台代码中,根据id查询出一条数据,封装成对象,存储在request中
3、跳转到修改页面,将要修改的旧数据显示在控件,供用户查询-----数据回显
4、点击页面修改,将要修改的新数据提交到数据库

2、转发与重定向

javaweb_1103">I、javaweb程序跳转的方式有两种
方式1: 转发 foreardrequest.getRequestDispatcher("show.jsp").forward(request,response);特点:1、转发时是在服务器端完成的跳转,地址栏不会改变,依然是之前的请求地址,如果刷新页面请求就会重复执行2、转发时,request会作为参数向下传递参数,所以,存储在request中的数据,在下一个页面中是可以把request中的数据取出来3、转发时只能跳转到当前项目中的地址方式2: 重定向 redirectresponse.sendRedirect("show.jsp");特点:1、重定向,它是通过修改客户端浏览器地址栏的地址实现跳转,地址栏的信息会改变成跳转后的地址,之前的请求已经结束,此时再刷新页面,请求也不会执行2、重定向时,没有将请求继续向下继续传递,所以存在request中的数据,下一个页面取不到值3、重定向时,可以跳转到任意的URL地址
II、面试题:forward(转发)与redirect(重定向)的区别
1、forward它是在服务器端完成的跳转,地址栏不会变,依然是之前的请求地址重定向它是客户端地址栏中实现的跳转,地址栏会改变,之前的请求会结束2、转发时request会作为参数向下传递,所有存储在request中的数据再下一个页面可以取到,重定向时,没有将request作为参数向下传递,所以存储在request中的数据在下一个页面中取不到值3、转发时,只能在项目内跳转;重定向时,可以跳转到任意地址4、转发由request产生;重定向是由response产生@@一般在加载数据时用转发,增、删、改以后用重定向
III、重定向的两种写法
java">方式1:重定向到页面response.sendRedirect("show.jsp");方式2:重定向到serVlet中的某一个方法中response.sendRedirect("xxx?method=xxx")

第五章

—servlet的三种作用域

—jstl标签库的使用

—过滤器

1、servlet的三种作用域

**作用域:**作用域就是存储数据的有效范围

I、request:请求作用域
之前存储的数据时,采用如下形式request.setAttribute("键","值");request:它是一个请求对象,可以执行与请求相关的操作同时,它也是一个存储作用域,它存储的数据在一个请求(request)中有效,如果产生了新的请求,则之前存放在request(请求)中的数据会全部丢失

下列三种情况,会产生新的请求:

1、表单提交一次2、页面跳转一次3、页面刷新一次问题:怎么确保即使产生新的请求,数据也不会丢失?那么就需要更大的存储范围

II、HttpSession:会话作用域
HttpSession:会话(比请求作用域大)它是一个存储作用域,存放在会话作用域中的数据与请求无关,不论产生多少个请求,都不会影响到存放在会话作用域中的数据问题1:什么时候产生?当客户端与服务器端建立连接时,会话就会自动产生,会话作用域产生后就可以向该作用域存储数据,只要这个会话不中断,存储的数据将一直有效问题2:客户端与服务器端建立连接?值客户端用浏览器访问这个web应用程序,我们就称为:与服务器建立了连接问题3:会话中断指关闭正在访问web程序的浏览器,我们就称为:”会话中断“只要客服端与服务器端建立连接,就会自动产生会话“HttpSession“(如打电话)

第一步:在serlvet中获得会话

jsp">	HttpSession session=request.getSession();

第二步:向会话作用域中存储数据

	session.setAttribute("消息的key",“数据”);键:必须是字符串类型值;可以为任意字符注释:与request的使用一模一样

第三步:从会话中取数据(在java中取值)

	类型 val =(类型) session.getAttribute("消息的key");

第三步:从会话中取数据(在jsp页面中取值)

	${消息的key}
会话(session)作用域的特点
	1、存放在session作用域中的数据与请求无关,不论产生多少个新的请求,都不会影响到存储在会话中的数据2、数据如果存储在session中,不论是转发还是重定向都可以取到值(与跳转方式无关)3、当session中断时,存放在session中的数据会全部丢失下列三种情况session会中断:1、关闭浏览器2、默认情况下,如果三十分钟内没有操作,session会因为闲置超时过期idle 闲置 expire 失效session.setMaxInactiveInterval();设置session过期时间3、调用session.invalidate();此方法调用后,session会马上失效4、当客户端与服务器端建立连接时,服务器端会为每一个客户端分配一个session,用于存储当前客户端的数据,每一个客户端的session,只有当前客服端自己才能访问只要打开一个新的浏览器访问web程序,系统就会认为是一个新的客户端,就会分配一				个session给当前用户存储数据(一个浏览器就是一个新客户端)

在这里插入图片描述

session只能查看当前用户自己访问web程序的次数但是如果想要查看这个web程序启动以来,有多少个用户访问过,就需要更大的存储空间

III、 servletContext 全局上下文(全局作用域)
servletContext​			它是最大的存储作用域​			在web程序启动时(tomcat)全局上下文就开始了,知道服务器停止,全局上下文才会结束,只要服务器在运行,存放在全局上下文中的数据将一直有效
全局上下文的特点
	1、只要服务器在运行,存放在全局上下文的数据将一直有效,可以随时存,随时取2、全局上下文不区分用户,存放在全局上下文中的数据是全局共享(任何用户都可以取到)
获得全局上下文
java">servletContext cxt=this.getServletContext();
在servlet中,向全局上下文存数据
java">cxt.setAttribute("消息的key",值)
在servlet中,从全局上下文取数据
java">类型 val=(类型) cxt.getAttribute("消息的key");
jsp_1310">在jsp页面中,从全局上下文取数据
java">${消息的key}

IIII、三种作用域总结
java">三种作用域:​				request--------------------------------------请求作用域​				session--------------------------------------会话作用域​				servlet----------------------------------------全局上下文**存数据的方式:**​				作用域.setAttribute(“key”,值);**取数据的方式**​				类型 val = (类型)  作用域.getAttribute(“key”);**jsp页面取值**​				${}**以上三种存储作用域的范围从小到大排序依次是:**​				request   <    session	<	servletContext(几乎不用)**问题:我们在编写代码时,应该使用哪一种存储作用域存数据**​			原则:优先考虑范围较小的作用域,如果较小的范围解决不了问题,才会考虑大范围

2、jstl标签库

I、什么是jstl?
jstl:称为JSTL标准标签库,把一些jsp页面的常见功能封装成标签,通过标签可以简化jsp的页面,避免出现java小脚本
II、分类
前提条件:要使用jstl的标签,首先要导入两个依赖1standard.jar2、jstl.jar
1、核心标签库

要使用核心标签库,需要在jsp页面中引入核心标签库的指令

jsp"><%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>

EL表达式的取值原理:

jsp"><c:set var="msg" value="hello" scope="page"/>
<c:set var="msg" value="hello" scope="request"/>
<c:set var="msg" value="hello" scope="session"/>
<c:set var="msg" value="hello" scope="application"/>方式1:${msg}这种方式,没有指定作用域的范围,系统会默认从最小的作用域开始取,如果小的范围中能找到,就不会再查找大范围,如果没有找到,就会依次从大范围中查找方式2:${作用域范围.msg}这种方式取值,只会查找特定的存储范围,如果没有找到,也不会再查找其他范围${pageScore.msg}------page范围${requestScore.msg}------request范围${sessionScore.msg}------session范围${applicationScore.msg}-----application范围注意:在使用el表达式的时候,指定范围,性能会更好

核心标签库的分类

jsp">
1、通用标签<c:set>作用:在jsp页面中设置一个变量,存储在作用域中使用:<c:set var="msg" value="hello" scope="作用域的名称"/>var="msg"-----------设置了一个变量名叫msgvalue="hello"-------它的值是helloscope=""------------设置该变量的存储范围(默认是page作用域)作用域有四种:1、page--------它存储的数据仅在当前页面有效,离开当前页就取不到2、request-----它存储的数据在request中有效3、session-----它存储的数据在session中有效4、application--它存储的数据在整个应用程序中有效(servletContext)<c:redirect>作用:在页面进行重定向使用:<c:redirect url="show.jsp">url="show.jsp"---重定向到页面url="op?method=init"-----重定向到某个方法上2、逻辑标签:用于在页面中进行逻辑判断<c:if>作用:用于进行条件判断,如果条件成立,就执行if块的代码使用:<c:if test="${条件判断}">代码<c:if>案例:分数:${requestScore.score}考核结果:<c:if test="${requestScore.score>=60}"><b style="color:green">合格</b></c:if><c:if test="${requestScore.score<60}"><b style="color:red">不合格</b></c:if><c:choose> <c:when> <c:otherwise>作用:这三个标签组合在一起,类似java中的多重if使用:<c:choose><c:when test="${表达式1}">代码1<c:/when><c:when test="${表达式2}">代码2<c:/when><c:when test="${表达式3}">代码3<c:/when><c:otherwise>代码4<c:/otherwise></c:choose>案例:分数:${requestScore.score}考核结果:<c:choose><c:when test="${requestScore.score>=90}">优秀<c:/when><c:when test="${requestScore.score>=80}">良好<c:/when><c:when test="${requestScore.score>=60}">合格<c:/when><c:otherwise>不合格<c:/otherwise></c:choose>	3、迭代标签:也称为循环标签<c:forEach>作用:用于对集合循环遍历使用1:<c:forEach items="${list}" var="u" varStatus="st"><tr><td>${u.id}</td><td>${u.name}</td><td>${u.pwd}</td><td>${u.balance}</td></tr></c:forEach>items-----它用于指定要遍历的集合名称var-------它用于指定变量,保存从集合遍历出来的每一个对象varStatus------它用于指定变量,只在当前对象在集合中的状态信息使用2:<select><option value="-1" >请选择年龄</option><c:forEach var="k" begin="1" end="120">								<option value="${k}">${k}岁</option></c:forEach></select>>在页面中生成循环结构bengin:表示从几开始end:到几结束val:保存循环产生的每一个值
2、格式化标签库

作用:用于转换数据格式

前提条件:<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt_rt" %>

转换日期类型的数据

jsp">//在请求中存值
request.setAttribute("bir",new Date());   //格式化日期<fmt:formatDate value="${requestScope.bir}" pattern="yyyy-MM-dd HH:mm:ss E"></fmt:formatDate>

转换货币格式的数据

jsp">//在请求中存值
request.setAttribute("salary",123456.7895);  //格式化金额
<fmt:formatNumber value="${requestScope.salary}"  type="currency"/>
3、sql标签库(已废弃)

III、标签的示例:

示例1:要求某一个页面只有登录用户才能查看,未登录的用户不允许查询页面(一般用户登录成功后,我们会将用户信息存放在session中,只有session不中断,就可以一直记录当前用户的状态信息)

**1、盗链:**越过登录直接访问网页地址

在这里插入图片描述

解决方法:

jsp">	显示页面<%--//判断用户是否登录,如果没有登录就直接跳转到登录页面--%><c:if test="${sessionScope.user==null}"><c:redirect url="login.jsp"/></c:if><h1>${sessionScope.user}</span>,欢迎您! </h1>但此方法也有问题,一旦页面多了就得每个页面都写一个,过于麻烦
2、回显数据,转换日期格式
jsp"><input type="Date" value="<fmt:formatDate value="${requestScope.bir}" pattern="yyyy-MM-dd">">日期标签里面嵌套格式化日期标签
3、单选按钮的数据回显
jsp"><input type="radio" name="gender" value="男" 							<c:iftest="${user.gender=='男'}">checked</c:if>>男<input type="radio" name="gender" value="女"<c:if test="${user.gender=='男'}">checked</c:if>>女将查询到的用户性别做逻辑判断,匹配的加上checked属性
4、下拉选项数据回显
jsp"><select name="gender"><option value="-1" <c:if test="${gender=='-1'}">selected</c:if>>全部学生		</option><option value="男" <c:if test="${gender=='男'}">selected</c:if>>男生			</option><option value="女" <c:if test="${gender=='女'}">selected</c:if>>女生			</option>
</select>查询条件相等的加上selected属性
5、在idea中编写代码中如果出现黄色的波浪线,是因为系统检测到重复代码

1、只要编写一句不一样就OK

2、file>Inspections>Duplicated code取消√即可

3、数据的分页使用

-- 设涉及到分页的sql语句-- 分页查询的语句:select * from info limit 开始下标,几条数据;
-- 每页显示3条select * from info limit 0,3-----第1页select * from info limit 3,3-----第2页select * from info limit 6,3-----第3页select * from info limit,3-----第N页-- 开始下标=(当前页-1)* 每页条数
-- 开始下标-(N-1)* 3

要分页显示数据必须要知道的四个值

1、当前页 page2、每页显示的条数	rows3、一共有几条数据	count4、一共可以显示多少页  maxPage
总页数公式 = 总条数 % 每页条数 == 0 ?总条数/每页条数:总条数/每页条数 +1
int maxPage = count % rows == 0 ? count/rows : count/rows+1

分页流程

阶段1:显示全部数据
阶段2:只显示前3条数据
阶段3:实现分页
阶段4:优化分页

第六章

完善第五章的内容(新内容分页)

第七章

1、分页的优化

jsp">        <tr><td colspan="6"><c:if test="${page==1}"><span>首页</span><span>上一页</span></c:if><c:if test="${page!=1}"><a href="op?method=init&page=1">首页</a><a href="op?method=init&page=${page-1}">上一页</a></c:if><c:if test="${page==maxPage}"><span>尾页</span><span>下一页</span></c:if><c:if test="${page!=maxPage}"><a href="op?method=init&page=${page+1}">下一页</a><a href="op?method=init&page=${maxPage}">尾页</a></c:if>&nbsp;<span>当前第<select οnchange="location.href='op?method=init&page='+this.value"><c:forEach  var="k" begin="1" end="${maxPage}"><option value="${k}" <c:if test="${k==page}">selected</c:if>>${k}</option></c:forEach></select>页</span><span>共<b>${requestScope.maxPage}</b>页</span><span>每页<b>${requestScope.rows}</b>条</span><span>共<b>${requestScope.count}</b>条</span></td></tr>
多条件搜索后的分页
1、当点击搜索时,进入servlet中的search方法在该方法中获得所有查询条件,将查询条件存放在session2、然后从search方法中重定向带init方法,根据条件分页

2、过滤器 Filter

定义:过滤器,它是一个运行在服务器端的java组件,主要用于拦截用户请求,给请求附加功能在系统中配置了过滤器之后,客户端发出的请求在访问服务器的目标自愿(jsp,servlet)之前,会先进入过滤器,过滤器执行的代码完成之后,才会访问请求的目标资源

在这里插入图片描述

I、配置过滤器
过滤器属于工作类,一般放在util类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

II、使用过滤器的场景
过滤器主要用于进行功能扩展
例如:拦截用户请求,判断用户是否登录,如果没有登录,自动转向登录界面使用过滤器进行权限判断,用户不登录可以看到页面,但如果要操作页面上的功能,就必须要登录。如果未登录,会自动转向登录界面

个人认为这个过滤器很简单,很实用

3、支付宝沙箱

它是支付宝用于开发中的一种环境,它的用法与真实环境的用法一样区别:1、它是用于开发环境中,主要用于测试环境支付功能,并不能真的付款,它使用的是测试数据2、它使用网关是开发环境的网关如果要转换成正式环境,只需要向支付宝提交营业执照,更换网关地址即可
项目开发中会涉及三种环境:1、开发环境:这个环境主要用于编写代码2、测试环境:开发结束后,用于测试代码的环境3、生产环境:项目开发全部结束,并且测试通过,项目要上线投入生产使用
沙箱账号商家信息
商户账号hsgxuj3492@sandbox.com
登录密码
商户PID2088721012026616
账户余额1000100.00买家信息
买家账号yruahu7657@sandbox.com
登录密码
支付密码
用户UID2088722012026626
用户名称yruahu7657
证件类型IDENTITY_CARD
证件账号216297196408127438
账户余额1000000.00 商家秘钥:支付宝公钥:网关地址:https://openapi.alipaydev.com/gateway.dotrade_no:2023042122001426620502312463---支付宝交易号
out_trade_no:202342117383328---商品交易号
total_amount:100.00---交易金额

第八章

1、支付宝的应用

java">app_id = "";merchant_private_key = "";alipay_public_key = "";return_url = "http://localhost:8080/alipay/return_url.jsp";gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

要调用支付宝接口进行支付,必须提供四个参数

tradeNo---------订单编号
tradePrice------订单金额
tradeName-------订单名称
tradeMsg--*-----交易详情

编写一个servlet类,用于处理付款成功的回调,这样才能获得支付宝的交易号,才能执行退款操作


2、购物车的综合练习

流程
1、数据表分析2、加载全部商品3、判断用户是否登录4、用户的注册、登录5、添加商品到购物车中6、修改商品信息(增、删、改、查)7、分页显示商品8、支付
1、数据表的分析
1、商品表goods表goods_id 商品编号goods_name 商品名称goods_price 商品单价goods_prc 商品的图片2、用户表user表user_id 用户编号user_name 用户名称user_pwd 用户密码3、购物信息表cart表cart_id 购物编号user_id 用户编号---标识是哪一个用户的购物信息(外键,关联到用户表)goods_id 商品编号---标识购买的是哪一件商品(外键,关联到商品表)amout   购买数量

重定向传值

java">//传值response.sendRedirect("init.jsp?flag=ok");//取值${param.flag}

弹框


alert() 是单线程消息框,再没有点击之前,其他数据无法加载<c:if test="${param.flag=='ok'}"><script>new swal({title: '已加入购物车!',color: 'rgb(44, 153, 238)',text: '2秒后自动关闭。',timer: 2000}).then(function () { },function (dismiss) {if (dismiss === 'timer') {console.log('小趴菜')}})</script></c:if>

第九章

1、完善购物车案例

2、cookie的使用

3、文件上传下载

4、oos的使用

1、完善购物车

分页显示
1、当前页 page2、每页显示的条数	rows3、一共有几条数据	count4、一共可以显示多少页  maxPage
总页数公式 = 总条数 % 每页条数 == 0 ?总条数/每页条数:总条数/每页条数 +1
int maxPage = count % rows == 0 ? count/rows : count/rows+1
付款
1、支付宝的四个值2、导入依赖以及配置类3、编写页面1、订单编号2、订单名称3、订单金额4、订单详情

2、cookie

I、什么是cookie
cookie是由服务器端产生的一个文本,产生好以后,服务器将会把cookie发送到客户端保存cookie:它用于将用户信息保存在客户端
HttpSession:它用于将用户信息保存在服务器端cookie的作用:用于在客户端保存用户信息
II、cookie的工作原理
1、当客户端与服务器端建立连接时,服务器将会产生一个cookie,cookie可以记录一些用户信息,然后服务器会将cookie发送到客户端保存2、以后每一次客户端与服务器建立连接,保存在客户端的cookie将会自动跟随请求一起发送到服务器
III、cookie的保存位置
不同的浏览器,保存的cookie的位置不一样C:\Users\86159\AppData\Local\Google\Chrome\User Data\Default\Network
IIII、cookie的特点
cookie是在客户端以文本的方式保存用户信息,安全性不高,所以不能存储敏感信息,芽一班用于存储用户身份(userID、username)它主要在客户端记录当前用户的身份信息;
例如:用户几天之内不用登录,系统会自动登录
IIIII、cookie的基本使用

创建cookie

java">在服务器端创建cookie//创建cookieCookie ck=new Cookie("d118_cookie","这是一个新的cookie");//设置cookie的存活时间-秒ck.setMaxAge(120);//将cookie保存到客户端response.addCookie(ck);System.out.println("cookie发送成功!");

获得cookie

获得指定的cookie//获取请求携带的cookie----它只能获得当前程序发送到客户端保存的cookieCookie[] cks=request.getCookies();if (cks!=null){for (Cookie ck:cks) {if (ck.getName().equals("d118_cookie")){System.out.println("cookie的名字:"+ck.getName());System.out.println("cookie的值:"+ck.getValue());}}}

3、自动登录案例–cookie

获得复选框的值

java"> <input type="chekbox" value="ok" >//获得一组复选框选中的值String[] vals = request.getParameterValues("复选框的name'");//获取一个复选框的值
String str = request.getParameter("复选框的name");
*选中有值
*没有选中是null
java">package web;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;@WebServlet("/user")
public class cookieServlet extends BaseServlet {protected void init(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//读取cookie//获取请求携带的cookie----它只能获得当前程序发送到客户端保存的cookieCookie[] cks=request.getCookies();//指定的cookieCookie userCookie=null;//对所有的cookie遍历if (cks!=null){for (Cookie ck:cks) {if (ck.getName().equals("username")){//找到了指定的cookieuserCookie=ck;break;}}}if (userCookie!=null){//得到cookie的用户信息String user  = userCookie.getName();//将用户信息存到seesion中request.getSession().setAttribute("user",user);//重定向到显示页面response.sendRedirect("success.jsp");}else {//cookie已失效//没有找到指定cookieresponse.sendRedirect("login.jsp");}}protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取用户名String username = request.getParameter("user");if (username.equals("")){request.setAttribute("msg","用户名或密码错误");request.getRequestDispatcher("login.jsp").forward(request,response);}else{//将用户信息存放到session中request.getSession().setAttribute("username",username);//判断用户是否勾选记住登录String remember = request.getParameter("remember");if (remember!=null){//创建cookieCookie ck=new Cookie("username",username);//设置cookie的存活时间-秒ck.setMaxAge(20);//将cookie保存到客户端response.addCookie(ck);System.out.println("cookie发送成功!");}response.sendRedirect("success.jsp");}}}

4、文件上传

指客户端的文件上传到服务器1、编写工程2、导入依赖common-fileupload.jarcommon-io.jar3、编写页面4、编写servlet处理请求
1、编写上传页面的要求
java">1、表单提交方式必须post请求2、必须指定表单enctype="multipart/form-data"-----允许表单携带附件3、使用文件域选择文件<input type="file" name="file"><form action="" method="post" enctype="multipart/form-data">文件:<input type="file" name="file"><input type="submit" value="提交"></form>
2、上传案例
java">package com.web;import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;@WebServlet("/file")
public class fileServlet extends BaseServlet {SimpleDateFormat sfdate=new SimpleDateFormat("yyyy-MM-dd");Map<String,String> map=new HashMap<>();protected void up(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {try {//获得文件对象的工厂类,用于获得表单提交的所有数据(表单中提交的的数据,系统都会当成一个文件进行处理)FileItemFactory factory =new DiskFileItemFactory();//获得处理器ServletFileUpload sf=new ServletFileUpload(factory);//通过处理器,将表单请求中提交的每一条数据转换成文件对象FileItem放入list集合中List<FileItem> list=sf.parseRequest(request);//判断哪些是真正的文件,哪些是表单的普通数据//如果是真的文件,需要在服务器端生成物理文件,如果是普通数据直接使用for (FileItem item:list) {if (item.isFormField()){//如果返回true,就表示当前是表单的普通数据,如果false,则是文件//普通数据//获取当前普通数据的字段名称String key=item.getFieldName();//获得普通数据的值String value=item.getString("utf-8");//把数据存放到map中map.put(key,value);}else {//文件//获取时间,防止重名Date date=new Date();//获得上传的文件名String fileName = "a_"+sfdate.format(date)+"_"+UUID.randomUUID().toString()+"_"+item.getName();//在服务器指定路径下,生成新文件File file=new File("E:/upload",fileName);//判断文件目录是否存在if (!file.getParentFile().exists()){file.getParentFile().mkdirs();}//将上传文件的数据写入新文件中item.write(file);}}} catch (Exception e) {e.printStackTrace();}//        从map中取值String user=map.get("user");String pwd=map.get("pwd");request.getSession().setAttribute("user",user);request.getSession().setAttribute("pwd",pwd);//重定向response.sendRedirect("ok.jsp");}}

第十章

基于javaweb上传下载

oos对象存储服务

jxl

1、上传与下载

模拟向数据库添加文件

java">SimpleDateFormat sfdate=new SimpleDateFormat("yyyy-MM-dd");Date date=new Date();String fileName = "a_"+sfdate.format(date)
+"_"+UUID.randomUUID().toString()
+"_"+item.getName();//解决文件重名

上传

java">//上传protected void up(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {try {//获得文件对象的工厂类,用于获得表单提交的所有数据(表单中提交的的数据,系统都会当成一个文件进行处理)FileItemFactory factory =new DiskFileItemFactory();//获得处理器ServletFileUpload sf=new ServletFileUpload(factory);//通过处理器,将表单请求中提交的每一条数据转换成文件对象FileItem放入list集合中List<FileItem> list=sf.parseRequest(request);//判断哪些是真正的文件,哪些是表单的普通数据//如果是真的文件,需要在服务器端生成物理文件,如果是普通数据直接使用for (FileItem item:list) {if (item.isFormField()){//如果返回true,就表示当前是表单的普通数据,如果false,则是文件//普通数据//获取当前普通数据的字段名称String key=item.getFieldName();//获得普通数据的值String value=item.getString("utf-8");//把数据存放到map中map.put(key,value);}else {//文件//获取时间,防止重名Date date=new Date();//获得上传的文件名String fileName = "a_"+sfdate.format(date)+"_"+item.getName();//在服务器指定路径下,生成新文件File file=new File("E:/upload",fileName);//判断文件目录是否存在if (!file.getParentFile().exists()){file.getParentFile().mkdirs();}//将上传文件的数据写入新文件中item.write(file);//获得文件类型String type=fileName.substring(fileName.lastIndexOf(".")+1);map.put("type",type);//存放到map中//获得文件保存路径map.put("path",file.getAbsolutePath());//获得文件大小long num=file.length();//1024byte=1kb  1024kb=1mb//判断是以什么结尾String size="";if (num/1024/1024>=1){size=num/1024.0/1024+"Mb";}else{size=num/1024.0+"kb";}map.put("size",size);/******************上传成功后存到数据库********************/fdao.add(map.get("user"),map.get("pwd"),map.get("type"),map.get("path"),map.get("size"));}}} catch (Exception e) {e.printStackTrace();}//        从map中取值String user=map.get("user");String pwd=map.get("pwd");String type=map.get("type");String path=map.get("path");String size=map.get("size");request.getSession().setAttribute("user",user);request.getSession().setAttribute("pwd",pwd);request.getSession().setAttribute("type",type);request.getSession().setAttribute("path",path);request.getSession().setAttribute("size",size);//重定向response.sendRedirect("ok.jsp");}

下载

java">//下载protected void download(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获得下载的文件编号Integer id=Integer.parseInt(req.getParameter("id"));//到数据库查找该id的文件信息fileInfo f=fdao.findByid(id);/*******************下面是下载的代码******************************************///获得文件名,将文件名转换utf-8String fname= URLEncoder.encode(f.getFileName(),"utf-8");//只需要转换文件名//显示下载界面resp.setContentType("application/x-msdownload");//设置下载面板上显示的内容resp.setHeader("Content-disposition","attachment;fileName="+fname);//创建输入流,用于读取要下载的文件InputStream in=new FileInputStream(f.getFilePath());//通过响应产生输出流ServletOutputStream out=resp.getOutputStream();//创建字节数组,充当数据缓冲区byte[] b=new byte[8192];//定义变量保存写入到数据缓冲区的数据长度int len=0;//一边读一边写while ((len=in.read(b))!=-1){out.write(b,0,len);}out.close();in.close();}

2、在web程序中图片显示的问题

在web程序中,要显示图片,图片的路径只支持两种路径1、相对路径img/1.jpg
2、网络路径http://xxxx.xx.xx/xx.jpg绝对路径无法显示

解决图片上传的显示问题

解决方案1:使用分布式文件系统FastDFSFastDFS需要在linux系统中配置

在这里插入图片描述

java">解决方案2:使用对象oss服务阿里云对象存储 OSSObject Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供最高可达 99.995 % 的服务可用性。多种存储类型供选择,全面优化存储成本。

3、oss服务配置及使用

阿里云账号
登录名:
账号ID:
手机号:1、服务器位置:oss-cn-beijing.aliyuncs.com2、AccessKey ID:AccessKey Secret:3、空间名称:4、上传文件名:6.jpg5、完整路径:e:/upload/6.jpg
java">package com.demo;import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;import java.io.FileInputStream;
import java.io.InputStream;public class fileUpload {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "oss-cn-.aliyuncs.com";// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessKeyId = "";String accessKeySecret = "";// 填写Bucket名称,例如examplebucket。String bucketName = "";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。String objectName = "bg.jpg";// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。String filePath= "E:\\upload\\bg.jpg";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {InputStream inputStream = new FileInputStream(filePath);// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);// 设置该属性可以返回response。如果不设置,则返回的response为空。putObjectRequest.setProcess("true");// 创建PutObject请求。PutObjectResult result = ossClient.putObject(putObjectRequest);// 如果上传成功,则返回200。System.out.println(result.getResponse().getStatusCode());} catch (Exception oe) {oe.printStackTrace();}}
}

第十一章

jxl解析电子表格文档

servlet的生命周期

jsp的内置对象

1、jxl解析电子表格文档

I、什么是jxl
jxl:它是操作电子表格文档excel的一种技术,通过它可以读取excel文件的数据,也可以将数据写入到excel文件
II、使用jxl解析excel文件
把excel中的数据读取到程序中电子表格文件的后缀名:*.xls、*.xlsx
jxl解析主要支持*.xls
poi可以解析*.xlsx一般在显示数据表格时,或者是批量导入数据时,导入到数据里

使用步骤

java">1、导入依赖jar  jxl.jar2、编写如下代码/*解析单个工作表*/
package com.sc.demo;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import java.io.FileInputStream;
import java.io.InputStream;public class demo {public static void main(String[] args) throws Exception {//创建输入流,用于读取要解析的文件InputStream in=new FileInputStream("e:/date/test.xls");//根据输入流的信息,产生工作簿Workbook wk=Workbook.getWorkbook(in);//获得工作簿中所有的表单Sheet[] sheets=wk.getSheets();//分别获得表单的名称
//        for (Sheet sheet:sheets) {
//            System.out.println(sheet.getName());
//        }//获得第一个表单的数据Sheet st=sheets[1];//获得表单的总行数int rows = st.getRows();//获得表单的总列数int cols=st.getColumns();//读取每一行、每一列的值for (int i=0;i<rows;i++){//遍历所有行for (int j=0;j<cols;j++){//遍历所有的列//根据列下标,行下标获得表单中指定的单元格Cell cell=st.getCell(j,i);//(列下标,行下标);//获得当前单元格中的内容String msg=cell.getContents();System.out.print(msg+"\t");}System.out.println();}}
}/*解析所有工作表的方法*/
package com.sc.demo;import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import java.io.FileInputStream;
import java.io.InputStream;public class demo {public static void main(String[] args) throws Exception {//创建输入流,用于读取要解析的文件InputStream in=new FileInputStream("e:/date/test.xls");//根据输入流的信息,产生工作簿Workbook wk=Workbook.getWorkbook(in);//获得工作簿中所有的表单Sheet[] sheets=wk.getSheets();//        获得所有的表单信息for (Sheet st:sheets) {System.out.println("----------------------------------------");//获得表单的总行数int rows = st.getRows();//获得表单的总列数int cols=st.getColumns();//读取每一行、每一列的值for (int i=0;i<rows;i++){//遍历所有行for (int j=0;j<cols;j++){//遍历所有的列//根据列下标,行下标获得表单中指定的单元格Cell cell=st.getCell(j,i);//(列下标,行下标);//获得当前单元格中的内容String msg=cell.getContents();System.out.print(msg+"\t");}System.out.println();}}}
}
III、将数据写入到xls文件中

只写入一个单元格的案例

java">package com.sc.demo;import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;public class demo2 {/** 写数据到excel* */public static void main(String[] args) throws Exception {//创建输出流OutputStream out= new FileOutputStream("e:Date/out.xls");//创建一个可以写入数据的工作簿WritableWorkbook wk= Workbook.createWorkbook(out);//在工作簿中创建表单,并设置表单名称WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标//创建一个标签Label-----它就是每一个单元格要显示的内容Label labelid=new Label(0,0,"编号");//(列下标,行下标,标签显示的名称)//将标签放到表单中st.addCell(labelid);//将工作簿的数据写入到文件中wk.write();//关闭工作簿wk.close();out.close();System.out.println("数据已写入");}
}

将数据库的数据写入到excel表格中

java">package com.sc.demo;import com.sc.dao.stuDao;
import com.sc.enty.stuInfo;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;public class demo2 {/** 写数据到excel* */public static void main(String[] args) throws Exception {//创建输出流OutputStream out= new FileOutputStream("e:Date/out.xls");//创建一个可以写入数据的工作簿WritableWorkbook wk= Workbook.createWorkbook(out);//在工作簿中创建表单,并设置表单名称WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标//创建一个标签Label-----它就是每一个单元格要显示的内容Label labid=new Label(0,0,"编号");//(列下标,行下标,标签显示的名称)Label labname=new Label(1,0,"姓名");Label labage=new Label(2,0,"年龄");Label labgender=new Label(3,0,"性别");Label labclazz=new Label(4,0,"班级");Label labtel=new Label(5,0,"电话");Label labtime=new Label(6,0,"注册日期");Label labres=new Label(7,0,"备注");//将标签放到表单中st.addCell(labid);st.addCell(labname);st.addCell(labage);st.addCell(labgender);st.addCell(labclazz);st.addCell(labtel);st.addCell(labtime);st.addCell(labres);stuDao sdao=new stuDao();//获得要写入的数据List<stuInfo> list=sdao.init();for (int i=0;i<list.size();i++){//蝴蝶每一个对象stuInfo stu=list.get(i);Label id=new Label(0,i+1,stu.getSid().toString());Label name=new Label(1,i+1,stu.getSname());Label age=new Label(2,i+1,stu.getSage().toString());Label gender=new Label(3,i+1,stu.getSgender());Label sclass=new Label(4,i+1,stu.getSclass());Label tel=new Label(5,i+1,stu.getStel());Label time=new Label(6,i+1,stu.getSregtime());Label res=new Label(7,i+1,stu.getRes());//将标签添加到表单中st.addCell(id);st.addCell(name);st.addCell(age);st.addCell(gender);st.addCell(sclass);st.addCell(tel);st.addCell(time);st.addCell(res);}//将工作簿的数据写入到文件中wk.write();//关闭工作簿wk.close();out.close();System.out.println("数据已写入");}
}

设置写入到exce中的样式

java">package com.sc.demo;import com.sc.dao.stuDao;
import com.sc.enty.stuInfo;
import jxl.Workbook;
import jxl.write.*;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.List;public class demo2 {/** 写数据到excel* */public static void main(String[] args) throws Exception {//创建输出流OutputStream out= new FileOutputStream("e:Date/out.xls");//创建一个可以写入数据的工作簿WritableWorkbook wk= Workbook.createWorkbook(out);//在工作簿中创建表单,并设置表单名称WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标/*****************************在写入数据前,设置表格的数据样式************************************/
//
//           设置表格每一列宽度或高度st.getSettings().setDefaultColumnWidth(25);//列宽
//            st.getSettings().setDefaultRowHeight(15);//行高
//        指定一种可以用流写入文件的字体(字体类型,字体大小,字体是否加粗)//大标题的样式WritableFont ft=new WritableFont(WritableFont.ARIAL,20,WritableFont.BOLD);
//            指定一种单元格的格式(参数:字体)WritableCellFormat wcf=new WritableCellFormat(ft);wcf.setAlignment(Alignment.CENTRE);//内容居中对齐wcf.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )wcf.setWrap(true);//数据自动换行//普通标题的样式WritableFont f1=new WritableFont(WritableFont.ARIAL,18,WritableFont.BOLD);
//          指定一种单元格的格式(参数:字体)WritableCellFormat wcf1=new WritableCellFormat(f1);wcf1.setAlignment(Alignment.CENTRE);//内容居中对齐wcf1.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )wcf1.setWrap(true);//数据自动换行//内容的样式WritableFont f2=new WritableFont(WritableFont.ARIAL,18);//          指定一种单元格的格式(参数:字体)WritableCellFormat wcf2=new WritableCellFormat(f2);wcf2.setAlignment(Alignment.CENTRE);//内容居中对齐wcf2.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )wcf2.setWrap(true);//数据自动换行/************************************指定样式结束**********************************************///添加大标题Label th=new Label(0,0,"学员信息",wcf);st.addCell(th);//合并单元格(开始列下标,开始行下标,结束列下标,结束行下标);st.mergeCells(0,0,7,0);//创建一个标签Label-----它就是每一个单元格要显示的内容Label labid=new Label(0,1,"编号",wcf1);//(列下标,行下标,标签显示的名称,表格的样式)Label labname=new Label(1,1,"姓名",wcf1);Label labage=new Label(2,1,"年龄",wcf1);Label labgender=new Label(3,1,"性别",wcf1);Label labclazz=new Label(4,1,"班级",wcf1);Label labtel=new Label(5,1,"电话",wcf1);Label labtime=new Label(6,1,"注册日期",wcf1);Label labres=new Label(7,1,"备注",wcf1);//将标签放到表单中st.addCell(labid);st.addCell(labname);st.addCell(labage);st.addCell(labgender);st.addCell(labclazz);st.addCell(labtel);st.addCell(labtime);st.addCell(labres);stuDao sdao=new stuDao();//获得要写入的数据List<stuInfo> list=sdao.init();for (int i=0;i<list.size();i++){//蝴蝶每一个对象stuInfo stu=list.get(i);Label id=new Label(0,i+2,stu.getSid().toString(),wcf2);Label name=new Label(1,i+2,stu.getSname(),wcf2);Label age=new Label(2,i+2,stu.getSage().toString(),wcf2);Label gender=new Label(3,i+2,stu.getSgender(),wcf2);Label sclass=new Label(4,i+2,stu.getSclass(),wcf2);Label tel=new Label(5,i+2,stu.getStel(),wcf2);Label time=new Label(6,i+2,stu.getSregtime(),wcf2);Label res=new Label(7,i+2,stu.getRes(),wcf2);//将标签添加到表单中st.addCell(id);st.addCell(name);st.addCell(age);st.addCell(gender);st.addCell(sclass);st.addCell(tel);st.addCell(time);st.addCell(res);}//将工作簿的数据写入到文件中wk.write();//关闭工作簿wk.close();out.close();System.out.println("数据已写入");}
}

2、点击下载生成excel表格保存到本地

java">package com.sc.web;import com.sc.dao.stuDao;
import com.sc.enty.stuInfo;
import jxl.Workbook;
import jxl.write.*;import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;@WebServlet("/jxl")
public class jxlServlet extends BaseServlet {stuDao sdao=new stuDao();protected void init(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {//加载数据List<stuInfo> list=sdao.init();//存到seesion中request.getSession().setAttribute("list",list);//跳转到显示页面response.sendRedirect("init.jsp");}//导出数据protected void export(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {//取出session中的数据List<stuInfo> list= (List<stuInfo>) request.getSession().getAttribute("list");//文件名String fname="d118学生信息.xls";//转换文件编码格式String name= URLEncoder.encode(fname,"utf-8");//设置响应格式(响应格式是一个电子表格文件)response.setContentType("application/vnd.ms excel");//设置下载面板上显示的内容response.setHeader("Content-disposition","attachment;fileName="+name);//通过响应产生一个输出流,用于将excel文件输出到客户端ServletOutputStream out=response.getOutputStream();/********************************以下代码直接赋值导出表格的代码*********************************/try {//创建一个可以写入数据的工作簿WritableWorkbook wk= Workbook.createWorkbook(out);//在工作簿中创建表单,并设置表单名称WritableSheet st = wk.createSheet("d118", 0);//参数1:表单名称,参数2:表单的下标/*****************在写入数据前,设置表格的数据样式************************/
//
//           设置表格每一列宽度或高度st.getSettings().setDefaultColumnWidth(25);//列宽
//            st.getSettings().setDefaultRowHeight(15);//行高
//        指定一种可以用流写入文件的字体(字体类型,字体大小,字体是否加粗)//大标题的样式WritableFont ft=new WritableFont(WritableFont.ARIAL,20,WritableFont.BOLD);
//            指定一种单元格的格式(参数:字体)WritableCellFormat wcf=new WritableCellFormat(ft);wcf.setAlignment(Alignment.CENTRE);//内容居中对齐wcf.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )wcf.setWrap(true);//数据自动换行//普通标题的样式WritableFont f1=new WritableFont(WritableFont.ARIAL,18,WritableFont.BOLD);
//          指定一种单元格的格式(参数:字体)WritableCellFormat wcf1=new WritableCellFormat(f1);wcf1.setAlignment(Alignment.CENTRE);//内容居中对齐wcf1.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )wcf1.setWrap(true);//数据自动换行//内容的样式WritableFont f2=new WritableFont(WritableFont.ARIAL,18);//          指定一种单元格的格式(参数:字体)WritableCellFormat wcf2=new WritableCellFormat(f2);wcf2.setAlignment(Alignment.CENTRE);//内容居中对齐wcf2.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN);//(表格的哪些位置需要加边框,边框的样式 )wcf2.setWrap(true);//数据自动换行/******************指定样式结束************************///添加大标题Label th=new Label(0,0,"学员信息",wcf);st.addCell(th);//合并单元格(开始列下标,开始行下标,结束列下标,结束行下标);st.mergeCells(0,0,7,0);//创建一个标签Label-----它就是每一个单元格要显示的内容Label labid=new Label(0,1,"编号",wcf1);//(列下标,行下标,标签显示的名称,表格的样式)Label labname=new Label(1,1,"姓名",wcf1);Label labage=new Label(2,1,"年龄",wcf1);Label labgender=new Label(3,1,"性别",wcf1);Label labclazz=new Label(4,1,"班级",wcf1);Label labtel=new Label(5,1,"电话",wcf1);Label labtime=new Label(6,1,"注册日期",wcf1);Label labres=new Label(7,1,"备注",wcf1);//将标签放到表单中st.addCell(labid);st.addCell(labname);st.addCell(labage);st.addCell(labgender);st.addCell(labclazz);st.addCell(labtel);st.addCell(labtime);st.addCell(labres);for (int i=0;i<list.size();i++){//获得每一个对象stuInfo stu=list.get(i);Label id=new Label(0,i+2,stu.getSid().toString(),wcf2);Label stuname=new Label(1,i+2,stu.getSname(),wcf2);Label age=new Label(2,i+2,stu.getSage().toString(),wcf2);Label gender=new Label(3,i+2,stu.getSgender(),wcf2);Label sclass=new Label(4,i+2,stu.getSclass(),wcf2);Label tel=new Label(5,i+2,stu.getStel(),wcf2);Label time=new Label(6,i+2,stu.getSregtime(),wcf2);Label res=new Label(7,i+2,stu.getRes(),wcf2);//将标签添加到表单中st.addCell(id);st.addCell(stuname);st.addCell(age);st.addCell(gender);st.addCell(sclass);st.addCell(tel);st.addCell(time);st.addCell(res);}//将工作簿的数据写入到文件中wk.write();//关闭工作簿wk.close();out.close();System.out.println("数据已写入");} catch (Exception e) {e.printStackTrace();}/*******************************************赋值结束*********************************************/}
}

3、servlet的生命周期(理解)

servlet的生命周期分为下列几个阶段:

1、实例化阶段--------只执行1次

​ 调用的构造方法

2、实例初始化阶段--------只执行1次

​ init()

3、服务阶段--------多次执行

​ service()

4、销毁阶段--------只执行1次

​ destroy()

java">servlet生命周期的四个阶段,其中实例化、初始化、销毁只会执行一次,服务阶段会多次将执行

实例:

java">package com.sc.web;import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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("/demo")
public class demoServlet extends HttpServlet {public demoServlet(){System.out.println("1、调用了构造方法实例化servlet..");}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("3、service方法进行服务处理..");super.service(req, res);}@Overridepublic void destroy() {System.out.println("4、销毁servlet");super.destroy();}@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("2、调用init方法进行初始化..");super.init(config);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
servlet的执行过程
1、当请求到达服务器,web容器(tomcat)会调用servlet的构造方法创建一个servlet实例2、servlet创建好以后,web容器会马上调用当前servlet的init方法进行初始化3、初始化完成后,web容器会调用当前servlet父类(HttpServlet)类中的service方法进行处理,在该方法中系统会判断请求的请求方式,是post还是get请求,如何根据请求的类型调用servlet类中的doget或者dopost方法进行处理,当请求处理完成以后,当前servlet会驻留在web容器,当下一次请求再一次到达服务器时,web容器就会调用已存在的servlet直接处理,不再创建实例,初始化实例4、直到web容器停止时,web容器会调用servlet的destroy方法,销毁当前的servlet实例

jsp_3197">4、jsp的内置对象

在开发中,如何编写动态网页项目
开发流程:
1、美工会做好静态模型---Demo一般demo中只会包含:html,css,js2、程序员需要将美工提供的静态模型修改成动态页面
      Label sclass=new Label(4,i+2,stu.getSclass(),wcf2);Label tel=new Label(5,i+2,stu.getStel(),wcf2);Label time=new Label(6,i+2,stu.getSregtime(),wcf2);Label res=new Label(7,i+2,stu.getRes(),wcf2);//将标签添加到表单中st.addCell(id);st.addCell(stuname);st.addCell(age);st.addCell(gender);st.addCell(sclass);st.addCell(tel);st.addCell(time);st.addCell(res);}//将工作簿的数据写入到文件中wk.write();//关闭工作簿wk.close();out.close();System.out.println("数据已写入");} catch (Exception e) {e.printStackTrace();}/*******************************************赋值结束*********************************************/}

}

### 3、servlet的生命周期(理解)**servlet的生命周期分为下列几个阶段:****1、实例化阶段**--------只执行1次​		 调用的构造方法**2、实例初始化阶段**--------只执行1次​		 init()**3、服务阶段**--------多次执行​		 service()**4、销毁阶段**--------只执行1次​		destroy()```java
servlet生命周期的四个阶段,其中实例化、初始化、销毁只会执行一次,服务阶段会多次将执行

实例:

java">package com.sc.web;import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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("/demo")
public class demoServlet extends HttpServlet {public demoServlet(){System.out.println("1、调用了构造方法实例化servlet..");}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {System.out.println("3、service方法进行服务处理..");super.service(req, res);}@Overridepublic void destroy() {System.out.println("4、销毁servlet");super.destroy();}@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("2、调用init方法进行初始化..");super.init(config);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
servlet的执行过程
1、当请求到达服务器,web容器(tomcat)会调用servlet的构造方法创建一个servlet实例2、servlet创建好以后,web容器会马上调用当前servlet的init方法进行初始化3、初始化完成后,web容器会调用当前servlet父类(HttpServlet)类中的service方法进行处理,在该方法中系统会判断请求的请求方式,是post还是get请求,如何根据请求的类型调用servlet类中的doget或者dopost方法进行处理,当请求处理完成以后,当前servlet会驻留在web容器,当下一次请求再一次到达服务器时,web容器就会调用已存在的servlet直接处理,不再创建实例,初始化实例4、直到web容器停止时,web容器会调用servlet的destroy方法,销毁当前的servlet实例

jsp_3336">4、jsp的内置对象

在开发中,如何编写动态网页项目
开发流程:
1、美工会做好静态模型---Demo一般demo中只会包含:html,css,js2、程序员需要将美工提供的静态模型修改成动态页面

http://www.ppmy.cn/news/1446383.html

相关文章

Git和SVN有什么区别?

Git和SVN都是版本控制系统&#xff0c;它们都是用来帮助团队协同开发&#xff0c;管理代码版本的。但是&#xff0c;git和svn在实现方式&#xff0c;使用方法&#xff0c;特性等方面都存在一些差异 分布式 vs 集中式 这是二者之间最大的区别。Git是分布式版本控制系统&#xff…

数据库管理工具

Heidisql HeidiSQL是一款简洁的图形化的数据库管理工具&#xff0c;支持MySQL、SQLServer、PostgreSQL、SQLite等多种数据库。HeidiSQL提供了一个用于在数据库浏览之间切换 SQL 查询和标签带有语法突出显示的简单易用的界面。其它功能包括BLOB 和 MEMO 编辑&#xff0c;大型SQ…

美国站群服务器常见的操作系统选项

美国站群服务器常见的操作系统选项 美国站群服务器是一种灵活且可扩展的服务器解决方案&#xff0c;可以用于托管和管理多个网站和应用程序。在选择合适的美国站群服务器时&#xff0c;一个重要的考虑因素是其支持的操作系统。本文将介绍美国站群服务器常见的操作系统选项&…

【云原生】Docker 实践(三):使用 Dockerfile 文件构建镜像

Docker 实践&#xff08;三&#xff09;&#xff1a;使用 Dockerfile 文件构建镜像 1.使用 Dockerfile 文件构建镜像2.Dockerfile 文件详解 1.使用 Dockerfile 文件构建镜像 Dockerfile 是一个文本文件&#xff0c;其中包含了一条条的指令&#xff0c;每一条指令都用于构建镜像…

创造未来知识管理新篇章:Ollama与AnythingLLM联手打造个人与企业的安全知识库!

一 Ollama 1.1 简介 Ollama是一个开源的大型语言模型服务工具,它帮助用户快速在本地运行大模型。通过简单的安装指令,用户可以执行一条命令就在本地运行开源大型语言模型,如Llama 2。Ollama极大地简化了在Docker容器内部署和管理LLM的过程,使得用户能够快速地在本地运行大…

计算机视觉(CV)简介

计算机视觉&#xff08;CV&#xff09;技术是一种在计算机中模拟人类视觉和图像处理能力的技术。它可以从图像和视频中提取有用的信息&#xff0c;并进行分析和理解。以下是计算机视觉技术的优势和挑战的一些例子&#xff1a; 优势&#xff1a; 高效处理大量图像数据&#xff…

【springMVC】@RequestMapping的作用

1.作用 将指定 URL 的请求绑定到一个特定的方法或类上&#xff0c;从而实现对请求的处理和响应。 RequestMapping注解只能出现在类上或者方法上。 2.value属性 Ant风格的value&#xff08;模糊匹配路径&#xff09;&#xff1a; 1&#xff09;?&#xff0c;代表任意一个字符 …

ThinkPHP8 导出Excel数据表格

1、开发版本 Think PHP8.0、PHP8.0&#xff0c;并非低版不能用&#xff0c;仅因本人当前版本如此。 部分参数需自行进行修改&#xff0c;具体查看执行代码. Excel有默认的表格样式&#xff0c;如需修改&#xff0c;根据实际应用场景进行设置即可。 2、实现原理 1.安装Spre…