第三次总结

Servlet入门

HTTP响应中有HTML等数据,请求中有什么?

HTTP协议有许多方法,最常用的是GET与POST

  • GET请求:请求的数据将直接放在URL后明文传输,以?分隔,各参数之间以&分隔

  • POST请求:将数据放在"消息体"或者"负载"中,这个消息体可以非常大

当请求到来时,需要有人来实例化Servlet,有人来调用Servlet的doPost()或doGet()方法,以及重要的参数——HTTP请求和HTTP响应对象.这个人就是Web容器.

servlet没有main()方法,它们受控于另一个Java应用,即容器,如Tomcat.Web服务器应用(如Apache)得到一个指向servlet的请求,服务器并不是把这个请求交给servlet本身,而是交给部署该servlet的容器,由容器向servlet提供HTTP请求和响应,且由容器调用servlet的方法.

具体过程:

用户点击一个链接,指向一个servlet ==> 容器创建两个对象:HttpServletResponseHttpServletRequest ==> 容器根据请求中的URL找到servlet,为这个请求创建或分配一个线程,并把请求和响应对象传递给这个进程(init()方法被调用,可以覆盖,如获取数据库连接) ==> 容器调用servlet的service()方法,根据请求的不同类型,service()方法会调用doGet()doPost()方法, doGet()doPost()方法作相应的处理(Servlet的一生主要都在这里度过) ==> 线程结束,容器把响应对象转换为HTTP响应,发回给用户,然后删除请求和响应对象(destroy()方法被调用)

Servlet中有什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet("/HelloWorldServlet")
public class LoginServlet extends javax.servlet.http.HttpServlet {

@Override
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) {

}

@Override
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
}

这里没有service()方法,是因为service()方法是从javax.servlet.http.HttpServlet中继承来的

Get请求是幂等的,而Post请求不是.即重复的Post请求可能会造成不好的后果,如购物结算时重复提交post会购买两次.而Get请求重复提交不会产生副作用,因此需要设计代码以应对重复提交Post请求

从请求中获取参数:

获取单个参数对应的单个值:

1
request.getParameter() //返回值为一个值

获取像复选框这样的一个参数对应多个值:

1
request.getParameterValues() //返回值为一个数组

向响应中传输数据:

大多数情况下使用响应是为了向客户发回数据.会对响应调用两个方法:setContentType()getWriter().在此之后,只需要完成I/O将html或者其他内容写到流中.比如向客户发送一个JAR:

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 servlet.DownloadServlet;

import javax.servlet.ServletContext;
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.io.InputStream;
import java.io.OutputStream;

/*
* @author Sheng WenZeng
* @Date 2019/7/27 16:41
* @Version 1.0
*/
@WebServlet(name = "DownloadCodeServlet")
public class DownloadCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//告诉浏览器这是一个JAR而不是HTML
response.setContentType("application/jar");
//从资源中获取输入流
ServletContext ctx = getServletContext();
InputStream is = ctx.getResourceAsStream("/resources/code/java");
int read = 0;
byte[] bytes = new byte[1024];
//将文件写到从响应对象得到的输出流中
OutputStream os = response.getOutputStream();
while ((read = is.read(bytes)) != -1) {
os.write(bytes, 0, read);
}
os.flush();
os.close();
}
}
  • response.setContentType("application/jar");这一行是告诉浏览器你要发回什么,这样浏览器才能有正确的处理.

    常用的MIME类型:

    • text/html
    • application/pdf
    • video/quicktime
    • application/java
    • image/jpeg
    • application/jar
    • application/octet-stream
    • application/x-zip

更多见:MIME 参考手册

  • 对于输出,有两个选择:字符或者字节

    ServletReponse接口只提供了两个可以选择的流:

    • ServletOutputStream用于输出字节
    • PrintWriter用于输出字符数据

    PrintWriter:

    1
    2
    PrintWriter writer = response.getWriter();
    whiter.println("some text and html");

    用于将文本数据打印到字符流,专门用来处理字符数据

    OutputStream:

    1
    2
    ServletOutputStream out = response.getOutputStream();
    out.write(aByteArray);

    用于写其他的所有内容

    PrintWriter实际上包装了ServletOutputStream.但是PrintWriter会装饰这个流使其对字符支持更好

事实上可以直接写一个指向JAR的链接,这样就无需经过servlet.但是如果需要执行更多的代码,比如判断该用户是否有权下载这个JAR,就需要经过servlet来判断.

Redis基本操作

下载安装包:

1
wget http://download.redis.io/releases/redis-5.0.5.tar.gz

解压:

1
tar -zcvf redis-5.0.5.tar.gz

编译:

1
2
cd redis-5.0.5.tar.gz
make

安装到指定目录:

1
make install PREFIX=/usr/local/redis

redis.conf文件复制到/usr/local/中:

1
cp redis.conf /user/local

配置redis.conf:

1
vim redis.conf

基本配置主要修改三处,其保持默认即可使用:

  • daemonize no改为daemonize yes,以守护进程方式运行
  • bind:127.0.0.1这一句注释掉
  • 找到requirepass,将这一句取消注释,并修改为自己的密码,即requirepass 你的密码

运行服务端:

1
2
cd /usr/local/redis
./bin/redis-server ./redis.conf

查看服务端运行状态:

1
ps aux|grep redis

