Linux

前期准备(软件安装管家下载安装步骤)

  1. VMware虚拟机(VMware 12)
  2. CentOs 6 64位

linux目录结构分析

  • Linux目录结构: 只有1个根目录

usr::   用于存放共享的系统资源(c:program Files)
etc:    存放系统配置文件
root:   **系统管理员默认用户目录(c:用户/root)
**home(安装软件目录):
  其他用户目录(c:用户/home/其他用户)

  • 基础命令:

pwd:  打印当前目录
cd /:  切换当前目录
ll:  查看当前目录下的内容


SecureCRT连接linux

  1. 在linux的终端输入:ifconfig(windows是ipconfig)–选择里面的 192.168.21.128

  1. 点击SecureCRT.exe–点击文件–连接–快速选择–输入主机名:192.168.21.128(第一步获取的)

  1. 提示新建主机密钥点击接收并保存–输入用户名root和linux当时的用户密码

  1. 弹出连接成功的框(乱码)–然后关闭之后重启–对网络右键属性–更改外观里面的语言为UTF-8

  1. 输入ll显示(无乱码)


展示目录 ll / ls

1. ls **  显示目录下所有文件名称**

2. ls -a **  显示目录下所有文件名称(包括隐藏文件)**

3. ls -l / ll **  显示目录下所有文件的详细内容**


切换目录 cd

1. cd ~ **  切换到root目录**

2. cd - **  切换到上次访问**的目录

3. cd .. **  **回退到上一层目录

4. cd /xx/yy **  可以一次性直接到xx目录下的yy目录**(也可以一层一层找)


创建目录 mkdir (-p)#

1. mkdir xxx **  **创建一个xxx文件夹

2. mkdir -p aaa/bbb **  **创建多级目录文件


移除目录 rmdir

1. rmdir xxx **  **移除一个文件夹


浏览文件 cat more less tail#

cat(一次性展示)

1.cat xxx ** 文档内容  **一次性展示

more(按%展示)

1. more install.log **  文档进行分页展示**

空格:一页一页展示
回车:一行一行
Q:退出

less(按照%展示)

1. less install.log **  文档进行分页展示**

空格:一页一页展示
回车:一行一行
Q/ctrl+c:退出
键盘上下键:可以上下翻页 (区别于more)

tail(具体看某几行 (-n))

1. tail -n install.log **  查看倒数n行的文档内容**


复制文件 cp

1. cp xxx yyy **  **将xxx复制到yyy目录里面

2. cp xxx yyy/zzz **  **将xxx复制到yyy目录的时候更改名为zzz


拷贝(剪切)文件 mv#

*1. mv a.txt /root/bb *  将当前目录下的a.txt剪切到bb目录

*2. mv a.txt /root/bb/b.txt *  将当前目录下的a.txt剪切到bb目录并且命名改为b.txt


删除文件 rm (-rf)

1. rm -r xxx  删除xxx文件

rm -f xxx  不询问的删除xxx文件
rm -r xxx  询问的删除xxx文件
rm -rf xxx 不询问的删除xxx文件(配合使用)


创建空文件 touch#

1. touch xxx.txt  创建一个空文件


压缩文件 tar -zcvf#

压缩和解压文件所需要的属性:

-c:创建一个新的tar文件
-v:显示运行过程中的信息
-f:指定文件名
-x:解开tar文件
-z:调用gzip压缩命令进行压缩
-t:查看压缩文件内容

1. tar -cvf xxx.tar ./* **  **打包

2. tar -zcvf xxx.tar ./* **  **打包并且压缩


解压文件 tar -zxvf

1. tar -xvf xxx.tar

2. tar -zxvf xxx.tar.gz -C /usr/aaa  解压 (linux压缩包后缀是gz) -C是减压到 usr的aaa目录


查找文件位置 find

1. find / -name “ins”  查找名字以ins开头的文件

2. find / -user xxx -ls  查找用户为xxx的目录


查找文件内容 grep

1. grep lang xxx  在文件中查找lang

2. grep lang xxx -color **  **高亮显示


重定向输出 >(覆盖) >>(覆盖)

1. cat aaa > bbb aaa的覆盖bbb

2. cat aaa >> bbb aaa内容追加到bbb


系统管理命令

1. ps -ef **  查看所有**进程

2. ps -ef | grep ssh **  查看某一**进程

3. kill -9 xxxx **  **强制杀死xxxx编号的进程

4. kill xxxx  杀死xxxx编号的进程


ServletContext

一、ServletContext(Servlet 上下文)

每个web工程都只有一个ServletContext对象。 说白了也就是不管在哪个servlet里面,获取到的这个类的对象都是同一个。

举例步骤:新建一个项目–java Resources–src右键新建Servlet–填写类名和包名

自动生成代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package servleter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class ServletContext01
*/
public class ServletContext01 extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public ServletContext01() {
super();
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

}

###如何得到对象(和ServletConfig相似)

//1. 获取对象
    ServletContext context = getServletContext();

二、ServletContext获取全局参数

ServletConfig----在servlet里面对<init-paramd>写具体的参数

ServletContext---对根标签servlet外面对<context-param>写全局参数

使用了直接右键server所以不用自己配

web.xml的完整内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>ServletRegister</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<context-param> //在这加context-param标签!!!!!!!!!!!!!!!
<param-name>address</param-name>
<param-value>shenzhen</param-value>
</context-param>

<servlet>
<servlet-name>Demo</servlet-name>
<servlet-class>servlet.Demo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Demo</servlet-name>
<url-pattern>/Demo</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ServletContext01</display-name>
<servlet-name>ServletContext01</servlet-name>
<servlet-class>servleter.ServletContext01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContext01</servlet-name>
<url-pattern>/ServletContext01</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>ServletContext02</display-name>
<servlet-name>ServletContext02</servlet-name>
<servlet-class>servleter.ServletContext02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletContext02</servlet-name>
<url-pattern>/ServletContext02</url-pattern>
</servlet-mapping>
</web-app>

ServletContext01/02代码几乎一样都是创建对象然后输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ServletContext02 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取对象
ServletContext context=getServletContext();
//2.获得address
String address=context.getInitParameter("address");
System.out.println("这是ServletContext02的address="+address);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

01通过浏览器去刷新/02通过eclipse自带的页面浏览器刷新


三、ServletContext获取Web应用中的资源

  1. 获取资源在tomcat里面的绝对路径(getRealpath()方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo04 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取对象
ServletContext context=getServletContext();
String path=context.getRealPath("file/config.properties"); //获取给定的文件在服务器上面的绝对路径 ---如果“”里面没有东西意思就是找到根目录
System.out.println("path="+path);

//1.创建属性对象
Properties properties=new Properties();
InputStream is=new FileInputStream(path); //通过InputStream数据流连接path
properties.load(is); //加载输入流

//3.获取name属性的值
String name=properties.getProperty("name");
System.out.println("name="+name);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

代码结果如下:


  1. ServletContext对象.getResourceAsStream获取资源流对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo04 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//test01();
test02();
}

private void test02() throws IOException {
//1.获取对象
Properties properties=new Properties();
ServletContext context=getServletContext(); //创建ServletContext对象
InputStream is=context.getResourceAsStream("file/config.properties"); //直接写文件路径(不需要path)
properties.load(is); //加载文件
//3.获取name属性的值
String name=properties.getProperty("name");
System.out.println("name22="+name);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

  1. 通过classloader去获取web工程下的资源
  • ServletContext:
      
    a路径:F:\tomcat\apache-tomcat…\wtpwebapps\Demo04

  • ClassLoader:
      
    a路径:F:\tomcat\apache-tomcat…\wtpwebapps\Demo04\WEB-INF\classes

要想让classloader回到Demo03的位置:

1
2
//获得该java文件吧内磨机片的class然后获取到加载这个class的虚拟机中的那个类加载器对象
InputStream is=this.getClass().getClassLoader().getResourceAsStream("../../file/config.properties");

四、ServletContext存取数据

此为web代码框架:

实现界面分析:

步骤:

  1. Client客户端:主要是要有两个html的客户端代码:
    login主要是有三个input标签分别是登录、注册、提交按钮;login_success是用来用href标签弹出网站成功登陆次数(通过ServletContext对象的getAttribute()方法获取loginservlet类中的count值)
  2. server服务器端:主要是两个类:
    CountServlet类只是获取LoginServlet类的ServletContext对象获取count输出
    LoginServlet主要分为两步骤:一是通过request的getParameter方法获取login.html输入的账户密码;二是通过ServletContext()对象的set/getAttribute方法获取和更改登陆成功数字。成功可以通过response的setStatus(302)方法设置状态码,然后通过setHeader方法跳转到预定的login_success.html页面。

LoginServlet类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取数据
String username=request.getParameter("username"); //request 包括请求的信息
String password=request.getParameter("password");
System.out.println(username+password);

//2.校验数据
PrintWriter pw=response.getWriter(); //response 响应数据给浏览器

if("admin".equals(username)&&"123".equals(password))
{
//System.out.println("登陆成功!");
//pw.write("login success..");

//1.成功的次数累计加一
Object obj=getServletContext().getAttribute("count");//使用ServeletContext对象的getAttribute方法获取count数

//默认是0次
int totalCount=0; //计数用
if(obj!=null)
{
totalCount=(int) obj; //如果不为0就把obj强转给计数用的totalCount
}
System.out.println("已经登陆成功的次数是:"+totalCount);

//给count赋新的值
getServletContext().setAttribute("count",totalCount+1); //输出之后可以使用ServletContext对象的setAttribute方法更改count数字(当前输出的数字加一付给count)

//2.跳转到成功的界面
//设置状态码
response.setStatus(302);
//定位----->跳转去 login_success.html
response.setHeader("Location","login_success.html");
}
else
{
System.out.println("登录失败!");
pw.write("login failed..");
}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

CountServlet类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CountServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.取值
int count=(int) getServletContext().getAttribute("count");

//2.输出到界面
response.getWriter().write("当前网站成功登录总次数为"+count+"次");
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

login_success.html代码:

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<h2>登录成功了</h2>
<a href="CountServlet">获取网站登录成功总数 </a> <!--href找的是xml里面 url标签的内容-->
</body>
</html>

login.html代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>请输入以下内容,完成登陆</h2>
<form action="LoginServlet" method="get"> <!--action找的是xml里面 url标签的内容-->
账号:<input type="text" name="username"/><br>
密码:<input type="text" name="password"/><br>
<input type="submit" value="登录"/>
</form>
</body>
</html>

HTTPServletReauest和HTTPServletResponse

一、HTTPServletRequest(这个对象封装了客户端提交过来的一切数据)

  • 获取客户端http请求头信息
1
2
3
4
5
6
7
8
//得到一个枚举集合  
Enumeration<String> headerNames = request.getHeaderNames(); //用集合去存取所有的http头
while (headerNames.hasMoreElements()) {
String name = (String) headerNames.nextElement(); //每次取下一个
String value = request.getHeader(name); //取头就是给它的值
System.out.println(name+"="+value);

}
  • 获取客户端提交的数据
1
2
3
4
5
6
7
8
9
10
//2.获取所有的参数---一个枚举集合(一个key对应多个value)
// Enumeration<String> headerNames = request.getHeaderNames(); //ctrl+1 提示左边的代码 获得所有的http头部
Map<String, String[]> map = request.getParameterMap();
Set<String> keySet = map.keySet(); //得到左边的key
Iterator<String> iterator = keySet.iterator();//得到加载器iterator
while(iterator.hasNext()) {
String key = iterator.next(); //加载器.get方法获得key值
String[] value = map.get(key); //request的对象调用.get方法获取value值
System.out.println("key="+key+" value="+value);
}

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Demo01 extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.得到一个枚举集合
Enumeration<String> headerNames = request.getHeaderNames(); //ctrl+1 提示左边的代码 获得所有的http头部
while(headerNames.hasMoreElements())
{
String name=(String)headerNames.nextElement(); //while一次获取一次的http头部
String value=request.getHeader(name); //获取当对应的http头部的value值
System.out.println("name="+name+" value="+value);
}
System.out.println("--------------");

//获取的是客户端(html登录写的)提交上来的数据
String parameter = request.getParameter("name");
System.out.println("name="+parameter);
System.out.println("--------------");

//2.获取所有的参数---一个枚举集合(一个key对应多个value)
// Enumeration<String> headerNames = request.getHeaderNames(); //ctrl+1 提示左边的代码 获得所有的http头部
Map<String, String[]> map = request.getParameterMap();
Set<String> keySet = map.keySet(); //得到左边的key
Iterator<String> iterator = keySet.iterator();//得到加载器iterator
while(iterator.hasNext()) {
String key = iterator.next(); //加载器.get方法获得key值
String[] value = map.get(key); //request的对象调用.get方法获取value值
System.out.println("key="+key+" value="+value);
}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

此外需要完成一个loginer.html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>请输入以下内容,完成登陆</h2>
<form action="LoginServleter" method="get"> <!--action找的是xml里面 url标签的内容-->
账号:<input type="text" name="username"/><br>
密码:<input type="text" name="password"/><br>
<input type="submit" value="登录"/>
</form>
</body>
</html>

第一个循环出来的是所有的http的头部/然后是输入的账号密码/展示输入的账户密码


二、HTTPServletRequest的中文乱码问题

  由于tomcat收到使用getParameter()方法默认是ISO-8859-1去解码,所以必须要去转换。

1.get方式(前端代码form表单里面是method=”get”)

  • 1.1 通过(username.getBytes(“ISO-8859-1”))去更改
    1
    username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
  • 1.2 在tomcat/conf/server.xml 加上URIEncoding=”utf-8”
    1
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

第一种方式的具体代码(还需要上面的loginer.html代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class LoginServleter extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username=request.getParameter("username"); //request 包括请求的信息
String password=request.getParameter("password");
System.out.println(username+" "+password);

//get请求过来的数据,在url地址栏上已经是编码过的,所以取到的是乱码
//tomcat收到使用getParameter()方法默认是ISO-8859-1去解码

//先让文字回到ISO-8859-1对应的字节数组 , 然后再按utf-8组拼字符串
username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
System.out.println("userName="+username+"==password="+password);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

2.post方式(前端代码form表单里面是method=”post”)

  • 2.1 直接在getParameter方法之前使用一个setCharacterEncoding(“UTF-8”);
  • 1
    2
    request.setCharacterEncoding("UTF-8");
    这行设置一定要写在getParameter之前。

三、HTTPServletResponse(返回数据给客户端)

字符流/字节流方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo02 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOExceptio

//以字符流getWriter
response.getWriter().write("<h1>hello response...</h1>");

//以字节流getOutputStream
response.getOutputStream().write("hello response......".getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

四、HTTPServletResponse 中文乱码问题

###不管是字节流还是字符流,直接使用一行代码就可以了。

1
2
3
response.setContentType("text/html;charset=UTF-8");

然后在写数据即可。

五、下载资源

1.使用超链接的方式下载##

tomcat里面有一个默认的Servlet – DefaultServlet –专门用于处理放在tomcat服务器上的静态资源。

代码框架:
  在WebContent里面放需要下载的资源download文件(准备好的文件)。新建的index.html文件去实现超链接下载。

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="download/aa.jpg">aa.jpg</a><br>
<a href="download/bb.txt">bb.tex</a><br>
<a href="download/cc.rar">cc.rar</a><br>
</body>
</html>

2.手写编码实现

代码框架:

有一个弹窗的操作:

1
2
//让浏览器收到资源,弹出提醒!!!
response.setHeader("Content-Disposition", "attachment; filename="+fileName); //response调用setHeader方法

index.html(客户端)代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

这是tomcat默认的servlet区提供下载:<br>
<a href="download/aa.jpg">aa.jpg</a><br>
<a href="download/bb.txt">bb.txt</a><br>
<a href="download/cc.rar">cc.rar</a><br>


<br>手动编码提供下载。:<br>
<a href="demo01?filename=aa.jpg">aa.jpg</a><br> <!--浏览器后面就是--filename=xxx-->
<a href="demo01?filename=bb.txt">bb.txt</a><br>
<a href="demo01?filename=cc.rar">cc.rar</a><br>

</body>
</html>

demo01代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class demo01 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取要下载的文件
String fileName = request.getParameter("filename"); //使用getParameter获得filename

//2.获取这个文件正在tomcat的绝对路径getRealPath()
String path = getServletContext().getRealPath("download/"+fileName); //使用servletcontext去获得绝对路径(里面写"存放文件的名字/"+fileName)

//让浏览器收到资源,弹出提醒!!!
response.setHeader("Content-Disposition", "attachment; filename="+fileName);

//3.转换成输入流
InputStream is=new FileInputStream(path); //输入流获取
OutputStream os = response.getOutputStream(); //输出流由response获得

int len=0;
byte[]buffer =new byte[1024];
while((len=is.read(buffer))!=-1) //输入流不为-1
{
os.write(buffer,0,len); //有多长写多长
}

os.close(); //关闭
is.close();

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

}

最终结果(可以弹窗)


六、下载资源中文乱码问题

针对浏览器类型,对文件名字做编码处理:

Firefox ---使用的是UBase64 
IE、Chrome ---使用的是URLEncoder

代码结构框架:

1.index.html里面只需要增加一行标签代码即可

1
<a href="demo01?filename=黑马.png">黑马.png</a><br>

2.在上面的基础上新增一个DownLoadUtil类写一个帮助火狐firefox浏览器识别的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package servlet;
import java.io.UnsupportedEncodingException;
import sun.misc.BASE64Encoder;
public class DownLoadUtil {
public static String base64EncodeFileName(String fileName) {
BASE64Encoder base64Encoder = new BASE64Encoder();
try {
return "=?UTF-8?B?"+ new String(base64Encoder.encode(fileName.getBytes("UTF-8"))) + "?=";
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

3.原来的demo01里面需要增加中文编码环节:

主要代码分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//1.获取要下载的文件
String fileName = request.getParameter("filename"); //获取filename
//有中文转成UTF-8格式
fileName=new String(fileName.getBytes("ISO-8859-1"),"UTF-8"); //通过getBytes获得tomcat默认的ISO-8859-1的格式,然后更改为UTF-8

//2.获取这个文件正在tomcat的绝对路径getRealPath()
String path = getServletContext().getRealPath("download/"+fileName);

String clientType = request.getHeader("User-Agent"); //获取当前的用户端类型

if(clientType.contains("Firefox"))
{
fileName = DownLoadUtil.base64EncodeFileName(fileName); //调用DownLoadUtil类(新增的类)的方法
}
else //IE ,或者 Chrome (谷歌浏览器) ,
{
fileName = URLEncoder.encode(fileName,"UTF-8"); //使用URLEncoder类的encode方法更改
}

demo01完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class demo01 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1.获取要下载的文件
String fileName = request.getParameter("filename");
//有中文转成UTF-8格式
fileName=new String(fileName.getBytes("ISO-8859-1"),"UTF-8");

//2.获取这个文件正在tomcat的绝对路径getRealPath()
String path = getServletContext().getRealPath("download/"+fileName);

//获取来访的客户端类型
String clientType = request.getHeader("User-Agent");

if(clientType.contains("Firefox"))
{
fileName = DownLoadUtil.base64EncodeFileName(fileName);
}
else //IE ,或者 Chrome (谷歌浏览器) ,
{
fileName = URLEncoder.encode(fileName,"UTF-8");
}

//让浏览器收到资源,弹出提醒!!!
response.setHeader("Content-Disposition", "attachment; filename="+fileName);

//3.转换成输入流
InputStream is=new FileInputStream(path);
OutputStream os = response.getOutputStream();

int len=0;
byte[]buffer =new byte[1024];
while((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
}
os.close();
is.close();

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

最终黑马.png也可以通过弹窗打开!


七、请求转发(原来的地方)和重定向(去新的地方)

主要代码(跳转)

1
2
3
4
5
6
7
8
9
//早期的写法:
//response.setStatus(302); //添加一个状态
//response.setHeader("Location", "login_success.html"); //成功之后就可以直接跳转到login_success.html页面

//重定向写法:重新定位方向
response.sendRedirect("login_success.html");

//请求转发写法:
request.getRequestDispatcher("login_success.html").forward(request,response);

只展示java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

response.setContentType("text/html;charset=utf-8"); //解决中文乱码问题

String username=request.getParameter("username");
String password=request.getParameter("password");
if("admin".equals(username)&&"123".equals(password))
{
//response.getWriter().write("yes"); //使用字符流 但是要改中文的问题

//早期的写法:
//response.setStatus(302); //添加一个状态
//response.setHeader("Location", "login_success.html"); //成功之后就可以直接跳转到login_success.html页面

//重定向写法:重新定位方向
response.sendRedirect("login_success.html");

//请求转发写法:
request.getRequestDispatcher("login_success.html").forward(request,response);
}
else
{
response.getWriter().write("no");
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

两者之间的区别和联系

区分项目 请求转发(request) 重定位(response)
请求次数 一次(服务器内部帮忙完成) 两次(服务器在第一次请求后悔返回302和一个地址,然后浏览器根据地址去第二次访问)
显示地址 请求的servlet地址(要去哪里) 显示的最后的那个资源的地址(最终跳转的)
跳转路径 只能去自己项目的路径 可以跳转到任意路径
效率 高效(1次) 低效(2次)
*后续请求(上一次的request) * 不可以使用(两次不同请求) 可以使用(同一请求)


Servlet

一、web资源

在http协议当中,规定了请求和响应双方, 客户端和服务器端。与web相关的资源。

  • 静态资源
    html 、 js、 css
  • 动态资源
    servlet/jsp

二、Servlet介绍+创建tomcat配置

  • 其实就是一个java程序,运行在我们的web服务器上,用于接收和响应客户端的http请求。

  • 更多的是配合动态资源来做。 当然静态资源也需要使用到servlet,只不过是Tomcat里面已经定义好了一个DefaultServlet

简单使用Web工程

  1. 切换工作空间(左上角文件–切换工作空间)

  2. 自动打开然后需要配置Tomcat,点开右上角透视图(如图)–JAVAEE

  1. 点击下边输出框的Servers–提示一行NO….–然后空白位置右键new

  1. Apache–tomcat版本7.0

  1. 选定tomcat–下面的Servers里面的tomcat7–右键open–中间Server Locations选中第二个

  1. 新建一个web项目–右键new–other–Web–Dynamic Web Project

  1. 新建一个名字HelloServlet–Dynamic web module version更改为2.5

  1. 在HelloServlet–WebContent新建名为index.html文件

  1. index里面写一个h标签内容–点run as–选自己的tomcat–稍等一会(提前不要打开tomcat)

  1. 可以通过访问网页展示
1
http://localhost:8080/HelloServlet/index.html


三、Servlet操作代码

  1. 在前面的基础上Java Resources–src–新建HelloServer类(实现Server接口)–要实现五个方法(只用改service方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

package server;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServer implements Servlet{
public static void main(String[] args) {

}

@Override
public void destroy() {}

@Override
public ServletConfig getServletConfig() {
return null;
}

@Override
public String getServletInfo() {
return null;
}

@Override
public void init(ServletConfig arg0) throws ServletException {}

@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
System.out.println("helloServlet...");
}

}
  1. 配置Servlet:告诉服务器我们的应用要这么写个servlet

点开WebContent–WFB-INF–lib–web.xml–点击下面框的source更改–然后重启tomcat

1
2
3
4
5
6
7
8
9
10
11
<!--1.向tomcat报告 我有一个XXX类,路径是XXX-->
<servlet> <!--提示报错之后选最后一个servlet-name-->
<servlet-name>HelloServer</servlet-name> <!--提示报错之后选最后一个servlet-class-->
<servlet-class>server.HelloServer</servlet-class> <!--需要写包.类名-->
</servlet>

<!--2.注册servlet的映射,servletName:找到上面注册的具体servlet,url-pattern:在地址栏上的path-->
<servlet-mapping> <!--提示报错之后选最后一个servlet-name-->
<servlet-name>HelloServer</servlet-name>
<url-pattern>/a</url-pattern> <!--一定要记得写/ 实在项目名后写的地址-->
</servlet-mapping>
  1. 地址栏输入http://localhost:8080/项目名称(HelloServlet)/a

执行框会显示类的结果:


四、Servlet 执行过程

执行分析过程:tomcat应用(localhost:8080)–找到项目(HelloServlet)–找到web.xml–找下面的url-pattern的/a–找到servlet-mapping中的servlet-name(类名)–找到上面的servlet-class 然后开始创建该类的实例–实现service方法


五、Servlet的通用写法

Servlet (接口)
    |
    |
GenericServlet
    |
    |
HttpServlet (用于处理http的请求)
  • 定义一个类—继承HttpServlet—复写doGet 和 doPost
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package server;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class shixian extends HttpServlet {

//Get请求会来这个方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get---");
}

//POST请求会来这个方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post----");
}

}


六、Servlet 生命周期

  • init方法

    在创建该servlet的实例时,就执行该方法。
    一个servlet只会初始化一次, init方法只会执行一次
    默认情况下是 : 初次访问该servlet,才会创建实例。 
  • service方法

    只要客户端来了一个请求,那么就执行这个方法了。
      该方法可以被执行很多次。 一次请求,对应一次service方法的调用
  • destroy方法

    servlet销毁的时候,就会执行该方法
    
        1. 该项目从tomcat的里面移除。
        2. 正常关闭tomcat就会执行 shutdown.bat

doGet 和 doPost不算生命周期方法,所谓的生命周期方法是指,从对象的创建到销毁一定会执行的方法, 但是这两个方法,不一定会执行。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package server;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
public class Hello implements Servlet{

///1 (一次)
//在创建servlet实例-->执行的方法
//默认是初次访问servlet,才会创建实例
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("Hello初始化..."); //重启tomcat--浏览器输入http://localhost:8080/HelloServlet/Hello--控制台会输出
}

//2 (多次)
//只要客户端来请求,就执行
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("客户端来请求,service方法已经执行了"); //重启tomcat--浏览器输入http://localhost:8080/HelloServlet/Hello--控制台会输出
}

//3
//用于servlet销毁
///1. 该项目从tomcat的里面移除。
//2. 正常关闭tomcat(shutdown.bat)就会执行
@Override
public void destroy() {
System.out.println("destroy方法已经执行了"); //重启tomcat--浏览器输入http://localhost:8080/HelloServlet/Hello--控制台会输出
}


@Override
public ServletConfig getServletConfig() {
// TODO 自动生成的方法存根
return null;
}

@Override
public String getServletInfo() {
// TODO 自动生成的方法存根
return null;
}

}

七、Servlet创建实例提前(缓解init方法逗留时间太长)

  1. 默认情况下,只有在初次访问servlet的时候,才会执行init方法。 有的时候,我们可能需要在这个方法里面执行一些初始化工作,甚至是做一些比较耗时的逻辑。
  2. 那么这个时候,初次访问,可能会在init方法中逗留太久的时间。 那么有没有方法可以让这个初始化的时机提前一点。
  3. 在配置的时候, 使用load-on-startup元素来指定, 给定的数字越小,启动的时机就越早。 一般不写负数, 从2开始即可。

web.xml里面更改:

1
2
3
4
5
<servlet>
<servlet-name>HelloServlet04</servlet-name>
<servlet-class>com.itheima.servlet.HelloServlet04</servlet-class>
<load-on-startup>2</load-on-startup> //增加这一行
</servlet>

八、ServletConfig(API)

Servlet的配置,—>这个对象,获取servlet配置时的一些信息

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package server;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletConfig extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//ServletConfig -----> 获取servlet配置的信息

//1.得到servlet配置对象
javax.servlet.ServletConfig config=getServletConfig();

//获取servlet里面xml的配置名称servletName
String servletName=config.getServletName();
System.out.println("servletName="+servletName);
System.out.println("-------");

//获取servlet里面具体的某一个参数
String address=config.getInitParameter("address"); //配置文件写的<param-name>address</param-name>
System.out.println("address="+address);
System.out.println("-------");

//遍历取出所有的参数名称
Enumeration<String> names = config.getInitParameterNames(); //ctrl+1--选“将方法给定指定局部变量 ”
while (names.hasMoreElements()) {
String key = (String) names.nextElement();
String value = config.getInitParameter(key);
System.out.println("key==="+key + " value="+value);
}

}

//来了post请求,就让它去执行doGet方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}

}

web.xml配置文件加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!--ServletConfig类的配置文件-->

<servlet> <!--提示报错之后选最后一个servlet-name-->
<servlet-name>ServletConfig</servlet-name> <!--提示报错之后选最后一个servlet-class-->
<servlet-class>server.ServletConfig</servlet-class> <!--需要写包.类名-->

<!-- 添加初始化参数 init-param -->

<init-param>
<param-name>address</param-name>
<param-value>beijing...</param-value>
</init-param>

<init-param>
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>

<init-param>
<param-name>name</param-name>
<param-value>zhangsan</param-value>
</init-param>

</servlet>

<servlet-mapping> <!--提示报错之后选最后一个servlet-name-->
<servlet-name>ServletConfig</servlet-name>
<url-pattern>/ServletConfig</url-pattern>
</servlet-mapping>

重新打开tomcat–浏览器输入http://localhost:8080/HelloServlet/ServletConfig--控制台得到结果


HTTP协议

1.http协议(超文本传输协议)

针对网络上的客户端与服务器端在执行http请求的时候,遵守的一种规范。 其实就是规定了客户端在访问服务器端的时候,要带上哪些东西, 服务器端返回数据的时候,也要带上什么东西。

  • 版本
    1.0—请求数据,服务器返回后,将会断开连接
    1.1—请求数据,服务器返回后,连接还会保持着。 除非服务器|客户端关掉。有一定的时间限制,如果都空着这个连接,那么后面会自己断掉。

1.1 介绍

image-20231222163410552

HTTP:Hyper Text Transfer Protocol(超文本传输协议),规定了浏览器与服务器之间数据传输的规则。

  • http是互联网上应用最为广泛的一种网络协议
  • http协议要求:浏览器在向服务器发送请求数据时,或是服务器在向浏览器发送响应数据时,都必须按照固定的格式进行数据传输

1.2 特点

我们刚才初步认识了HTTP协议,那么我们在看看HTTP协议有哪些特点:

  • *1.基于TCP协议: * 面向连接,安全

    TCP是一种面向连接的(建立连接之前是需要经过三次握手)、可靠的、基于字节流的传输层通信协议,在数据传输方面更安全

  • 2.基于请求-响应模型: 一次请求对应一次响应(先请求后响应)

    请求和响应是一一对应关系,没有请求,就没有响应

  • 3.HTTP协议是无状态协议: 对于数据没有记忆能力。每次请求-响应都是独立的

    无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。

    • 缺点: 多次请求间不能共享数据
    • 优点: 速度快

    请求之间无法共享数据会引发的问题:

    • 如:京东购物。加入购物车和去购物车结算是两次请求
    • 由于HTTP协议的无状态特性,加入购物车请求响应结束后,并未记录加入购物车是何商品
    • 发起去购物车结算的请求后,因为无法获取哪些商品加入了购物车,会导致此次请求无法正确展示数据

    具体使用的时候,我们发现京东是可以正常展示数据的,原因是Java早已考虑到这个问题,并提出了使用会话技术(Cookie、Session)来解决这个问题。具体如何来做,我们后面课程中会讲到。

1.3 Http协议两个分类

浏览器和服务器是按照HTTP协议进行数据通信的。

HTTP协议又分为:请求协议响应协议

  • 请求协议:浏览器将数据以请求格式发送到服务器
    • 包括:请求行请求头请求体
  • 响应协议:服务器将数据以响应格式返回给浏览器
    • 包括:响应行响应头响应体

2.HTTP-请求协议

请求的数据(三部分):请求行、请求头、请求体

image-20231222164414883
  • 请求行(以上图中红色部分):包含请求方式、资源路径、协议/版本
    • 请求方式:POST
    • 资源路径:/brand
    • 协议/版本:HTTP/1.1
  • 请求头(以上图中黄色部分)
  • 请求体(以上图中绿色部分) :存储请求参数
    • 请求体和请求头之间是有一个空行隔开(作用:用于标记请求头结束)

2.1 请求行

image-20231222165531796
  • 请求方式
请求方式 请求说明
GET(最常见) 获取资源。
向特定的资源发出请求。例:http://www.baidu.com/s?wd=itheima
POST(最常见) 传输实体主体。
向指定资源提交数据进行处理请求(例:上传文件),数据被包含在请求体中。
OPTIONS 返回服务器针对特定资源所支持的HTTP请求方式。
因为并不是所有的服务器都支持规定的方法,为了安全有些服务器可能会禁止掉一些方法,例如:DELETE、PUT等。那么OPTIONS就是用来询问服务器支持的方法。
HEAD 获得报文首部。
HEAD方法类似GET方法,但是不同的是HEAD方法不要求返回数据。通常用于确认URI的有效性及资源更新时间等。
PUT 传输文件。
PUT方法用来传输文件。类似FTP协议,文件内容包含在请求报文的实体中,然后请求保存到URL指定的服务器位置。
DELETE 删除文件。
请求服务器删除Request-URI所标识的资源
TRACE 追踪路径。
回显服务器收到的请求,主要用于测试或诊断
CONNECT 要求用隧道协议连接代理。
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
  • 资源路径

资源路径=请求路径?请求参数1=值1&请求参数2=值2

  • 协议/版本

HTTP/1.1等等

2.2 请求头

image-20231222170506433

http是个无状态的协议,所以在请求头设置浏览器的一些自身信息和想要响应的形式。这样服务器在收到信息后,就可以知道是谁,想干什么了

常见的HTTP请求头有:

1
2
3
4
5
6
7
8
9
10
11
12
13
Host: 表示请求的主机名

User-Agent: 浏览器版本。 例如:Chrome浏览器的标识类似Mozilla/5.0 ...Chrome/79 ,IE浏览器的标识类似Mozilla/5.0 (Windows NT ...)like Gecko

Accept:表示浏览器能接收的资源类型,如text/*,image/*或者*/*表示所有;

Accept-Language:表示浏览器偏好的语言,服务器可以据此返回不同语言的网页;

Accept-Encoding:表示浏览器可以支持的压缩类型,例如gzip, deflate等。

Content-Type:请求主体的数据类型

Content-Length:数据主体的大小(单位:字节)

2.3 请求体

image-20231222171056457

2.4 Get和Post的区别

区别方式 GET请求 POST请求
请求参数 请求参数在请求行(第一部分)
例:/brand/findAll?name=OPPO&status=1
请求参数在请求体(第三部分)
请求参数长度 有限制(浏览器不同限制也不同) 没有限制
安全性 安全性低(请求参数暴露在浏览器地址栏中) 安全性相对高

3.HTTP-响应协议

响应的数据(三部分):响应行、响应头、响应体

image-20231222164452936

3.1 响应行

image-20231222171333614

  • 协议

​ http1.1等协议

  • 状态码
状态码分类 说明
1xx 响应中(发送还未结束)——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它
2xx 成功(最希望看到的)——表示请求已经被成功接收,处理已完成(成功了)
3xx 重定向(我这里有问题,给你自动换一个服务器)——重定向到其它地方:它让客户端再发起一个请求以完成整个处理(域名过期,已经为您转到新域名位置)
4xx 客户端错误——处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
5xx 服务器端错误——处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等(后端controller不写@RequestParam注解)
  • 描述

    对响应数据的描述

3.2 响应头

image-20231222171815139

  • 常见的响应头信息:

image-20231222172032115

3.3 响应体

image-20231222171920140

4.HTTP状态码(响应协议)

4.1 状态码大类

状态码分类 说明
1xx 响应中(发送还未结束)——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它
2xx 成功(最希望看到的)——表示请求已经被成功接收,处理已完成(成功了)
3xx 重定向(我这里有问题,给你自动换一个服务器)——重定向到其它地方:它让客户端再发起一个请求以完成整个处理(域名过期,已经为您转到新域名位置)
4xx 客户端错误——处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
5xx 服务器端错误——处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等(后端controller不写@RequestParam注解,mapper写错了sql)

4.2 常见的响应状态码

状态码 英文描述 解释
==200== OK 客户端请求成功,即处理成功,这是我们最想看到的状态码
302 Found 指示所请求的资源已移动到由Location响应头给定的 URL,浏览器会自动重新访问到这个页面
304 Not Modified 告诉客户端,你请求的资源至上次取得后,服务端并未更改,你直接用你本地缓存吧。隐式重定向
400 Bad Request 客户端请求有语法错误,不能被服务器所理解
403 Forbidden 服务器收到请求,但是拒绝提供服务,比如:没有权限访问相关资源
==404== Not Found 请求资源不存在,一般是URL输入有误,或者网站资源被删除了
405 Method Not Allowed 请求方式有误,比如应该用GET请求方式的资源,用了POST
428 Precondition Required 服务器要求有条件的请求,告诉客户端要想访问该资源,必须携带特定的请求头
429 Too Many Requests 指示用户在给定时间内发送了太多请求(“限速”),配合 Retry-After(多长时间后可以请求)响应头一起使用
431 Request Header Fields Too Large 请求头太大,服务器不愿意处理请求,因为它的头部字段太大。请求可以在减少请求头域的大小后重新提交。
==500== Internal Server Error 服务器发生不可预期的错误。服务器出异常了,赶紧看日志去吧
503 Service Unavailable 服务器尚未准备好处理请求,服务器刚刚启动,还未初始化好

状态码大全:https://cloud.tencent.com/developer/chapter/13553

5. HTTP协议解析

image-20231222172249641

Tomcat

1. WEB服务器-Tomcat

1.1 简介

1.1.1 服务器概述

服务器硬件

  • 指的也是计算机,只不过服务器要比我们日常使用的计算机大很多。
image-20231222173448980

服务器,也称伺服器。是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

服务器的构成包括处理器、硬盘、内存、系统总线等,和通用的计算机架构类似,但是由于需要提供高可靠的服务,因此在处理能力、稳定性、可靠性、安全性、可扩展性、可管理性等方面要求较高。

在网络环境下,根据服务器提供的服务类型不同,可分为:文件服务器,数据库服务器,应用程序服务器,WEB服务器等。

服务器只是一台设备,必须安装服务器软件才能提供相应的服务。

服务器软件

服务器软件:基于ServerSocket编写的程序

  • 服务器软件本质是一个运行在服务器设备上的应用程序
  • 能够接收客户端请求,并根据请求给客户端响应数据

image-20231222173608608

1.1.2 Web服务器

Web服务器是一个应用程序(软件),对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作(不用程序员自己写代码去解析http协议规则),让Web开发更加便捷。主要功能是”提供网上信息浏览服务”。

image-20231222173646117

Web服务器是安装在服务器端的一款软件,将来我们把自己写的Web项目部署到Tomcat服务器软件中,当Web服务器软件启动后,部署在Web服务器软件中的页面就可以直接通过浏览器来访问了。

Web服务器软件使用步骤

  • 准备静态资源
  • 下载安装Web服务器软件
  • 将静态资源部署到Web服务器上
  • 启动Web服务器使用浏览器访问对应的资源

第1步:准备静态资源

  • 在提供的资料中找到静态资源文件

image-20231222173726408

第2步:下载安装Web服务器软件

image-20231222173712179

第3步:将静态资源部署到Web服务器上

image-20231222173719630

第4步:启动Web服务器使用浏览器访问对应的资源

image-20231222173734901

浏览器输入:http://localhost:8080/demo/index.html

image-20231222173752168

上述内容在演示的时候,使用的是Apache下的Tomcat软件,至于Tomcat软件如何使用,后面会详细的讲到。而对于Web服务器来说,实现的方案有很多,Tomcat只是其中的一种,而除了Tomcat以外,还有很多优秀的Web服务器,比如:

image-20231222173802921

Tomcat就是一款软件,我们主要是以学习如何去使用为主。具体我们会从以下这些方向去学习:

  1. 简介:初步认识下Tomcat

  2. 基本使用: 安装、卸载、启动、关闭、配置和项目部署,这些都是对Tomcat的基本操作

  3. IDEA中如何创建Maven Web项目

  4. IDEA中如何使用Tomcat,后面这两个都是我们以后开发经常会用到的方式

首选我们来认识下Tomcat。

1.1.3 Tomcat

Tomcat服务器软件是一个免费的开源的web应用服务器。是Apache软件基金会的一个核心项目。由Apache,Sun和其他一些公司及个人共同开发而成。

由于Tomcat只支持Servlet/JSP少量JavaEE规范,所以是一个开源免费的轻量级Web服务器。

JavaEE规范: JavaEE => Java Enterprise Edition(Java企业版)

avaEE规范就是指Java企业级开发的技术规范总和。包含13项技术规范:JDBC、JNDI、EJB、RMI、JSP、Servlet、XML、JMS、Java IDL、JTS、JTA、JavaMail、JAF

因为Tomcat支持Servlet/JSP规范,所以Tomcat也被称为Web容器、Servlet容器。JavaWeb程序需要依赖Tomcat才能运行。

Tomcat的官网: https://tomcat.apache.org/

image-20231222173824051

1.2 基本使用

1.2.1 下载

直接从官方网站下载:https://tomcat.apache.org/download-90.cgi

image-20231222173909174

Tomcat软件类型说明:

  • tar.gz文件,是linux和mac操作系统下的压缩版本
  • zip文件,是window操作系统下压缩版本(我们选择zip文件)

大家可以自行下载,也可以直接使用资料中已经下载好的资源,

Tomcat的软件程序 :/资料/SpringbootWeb/apache-tomcat-9.0.27-windows-x64.zip

image-20231222173921491

1.2.2 安装与卸载

  • 安装: Tomcat是绿色版,直接解压即安装

在E盘的develop目录下,将apache-tomcat-9.0.27-windows-x64.zip进行解压缩,会得到一个apache-tomcat-9.0.27的目录,Tomcat就已经安装成功。

image-20231222173945563

==注意,Tomcat在解压缩的时候,解压所在的目录可以任意,但最好解压到一个不包含中文和空格的目录,因为后期在部署项目的时候,如果路径有中文或者空格可能会导致程序部署失败。==

打开apache-tomcat-9.0.27目录就能看到如下目录结构,每个目录中包含的内容需要认识下

image-20231222173958288

bin:目录下有两类文件,一种是以.bat结尾的,是Windows系统的可执行文件,一种是以.sh结尾的,是Linux系统的可执行文件。

webapps:就是以后项目部署的目录

  • 卸载:卸载比较简单,可以直接删除目录即可

1.2.3 启动与关闭

启动Tomcat

  • 双击tomcat解压目录/bin/startup.bat文件即可启动tomcat
image-20231222174200134

==注意: tomcat服务器启动后,黑窗口不会关闭,只要黑窗口不关闭,就证明tomcat服务器正在运行==

image-20231222174211676

Tomcat的默认端口为8080,所以在浏览器的地址栏输入:http://127.0.0.1:8080 即可访问tomcat服务器

127.0.0.1 也可以使用localhost代替。如:http://localhost:8080

  • 能看到以上图片中Apache Tomcat的内容就说明Tomcat已经启动成功

==注意事项== :Tomcat启动的过程中,遇到控制台有中文乱码时,可以通常修改conf/logging.prooperties文件解决

image-20231222174239235

关闭: 关闭有三种方式

1、强制关闭:直接x掉Tomcat窗口(不建议)

2、正常关闭:bin\shutdown.bat

3、正常关闭:在Tomcat启动窗口中按下 Ctrl+C

  • 说明:如果按下Ctrl+C没有反映,可以多按几次

1.2.4 常见问题

问题1:Tomcat启动时,窗口一闪而过

  • 检查JAVA_HOME环境变量是否正确配置
image-20231222174300794

问题2:端口号冲突

image-20231222174308683

  • 发生问题的原因:Tomcat使用的端口被占用了。

  • 解决方案:换Tomcat端口号

    • 要想修改Tomcat启动的端口号,需要修改 conf/server.xml文件

注: HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat时,将不用输入端口号。

dom4j入门

一、XML解析方式(面试考点)

其实就是获取元素里面的字符数据或者属性数据

其中常用的两种解析方式:

  • DOM
  • SAX

DOM(document object model)

将整个xml全部读到内存当中,形成树形结构(所有的对象都叫做Node节点。)

整个文档---document对象
属性(标签内描述属性)---attribute对象
所有元素节点(stu/name/age等标签)---element对象
文本(文字等描述)---text对象

SAX(simple API for Xml)

基于事件驱动(读一行解析一行)


二、针对两种解析方式的API(Dom4j 入门)

  • jaxp sun公司(比较繁琐)
  • jdom
  • dom4j 使用广泛

Dom4j 基本用法(导入jar)

1.创建SAXReader对象

1
SAXReader reader=new SAXReader();

2.指定解析的xml原地址(SAXReader调用read方法)

1
Document document=reader.read(new File("src/xml/demo.xml"));  //整个文档叫做document对象

3.获取根元素(文档document对象调用getRootElement方法)

1
Element rootElement=document.getRootElement();

4.根据根元素—下面的元素

element.element  //一个stu元素
element.elements();  //所有stu元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//得到根元素的子元素 age (找两层element)
rootElement.element("stu").element("age");

//得到根元素下面的所有子元素(所有的stu)
List<Element> elements=rootElement.elements(); //泛型(stu/name/age)返回子元素stu

//遍历所有的stu元素
for(Element element :elements)
{
//获取stu元素下面的name元素
String name = element.element("name").getText();
String age = element.element("age").getText();
String desc = element.element("desc").getText();
System.out.println("name="+name+" age+"+age+" desc="+desc);
}

具体实现::

demo.xml内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>李四</name>
<age>15</age>
<desc>我是老大</desc>
</stu>

<stu>
<name>网名</name>
<age>15</age>
<desc>我是老大</desc>
</stu>

</stus>

MainTest.java实现类内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package xml;
import java.io.File;
import java.util.List;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.sun.xml.internal.txw2.Document;
public class MainTest {
public static void main(String[] args){
//1.创建sax读取对象
SAXReader reader=new SAXReader();

try {
//2.指定解析的xml源
org.dom4j.Document document=reader.read(new File("src/xml/demo.xml")); //整个文档叫做document对象

//3.得到元素(element)

//得到根元素 getRootElement
Element rootElement=document.getRootElement();

//得到根元素的子元素 age (找两层element)
rootElement.element("stu").element("age");

//得到根元素下面的所有子元素(所有的stu)
List<Element> elements=rootElement.elements(); //泛型(stu/name/age)返回子元素stu

//遍历所有的stu元素
for(Element element :elements)
{
//获取stu元素下面的name元素
String name = element.element("name").getText();
String age = element.element("age").getText();
String desc = element.element("desc").getText();
System.out.println("name="+name+" age+"+age+" desc="+desc);
}

} catch (DocumentException e) {

e.printStackTrace();
}

}
}

通过泛型遍历所有的文本text内容(getText())


三 、Dom4j中的Xpath入门(导入jar)

dom4j里面支持Xpath的写法。 xpath其实是xml的路径语言,支持我们在解析xml的时候,能够快速定位到具体的某一个元素。

  • 不同之处:

如果需要获得单个的name:

1
2
3
4
5
Dom4j里面是根节点.element()方法:
rootElement.element("stu").element("age");

Xpath里面是根节点.selectSingleNode("具体的//或者/行为")方法;
Element nameElement=(Element) rootElement.selectSingleNode("//name");

如果需要获得所有的name:

1
2
3
4
5
Dom4j里面是根节点.elements()方法:
List<Element> elements=rootElement.elements(); //泛型(stu/name/age)返回子元素stu

Xpath里面是根节点.selectNodes("具体的//或者/行为")方法;
List<Element> elements= rootElement.selectNodes("//name"); //泛型(stu/name/age)返回子元素stu

完整代码如下(xml一样只是展示Xpath的不同):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package xml;
import java.io.File;
import java.util.List;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XpathTest {
public static void main(String[] args){
//1.创建sax读取对象
SAXReader reader=new SAXReader();

try {
//2.指定解析的xml源
org.dom4j.Document document=reader.read(new File("src/xml/demo.xml")); //整个文档叫做document对象

//3.得到元素(element)

//得到根元素 getRootElement
Element rootElement=document.getRootElement();

//要想使用Xpath,还需要支持的jar(获取的是第一个,只返回一个)
Element nameElement=(Element) rootElement.selectSingleNode("//name");
System.out.println(nameElement.getText());

System.out.println("-----------");

List<Element> elements= rootElement.selectNodes("//name"); //泛型(stu/name/age)返回子元素stu
//遍历所有的stu元素
for(Element element :elements)
{
System.out.println(element.getText());
}


} catch (DocumentException e) {
e.printStackTrace();
}

}
}

两者对比如下:


四、XML约束

  • DTD
  • Schema

XML

eXtendsible markup language 可扩展的标记语言

一、Xml简述和作用

作用:

  1. 可以用来保存数据
  2. 做配置文件(Tomcat)
  3. 可以传输载体(客户端和服务器端之间)

结构分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>lisi</name>
<age>15</age>
<desc>我是老大</desc>
</stu>
</stus>

<stus>
<stu>
<name>liming</name>
<age>17</age>
<desc>我是老二</desc>
</stu>
</stus>


二、定义xml

其实就是一个文件,文件的后缀为 .xml

version : 解析这个xml的时候,使用什么版本的解析器解析
               <?xml version="1.0" ?>

encoding : 解析xml中的文字的时候,使用什么编码来翻译
               <?xml version="1.0" encoding="gbk/UTF-8/big5" ?>

   standalone  : no - 该文档会依赖关联其他文档 ,  yes-- 这是一个独立的文档
               <?xml version="1.0" encoding="gbk" standalone="no" ?>

三、encoding详解(UTF-8 万岁!)

默认文件保存的时候,使用的是GBK的编码保存。

所以要想让我们的xml能够正常的显示中文,有两种解决办法

  1. 让encoding也是GBK 或者 gb2312 .

  2. 如果encoding是 utf-8 , 那么保存文件的时候也必须使用utf-8

  3. 保存的时候见到的ANSI 对应的其实是我们的本地编码 GBK。

为了通用,建议使用UTF-8编码保存,以及encoding 都是 utf-8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>lisi</name>
<age>15</age>
<desc>我是老大</desc>
</stu>
</stus>

<stus>
<stu>
<name>liming</name>
<age>17</age>
<desc>我是老二</desc>
</stu>
</stus>

四、XML元素定义(标签)

类似于h5的标签(<>里面的),但是可以**自己写标签!**(可扩展)。

XML 命名规则:

名称可以含字母、数字以及其他的字符 
名称不能以数字或者标点符号开始 
名称不能以字符 “xml”(或者 XML、Xml)开始 
名称不能包含空格 

五、XML属性定义

定义在元素里面, <元素名称 属性名称=”属性的值”></元素名称>

1
2
3
4
5
6
7
8
9
10
11
12
	
<stus>
<stu id="10086">
<name>张三</name>
<age>18</age>
</stu>

<stu id="10087">
<name>李四</name>
<age>28</age>
</stu>
</stus>

六、注释

与html的注释一样。

<!-- --> 
如: 

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 
        //这里有两个学生
        //一个学生,名字叫张三, 年龄18岁, 学号:10086
        //另外一个学生叫李四  。。。
     -->

xml的注释,不允许放置在文档的第一行。 必须在文档声明的下面


七、CDATA区(服务器给客户端返回)

  • 非法字符

    严格地讲,在 XML 中仅有字符 “<”和”&” 是非法的。
    所以用以下两种方式来代替(<&)
    < <
    & &

如果某段字符串里面有过多的字符, 并且里面包含了类似标签或者关键字的这种文字,不想让xml的解析器去解析。 那么可以使用CDATA.

使用 ![CDATA[]]让<a href="http://www.baidu.com">我爱黑马训练营</a>变为普通字符串

1
<des><![CDATA[<a href="http://www.baidu.com">我爱黑马训练营</a>]]></des>
,