基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
redis-cli --raw
set key value #设置key
get key #获得key,不存在返回nil
del key #删除key
exists key #查询某个key是否存在,1为存在,0为不存在
ttl key #查询有效时间,-1表示永久有效,-2表示过期(会自动删除).因此ttl key返回值为-2表示该值不存在(单位:秒)
pttl key #查询有效时间,-1表示永久有效,-2表示过期(会自动删除).因此ttl key返回值为-2表示该值不存在(单位:毫秒)
expire key seconds #为key设置过期时间(单位:秒)
pexpire key milliseconds #为key设置过期时间(单位:毫秒)
persist key #移除key的过期时间,key将永久有效
keys patten #查询
select 1 #切换到第二个数据库,默认在第零个数据库
rename key newkey #重命名key
move key db #将当前数据库key移动到指定数据库中
type key #查询key的数据类型

Maven入门

1. 检查JDK安装

在安装Maven之前,首先要确认安装了JDK.

2. 下载Maven

点击下载apache-maven-3.6.1-bin.zip,解压文件到指定目录,设置环境变量

3. Maven使用入门

3.1 编写pom.xml

Maven的核心文件是pom.xml.POM(Project Object Model)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等等.

以下为一个pom.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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>club.swzdl.wechatminiprogram</groupId>
<artifactId>wechatminiprogram</artifactId>
<version>1.0-SNAPSHOT</version>
<name>WeChatMiniProgram</name>

<dependencies>
<!--json-lib-->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>

<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

<!--JUnit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>

</dependencies>


<build>
<finalName>WeChatMiniProgram</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>

</pluginManagement>
</build>

</project>
  • 第一行是XML头,指定该XML文档的版本和编码方式.

  • 紧接着是project元素,是所有pom.xml的根元素,声明一些POM相关的命名空间和xsd元素,不是必须的,但是能够让第三方工具帮助我们快速编辑POM.

  • 根元素下的第一个子元素modelVersion指定了当前POM模型的版本,对于Maven2和Maven3,只能是4.0.0

  • 最重要的是包含groupId、artifactId和version的三行.这三个元素定义了一个项目基本的坐标.

    • groupId:定义项目属于哪个组,这个组往往和项目所在的组织或公司存在关联.如果你的公司是mycom,有一个项目是myapp,那么groupId就应该是com.mycom.myapp
    • artifactId:定义当前Maven项目在组中唯一的ID.在myapp中可能为不同的子项目(模块)分配不artifactId,如myapp-util,myapp-web等
    • version:定义当前项目的版本.
    • name:声明了一个对用户更为友好的项目名称,虽然不是必须的,但是推荐使用以方便交流
  • 添加依赖:<dependencies>元素中可以包含多个<dependency>元素以声明项目的依赖.通过groupId,artifactId,version定位一个jar,Maven将从中央仓库下载.JUnit依赖中的<scope>表示依赖范围,如果依赖范围为test,则表示该依赖只对测试有效.如果不声明依赖范围,默认值为compile,表示对主代码和测试代码都有效.

3.2 打包和运行

pom中没有指定打包类型,则使用默认打包类型jar.

1
mvn clean package

执行该命令后,将获得项目的jar包,可以将该jar包复制到其他项目的Classpath中以使用该jar包.

但是如何让其他的Maven项目引用这个jar呢?

需要一个安装的步骤:

1
mvn clean install

此时这个jar包被安装到了本地Maven仓库中.

但是生成的jar包不是可执行的,为了生成可执行的jar包,需要借助maven-shade-plugin,将该插件添加到pom.xml中:

1
2
3
4
5
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.1</version>
</plugin>

然后执行mvn clean install,构建完成后打开target/目录,生成两个jar包,其中original开头的为原始的jar包,另一个为可执行的jar包,执行该jar包:

1
java -jar target ***.jar

3.3 使用Archetype生成项目骨架

手动创建Maven的目录非常麻烦,可以使用maven archetype生成项目的骨架:

如果是Maven 3:

1
mvn archetype:generate

如果是Maven 2:

1
mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-5:generate

4. 项目坐标详解

Maven为各种构件引入了秩序,任何一个构件都必须明确定义其坐标,一组Maven坐标通过一些元素定义,分别是:groupId,artifactId,version,packaging,classifier.

  • groupId:定义当前Maven项目隶属的实际项目,一般为域名反向对应.注意要定义到项目级别而不应该只定义到组织级别.如com.sonatype.nexus,而不是com.sonatype
  • artifactId:定义实际项目中的一个Maven项目(模块),使用实际项目名称作为其前缀,如nexus-indexer,使用实际项目名nexus作为前缀.这样的好处是方便寻找构件.
  • version:定义Maven项目当前所处的版本.版本管理后面介绍.
  • packaging:定义Maven的打包方式,默认值为jar
  • artifactId:用来帮助定义构建输出的一些附属构件.不能直接定义项目的classifier,因为附属构件不是项目直接默认生成的,而是由附加的插件帮助生成.

以上五个元素,groupId,artifactId,version为必须定义的,packaging为可选的,classifier是不可直接定义的

5. 依赖的配置

1
2
3
4
5
6
7
8
9
<dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<artifactId>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
  • groupId,artifactId,artifactId:基本坐标
  • type:依赖的类型,对应于项目坐标定义的packaging,大部分情况下该元素不必声明,其默认值为jar
  • scope:依赖的范围
  • optional:标记依赖是否可选
  • exclusions:用来排除传递性依赖

大部分依赖声明只包含基本坐标,在一些特殊情况下,其他元素至关重要.对其他元素将在后面的文章介绍

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×