html超链接 a 转markdown

超链接如下所示

1
2
<a href="https://www.jb51.net/article/107218.htm" target="_blank" rel="noopener">response.setHeader各种用法详解</a>
<a href="/blog/e6671f57/#response内置对象简介">response内置对象简介</a>

对应的markdown超链接如下所示:

1
[response内置对象简介](/blog/e6671f57/#response内置对象简介)

超链接转markdown比较简单,使用一次正则表达式替换就行了。
匹配正则:<a href="(.+?)".*?>(.+?)<\/a>
替换正则:[$2]($1)

html图片 img 转markdown

1
<img src="https://image-1257720033.cos.ap-shanghai.myqcloud.com/blog/Java/JSP/innerClass/chongdingxiang_zhuanfa/login.png" alt="显示文本">

对应的markdown链接图片链接为:

1
![显示文本](https://image-1257720033.cos.ap-shanghai.myqcloud.com/blog/Java/JSP/innerClass/chongdingxiang_zhuanfa/login.png)

图片与超链接类似,也是一次正则表达式替换就可以搞定:
匹配正则:<img\s*src="(.+?)"\s*alt="(.*?)">
替换正则:![$2]($1)

代码段 code 转markdown

代码段如下所示:

1
<code>request.getRequestDispatcher(&quot;转发的页面&quot;).forward(request,response);</code>

匹配正则:<\/?code>
替换正则:

1
`

逆转义

代码段中会把双引号等特殊字符转义,所以还需要逆转义才能得到真正的markdown代码段:

html加粗 转 markdown

匹配正则:<\/?strong>
替换正则:**

html 标题转markdown

匹配正则:<h2 id=.+?><a href=.+?></a>(.+?)</h2>
替换正则:## $1 ##\n

抓取文章信息

匹配正则

1
.+<div class="post-body".*?>(.+?)<\/div>.+

替换正则

1
$1

精简表格正则##

生成的表格如下,

1
<table><thead><tr><th style="text-align:left">序号</th><th style="text-align:left">方法</th><th style="text-align:left">描述</th></tr></thead><tbody><tr><td style="text-align:left">1</td><td style="text-align:left">String getCharacterEncoding()</td><td style="text-align:left">返回响应用的是何种字符编码</td></tr><tr><td style="text-align:left">2</td><td style="text-align:left">void setContentType(String type)</td><td style="text-align:left">设置响应的MIME类型</td></tr><tr><td style="text-align:left">3</td><td style="text-align:left">PrintWriter getwriter()</td><td style="text-align:left">返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)</td></tr></tbody></table>

转markdown的时候样式是不需要的,先删除样式:

删除内嵌样式

匹配正则

1
(<t[h|d]) style=.*?(>)

替换正则

1
$1$2

替换后的效果:

1
<table><thead><tr><th>序号</th><th>方法</th><th>描述</th></tr></thead><tbody><tr><td>1</td><td>String getCharacterEncoding()</td><td>返回响应用的是何种字符编码</td></tr><tr><td>2</td><td>void setContentType(String type)</td><td>设置响应的MIME类型</td></tr><tr><td>3</td><td>PrintWriter getwriter()</td><td>返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)</td></tr></tbody></table>

生成分割符

匹配正则:

1
(?:<\/t[hd]><t[hd]>|<\/?t[hd]>)

替换正则:

1
|

替换结果

1
<table><thead><tr>|序号|方法|描述|</tr></thead><tbody><tr>|1|String getCharacterEncoding()|返回响应用的是何种字符编码|</tr><tr>|2|void setContentType(String type)|设置响应的MIME类型|</tr><tr>|3|PrintWriter getwriter()|返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)|</tr></tbody></table>

按行分割

匹配正则:<tr>(.+?)</tr>
替换正则:$1\n
替换结果:

1
2
3
4
5
<table><thead>|序号|方法|描述|
</thead><tbody>|1|String getCharacterEncoding()|返回响应用的是何种字符编码|
|2|void setContentType(String type)|设置响应的MIME类型|
|3|PrintWriter getwriter()|返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)|
</tbody></table>

删除其他html多余标签行

匹配正则:

1
<\/?(?:table|thead|tbody)>

**替换正则:**空字符串""
替换结果:

1
2
3
4
5
|序号|方法|描述|
|1|String getCharacterEncoding()|返回响应用的是何种字符编码|
|2|void setContentType(String type)|设置响应的MIME类型|
|3|PrintWriter getwriter()|返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)|

生成对齐方式

剩下的就交给java来解决吧。一行一行的遍历这个字符串,在第二行的时候,把里面的文本替换成对齐方式即可
匹配正则

1
[^|]+\|

替换正则
对齐方式,这里默认为左对齐

1
:--|

java代码

要想单纯的替换第二行,首先要知道现在匹配的是第几次,这里我通过使用计数器来实现。
匹配到第二次的时候,我先获取匹配的文本,然后对修改该文生成一个新的文本(对齐方式)。
接下来就是要使用新的文本替换字符串中旧的文本了,这里使用Matcher.appendReplacement(StringBuffer sb, String replacement)这个方法,这个方法可以在匹配过程中动态的替换,但是与其他替换方法不同,其他替换方法会把替换的结果直接返回,但appendReplacement方法替换后的结果会放在sb参数中。还有就是appendReplacement方法只会把扫描过的文本放到sb中,没有扫描的文本它不管,使用Matcher.appendTail(StringBuffer sb)可以把没有扫描过的文本追加到sb中。这样才真正做到动态的替换。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
StringBuffer sb = new StringBuffer();
int count = 0;
Pattern alignPattern = Pattern.compile("(\\|(?:.+?\\|)+\\n)");
Matcher alignMatcher = alignPattern.matcher(htmlTable);
while (alignMatcher.find())
{
count++;
if (count == 2)
{
// 获取匹配的文本
String align = alignMatcher.group();
// 生成替换的文本
align = align.replaceAll("[^|]+\\|", ":--|");;
// 使用新的替换旧的 然后处理过的文本放到缓存中
alignMatcher.appendReplacement(sb, align);
// 没有扫描过的文本放到缓存中
alignMatcher.appendTail(sb);
break;
}
}

替换结果

1
2
3
4
5
|序号|方法|描述|
|:--|:--|:--|
|1|String getCharacterEncoding()|返回响应用的是何种字符编码|
|2|void setContentType(String type)|设置响应的MIME类型|
|3|PrintWriter getwriter()|返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)|

这样就得到了markdown表格了,显示效果如下:

序号 方法 描述
1 String getCharacterEncoding() 返回响应用的是何种字符编码
2 void setContentType(String type) 设置响应的MIME类型
3 PrintWriter getwriter() 返回可以向客户端输出字符的一个输出流对象(注意比较PrintWriter与内置out对象的区别)

html table转Markdown 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
public static String table2Markdown(String htmlTable)
{
StringBuilder temp = new StringBuilder(htmlTable);
htmlTable = htmlTable
.replaceAll("(<t(?:h|d)) style=\"text\\-align:.*?(>)", "$1$2");
htmlTable = htmlTable.replaceAll(
"(?:<\\/?t(?:h|d)>\\n\\s+<\\/?t(?:h|d)>|<\\/?t(?:h|d)>)", "|");
htmlTable = htmlTable.replaceAll("<\\/?t(?:able|body|r)>", "");
htmlTable = htmlTable.replaceAll("^\\s*<\\/?t(?:able|body|r)>$", "");
htmlTable = htmlTable.replaceAll("(?m)^\\s*$(?:\\n|\\r\\n)+", "");
htmlTable = htmlTable.replaceAll("(?m)^\\s{2,}", "");
htmlTable = htmlTable
.replaceAll("<thead>\\n?((?:\\|.*)|)\\n?<\\/thead>", "$1\n$1");
StringBuffer sb = new StringBuffer();
int count = 0;
Pattern alignPattern = Pattern.compile("(\\|(?:.+?\\|)+\\n)");
Matcher alignMatcher = alignPattern.matcher(htmlTable);
while (alignMatcher.find())
{
count++;
if (count == 2)
{
// 获取匹配的文本
String align = alignMatcher.group();
// 生成替换的文本
align = align.replaceAll("[^|]+\\|", ":--|");;
// 使用新的替换旧的 然后处理过的文本放到缓存中
alignMatcher.appendReplacement(sb, align);
// 没有扫描过的文本放到缓存中
alignMatcher.appendTail(sb);
break;
}
}
return sb.toString();
}

处理文本

hexo next主题 生成的代码块html代码,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
<figure class="highlight plain">
<table>
<tr>
<td class="gutter">
<pre><span class="line">1</span><br></pre>
</td>
<td class="code">
<pre><span class="line">&lt;div class=&quot;post-body&quot;.*?&gt;(.+)&lt;\/div&gt;</span><br></pre>
</td>
</tr>
</table>
</figure>

现在把这段代码转为原生的markdown代码块:

获取代码文本

删除代码块行数

匹配正则

1
<td class="gutter">(\s*.*?)+?<\/td>

替换正则
空字符串
替换结果

1
2
3
4
5
6
7
8
9
10
<figure class="highlight plain">
<table>
<tr>

<td class="code">
<pre><span class="line">&lt;div class=&quot;post-body&quot;.*?&gt;(.+)&lt;\/div&gt;</span><br></pre>
</td>
</tr>
</table>
</figure>

替换换行符

代码文可能有多行,需要把换行符从<br>换成\n:
匹配正则:<br>
替换正则:\n
替换结果:

1
2
3
4
5
6
7
8
9
10
11
<figure class="highlight plain">
<table>
<tr>

<td class="code">
<pre><span class="line">&lt;div class=&quot;post-body&quot;.*?&gt;(.+)&lt;\/div&gt;</span>
</pre>
</td>
</tr>
</table>
</figure>

删除剩下的所有html标签

删除掉行号之后,旧简单了,只要删除掉所有的html标签即可得到代码块中的文本
匹配正则

1
<\/?.*?>

**替换正则:**空字符串
替换结果:

1
2
3
4
5
6
7
8
9
10
11





&lt;div class=&quot;post-body&quot;.*?&gt;(.+)&lt;\/div&gt;





删除空行

匹配正则:^\s*$(\n|\r\n)*
替换正则:"",空字符串
替换结果:

1
2
&lt;div class=&quot;post-body&quot;.*?&gt;(.+)&lt;\/div&gt;

删除多余空白符

匹配正则:^\s{2}
**替换正则:**空字符串
替换结果:

1
2
&lt;div class=&quot;post-body&quot;.*?&gt;(.+)&lt;\/div&gt;

HTML逆转义

我这里没有找到什么好的办法,暂时先使用穷举法来弄,就是把看到的html转移字符逐个进行替换。
<div class="post-body".*?>(.+)</div>
&lt;替换为<
&quot;替换为"
&gt;替换为>

匹配注释

匹配JSP注释

问题描述

写博客经常需要贴代码,但是我不想让代码里面出现太多注释,免得占据太多空间。
用java来复制代码,把代码中的JSP多行注释移除掉。单行注释保留,单行注释作为代码的描述信息。

正则匹配JSP多行注释

1
<%\-\-(?:.*\n)+\s*\-\-%>

匹配Java多行注释 文档注释

问题描述

我之前喜欢把文字(注释)和代码写到一起,但是我现在想把代码描述,从代码中提取出来,放到文章中。但是复制出来的文本带有注释,如先所示:

需求

使用正则表达式删除掉前面的多行注释

匹配正则

1
\s*(?:\/\*{1,2}|\*\/|\*)

图解:

匹配效果:

注意: 正则表达式分支要特别注意分支的顺序,\*\/要写在\*前面,如果写成\s*(?:\/\*{1,2}|\*|\*\/)d的话,匹配注释结束符号的时候会先匹配到单个星号*,正好与第二个分支合适,就不会再匹配/了,如下图所示:

迭代器

迭代器是一种设计模式,Iterator是Java迭代器最简单的实现。它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。
使用集合对象的.iterator()返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。

Iterator的接口

1
2
3
4
5
6
public interface Iterator 
{
boolean hasNext(); //获得序列中的下一个元素。
Object next(); //检查序列中是否还有元素。
void remove(); //将迭代器新返回的元素删除。
}

迭代方法

1
2
3
4
for(Iterator it = c.iterator(); it.hasNext(); ){  
Object o = it.next();
//do something
}

参考链接

https://www.cnblogs.com/hasse/p/5024193.html
http://www.cnblogs.com/lxqiaoyixuan/p/7156944.html

方式1 通过keysSet遍历Map

  • 先通过keySet方法先生成键key的Set集合,
  • 然后再根据Set集合的迭代器从set集合里取出键key
  • 再根据键key 通过 Map 的get(key)方法取出值,这样就取出了键值对:key-value

实例

先设置Map中的数据

1
2
3
4
Map<String, Integer> map2=new HashMap<String,Integer>();
map2.put("山羊", 123);
map2.put("茄子",456);
map2.put("西瓜",789);

通过key来遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
//1 获取Map中key的Set集合
Set<String> keys=map2.keySet();
// 生成key Set集合的迭代器
Iterator<String> its=keys.iterator();
// 遍历 key Set集合
while(its.hasNext())
{
//2 使用迭代器从key Set集合中取出key
String key=its.next();
//3 根据key取出Map中对应的值
int value=map2.get(key);//然后再根据键,取出值
System.out.println("key="+key+" value="+value);
}

方式2 通过Map.Entry对象遍历Map

  • 获取Map的Map.Entry对象的Set集合
  • 然后通过Map.Entry对象的迭代器 从Map.Entry对象的Set集合中,取出一个 Map.Entry对象:
  • 再从该Map.Entry中分别取出key和value

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
//1 获取Map.Entry对象的Set集合
Set<Map.Entry<String, Integer>> mapEntry=map2.entrySet();
//2 Map.Entry对象的Set集合迭代器
Iterator<Map.Entry<String, Integer>> mapEntryIt=mapEntry.iterator();
while(mapEntryIt.hasNext())
{
//2 从Set集合中取出一个 Map.Entry实例
Map.Entry<String, Integer> mapEntryElement=mapEntryIt.next();
//3 分别取出键和值
String key=mapEntryElement.getKey();
Integer value=mapEntryElement.getValue();
System.out.println("key="+key+"value="+value);
}

直接遍历所有的值

1
2
3
4
5
6
7
Collection<Integer> values = map2.values();
Iterator<Integer> it = values.iterator();
while (it.hasNext())
{
int value = it.next();
System.out.println("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
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<textarea rows="5" id="output" style="width:99%;margin-right:auto"></textarea>
<br>
<input type="button" value="变成大写" onclick="daxie()" />&nbsp;
<input type="button" value="变成小写" onclick="xiaoxie()" />&nbsp;
<input type="button" value="生成c语言头文件声明" onclick="cyuyantouwenjianshengming()" />&nbsp;
<input type="button" value="清空输入框" onclick="clean()" />&nbsp;
<input type="button" value="html空格转移符" onclick="HTMLSpase()">&nbsp;
<input type="button" value="转成markdown表格" onclick="mdTableCopy()">&nbsp;
<input type="button" value="正则 java多行注释" onclick="java_annotation()">&nbsp;
<script>
function java_annotation() {
var java_java_doc_annotation = "\\s*(?:\\/\\*{1,2}|\\*\\/|\\*)";
var output = document.getElementById("output");
output.value = java_java_doc_annotation;
copy();
}
function mdTableCopy() {
var input = document.getElementById("output");
var str = input.value;
//删除多余的空白行
str = str.replace(/^\s*$(\n|\r\n)/mg, "");
//在每行行首行尾添加表格分割符竖杠‘|’
str = str.replace(/^(.+)$/mg, "|$1|");
var result = "";
//按行分割,因为我不知道正则匹配怎么写
var array = str.split("\n");
var line = "";
var count = 0;
for (var j = 0, length = array.length; j < length; j++) {
line = array[j];
count++
//在第一行的后面添加markdown表格对齐符号
if (count == 1) {
// console.log("-->"+line);
//获取列数
var cols = line.match(/\S+/g).length;
line = line.replace(/\s+/g, "|");
result += line + "\n";
//生成markdown表格对齐符号
for (var i = 0; i < cols; i++) {
result += "|:---";
}
result += "|\n";
}
//行中的空白符替换为表格分割符
line = line.replace(/\s+/g, "|");
//
if (j < length - 1) {
result += line + "\n";
}
//最后一样不加换行符
else {
result += line;
}
}
//写回文本域
input.value = result;
//复制到剪贴板
copy();
}
function daxie() {
var input = document.getElementById("output");
if (input.value == null || input.value == "") {
alert("请先输入");
return;
}
input.value = input.value.toUpperCase();//变成大写
copy()//复制到剪贴板中
}
function xiaoxie() {
var input = document.getElementById("output");
if (input.value == null || input.value == "") {
alert("请先输入");
return;
}
input.value = input.value.toLowerCase();//变成小写
copy();//复制到剪贴板中
}
function HTMLSpase() {
//&nbsp;
document.getElementById("output").value = "&nbsp;";
copy();
}
function clean() {
document.getElementById("output").value = "";
}
//复制方法
function copy() {
var in_output = document.getElementById("output");
in_output.select(); // 选择对象
document.execCommand("Copy"); // 执行浏览器复制命令
if (confirm("代码已经复制到剪贴板粘贴即可")) {
in_output.value = "";
}
}
function cyuyantouwenjianshengming() {
var input = document.getElementById("output");
var oldValue = input.value;
if (oldValue == null || oldValue == "") {
alert("请先输入头文件名(一个单词)");
return;
}
var isOneWord = /^\w+$/;
if (isOneWord.test(oldValue)) {
var daxie = input.value.toUpperCase();//变成大写
input.value = "//" + oldValue + ".h\n" +
"#ifndef _" + daxie + "_H_ //如果没有引入头文件" + oldValue + ".h\n" +
" #define _" + daxie + "_H_ //那就引入头文件" + oldValue + ".h\n" +
"#endif";
copy();
}
else if (confirm("输入格式错误,是否清空输入框"))
document.getElementById("output").value = "";
}
</script>

参考链接

安装

解压安装包即可安装

安装mysql服务

以管理员身份打开cmd,cd到mysql安装目录下的bin目录:

1
cd C:\Users\lan\Desktop\mysql\数据库\mysql5.5.8\bin

然后输入命令:

1
mysqld -install

安装mysql服务,安装成功命令输出如下:

1
2
3
C:\Users\lan\Desktop\mysql\数据库\mysql5.5.8\bin>mysqld -install
Service successfully installed.
C:\Users\lan\Desktop\mysql\数据库\mysql5.5.8\bin>

启动mysql服务

服务安装后,就可启动mysql了,输入下面的命令启动服务:

1
net start mysql

使用mysql

直接输入命令:

1
mysql

即可进入mysql

验证

输入show databases;查看当前有多少个数据库,看到如下界面表示mysql安装成功了:

mysql用户登录

如使用密码登录root用户:mysql -u root -p,-u 后面表示用户,-p表示让用户输入密码

修改root用户密码

情况1 记得原来root用户的密码

登录root用户

默认的root用户没有密码,现在来设置root用户的密码。

修改密码

1
2
3
use mysql;
update user set password=password('新密码') WHERE User='root';
flush privileges;

如,想把root用户的密码设置为root,则写为:update user set password=password('root') WHERE User='root';

重启服务使新密码生效

1
2
3
exit
net stop mysql
net start mysql

这样就不能只用空密码登录了,只能使用新密码进行登录。

情况2 记不得root用户密码

这种情况,需要修改配置文件,让mysql跳过密码检查。可以直接登录,登录后的密码修改操作还是一样的。

修改my.in登录时跳过密码检查

先退出myql,然后,打卡mysql安装目录下面的my.in文件,这个是mysql的配置文件

在my.ini的[mysqld]字段加入:skip-grant-tables,然后保存。

重启mysql服务

修改配置文件后,管理员下cmd,输入下面两条指令重启mysql服务:

1
2
net stop mysql
net start mysql

直接登录mysql修改密码

现在直接输入mysql就可以登录了,修改密码操作与情况1一样。

其他知识

关闭mysql服务

先关闭服务,然后再删除服务。

1
2
net stop mysql
mysqld -remove

debug

The service already exists

mysqld -install 报错:

1
​The service already exists

原因是之前安装了以后卸载了,服务没删掉。

解决方案

sc query mysql,查看一下名为mysql的服务,如果有,则删除mysql服务。

1
sc delete mysql

然后再安装mysqld -install就能成功了。

参考链接

mysql以zip安装,解决the service already exists

JSP request内置对象

  • request内置对象是 HttpServletRequest 类的实例。
  • request对象封装了由客户端生成的HTTP请求的所有细节,主要包括HTTP头信息、系统信息、请求方式和请求参数等。通过request对象提供的相应方法可以处理客户端浏览器提交的HTTP请求中的各项参数。
  • request对象具有请求域,即完成客户端的请求之前该对象一直有效。

request对象常用方法

获取请求体信息

方法 描述
String getContentType() 得到请求体的MIME类型
int getContentLength() 返回请求体的长度(以字节数)

实例

想要获取请求信息,得先有请求吧。下面先创建请求页面:
login.jsp:

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
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>用户登录</title>
</head>
<body>
<form action="request.jsp" name="loginForm" method="post">
<table>
<tr>
<td align="right">用户名:</td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="reset" value="重置"></td>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>

然后创建request.jsp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html">
<html>
<head>
<meta charset="utf-8">
<title>request内置对象测试</title>
</head>
<body>
<%
out.println("<table border=\"1\">");
out.println("<tr><td align=\"right\">请求体的MIME类型:</td><td>"
+ request.getContentType() + "</td>");
out.println("<tr><td align=\"right\">请求体的长度:</td><td>"
+ request.getContentLength() + " 字节</td>");
out.println("</table>");
%>
</body>
</html>

先在login.jsp中填写表单,点击登录。

会跳转到request.jsp页面,request.jsp显示效果如下:

需要注意的是,post方式才有请求体,get方式没有请求体,参数通过url传递,所以这两个方法将无法获取:

获取表单提交的参数

方法 描述
Enumeration<String> getParameterNames() 返回表单里所有name属性的 属性/属性值枚举
String getParameter(String name) 返回表单name属性对应的属性值
String[] getParameterValues(String name) 根据表单name属性获取多个值,如复选框中的值
Map<String, String[]> getParameterMap() 该返回所提交请求中的请求参数和请求参数值的映射关系

对request.getParameterMap()的返回值使用泛型时应该是Map<String,String[]>形式,因为有时像checkbox这样的组件会有一个name对应对个value的情况。

实例

为了演示效果,修改login.jsp,在其中添加一个复选框,如下:

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
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>用户登录</title>
</head>
<body>
</body>
<form action="request.jsp" name="loginForm" method="post">
<table>
<tr>
<td align="right">用户名:</td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td align="right">爱好:</td>
<td>读书<input type="checkbox" name="hobby" value="book">游戏<input
type="checkbox" name="hobby" value="game">音乐<input
type="checkbox" name="hobby" value="music"></td>
</tr>
<tr>
<td><input type="reset" value="重置"></td>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</html>
枚举方式 遍历表单提交的数据
  • 使用request.getParameterNames();方法获取所有name属性的名称的枚举
  • 有了属性名称之后,我们就可以根据属性名称来获取对应的值了,这里有两种方式
    • 如果该属性名称只有一个值,则使用request.getParameter(name)方法获取对应的属性值
    • 如果该属性名称有多个值(如 复选框),则可以使用request.getParameterValues(name);方法获取属性值数组,然后我们在遍历数组即可。
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
out.println("<table border=\"1\">");
Enumeration<String> names = request.getParameterNames();
String name;
while (names.hasMoreElements())
{
name = names.nextElement();
out.println("<tr><td align=\"right\">" + name + "</td><td>");
//如果是name属性为hobby的情况
if ("hobby".equals(name))
{
//获取hobby多选框中的内容
String[] hobbys = request.getParameterValues(name);
for (int i = 0; i < hobbys.length; i++)
{
//输出分隔符
if (i > 0)
out.print(",");
out.print(hobbys[i]);
}
out.println("</td></tr>");
} else
{
out.println(request.getParameter(name) + "</td></tr>");
}
}
out.println("</table>");
Map方式 遍历表单提交的数据

Map<String, String[]> getParameterMap()这个方法会把表单提交的name属性名称和值封装成一个Map集合返回。可以通过遍历Map集合的方式来遍历表单提交的数据。

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
//获取参数的Map集合
Map<String, String[]> parmMap = request.getParameterMap();
//获取键值对Set集合
Set<Entry<String, String[]>> parmEntrySet = parmMap.entrySet();
//键值对Set集合的迭代器
Iterator<Entry<String, String[]>> parmIt = parmEntrySet.iterator();
String key;
String[] values;
out.println("<table border=\"1\">");
while (parmIt.hasNext())
{
//取得一个键值对
Entry<String, String[]> entry = parmIt.next();
//取出键和值
key = entry.getKey();
out.print("<tr><td align=\"right\">" + key + "</td><td>");
values = entry.getValue();
for (int i = 0; i < values.length; i++)
{
if (i > 0)
out.print(",");
out.print(values[i]);
}
out.print("</td><tr>");
}
out.print("</table>");

完整的request代码如下:

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
<%@page import="org.apache.jasper.tagplugins.jstl.core.ForEach"%>
<%@page import="java.util.Iterator"%>
<%@page import="java.util.Map.Entry"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ page import="java.util.Enumeration,java.util.Map,java.util.Set"%>
<!DOCTYPE html">
<html>
<head>
<meta charset="utf-8">
<title>request内置对象测试</title>
</head>
<body>
<%
out.println("<table border=\"1\">");
Enumeration<String> names = request.getParameterNames();
String name;
while (names.hasMoreElements())
{
name = names.nextElement();
out.println("<tr><td align=\"right\">" + name + "</td><td>");
//如果是name属性为hobby的情况
if ("hobby".equals(name))
{
//获取hobby多选框中的内容
String[] hobbys = request.getParameterValues(name);
for (int i = 0; i < hobbys.length; i++)
{
//输出分隔符
if (i > 0)
out.print(",");
out.print(hobbys[i]);
}
out.println("</td></tr>");
} else
{
out.println(request.getParameter(name) + "</td></tr>");
}
}
out.println("</table>");
out.println("<hr>");
//获取参数的Map集合
Map<String, String[]> parmMap = request.getParameterMap();
//获取键值对Set集合
Set<Entry<String, String[]>> parmEntrySet = parmMap.entrySet();
//键值对Set集合的迭代器
Iterator<Entry<String, String[]>> parmIt = parmEntrySet.iterator();
String key;
String[] values;
out.println("<table border=\"1\">");
while (parmIt.hasNext())
{
//取得一个键值对
Entry<String, String[]> entry = parmIt.next();
//取出键和值
key = entry.getKey();
out.print("<tr><td align=\"right\">" + key + "</td><td>");
values = entry.getValue();
for (int i = 0; i < values.length; i++)
{
if (i > 0)
out.print(",");
out.print(values[i]);
}
out.print("</td><tr>");
}
out.print("</table>");
// request.getParameterNames();
%>
</body>
</html>

运行结果:

操作request对象属性

方法 描述
void setAttribute(String name, object object) 设置属性/属性值到当前请求中。
Object getAttribute(String name) 返回当前请求中设置的属性值
Enumeration getAttributeNames() 返回所有可用属性名的枚举

在进行请求转发时,需要把一些数据传递到转发后的页面进行处理。这时,就需要使用 request对象的 setAttribute()方法将数据保存到 request范围内的变量中。
在将数据保存到 request范围内的变量中后,可以通过 request对象的 getAttribute()方法获取该变量的值.由于getAttribute()方法的返回值为Object类型,所以需要调用其 toString方法

操作编码

方法 描述
String getCharacterEncoding() 返回请求中的字符编码方式
void setCharacterEncoding() 设置请求的字符编码方式

当请求参数的文字编码方式与页面中的文字编码方式不一致会造成中文乱码问题,出现中文乱码时,可以通过setCharacterEncoding()方法把请求参数的编码改成页面的编码。

服务器信息

方法 描述
String getServerName() 返回接受请求的服务器主机名
int getServerPort() 返回服务器接受此请求所用的端口号

客户端信息

方法 描述
String getRemoteHost() 返回客户端的主机名
int getRemotePort() 返回客户端的端口号
String getRemoteAddr()( 返回客户端的IP地址
String getRemoteUser() 返回客户端通过登录认证的用户,若用户未认证则返回null

获取请求头信息

方法 描述
String getHeader(String name) 返回name指定的信息头
Enumeration getHeaderNames() 返回所有HTTP头的名称枚举
Enumeration getHeaders(String name) 返回指定名字的 request Header 的所有值,其结果是一个枚举型的实例

遍历所有HTTP头部信息

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
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Enumeration"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>requestSever相关</title>
</head>
<body>
<%
out.println("<table border=\"1\">");
Enumeration<String> headernames = request.getHeaderNames();
String name;
while (headernames.hasMoreElements())
{
//获取头部名称
name = headernames.nextElement();
//获取名称对应的值
out.println("<tr><td align=\"right\">" + name + ":</td><td>"
+ request.getHeader(name) + "</td></tr>");
}
out.println("</table>");
%>
<%
out.println("<table border=\"1\">");
Enumeration<String> accept = request.getHeaders("user-agent");
String acceptName;
while (accept.hasMoreElements())
{
//获取头部名称
acceptName = (String) accept.nextElement();
//获取名称对应的值
out.println("<tr><td align=\"right\">" + acceptName
+ ":</td></tr>");
}
out.println("</table>");
%>
</body>
</html>

运行效果如下图:

路径

方法 描述
String getContextPath() 返回请求文件的项目路径
String getRealPath(String) 返回当前请求文件的绝对路径,这个方法不推荐使用
1
2
3
4
5
6
7
8
9
10
<table border="1">
<tr>
<td align="right">返回请求文件的项目路径:</td>
<td><%=request.getContextPath()%></td>
</tr>
<tr>
<td align="right">返回当前请求文件的绝对路径:</td>
<td><%=request.getRealPath("requestPath.jsp")%></td>
</tr>
</table>

参考:https://blog.csdn.net/handsome_boy_wsq/article/details/82822186

其他信息

方法 描述
getMethod() 获得客户端向服务器端传送数据的方法,如get、post、 header、 trace等
getRequestURL() 获得发出请求字符串的客户端地址,不包括请求的参数
String getQueryString() 返回此请求的参数
String getProtocol() 返回请求用的协议类型及版本号

实例

创建一个request.jsp的页面,写入如下信息:

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
<%@page import="org.apache.jasper.tagplugins.jstl.core.ForEach"%>
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>request内置对象测试</title>
</head>
<body>
<%--
<%
//解决post提交的数据中的。中文乱码问题.无法解决URL传参方式的中文乱码问题
request.setCharacterEncoding("utf-8");
//解决get提交的数据乱码,可以通过tomcat的config目录下的server.xml配置文件来设置。
%>
--%>
<h2>request内置对象</h2>
获取到用户名:<%=request.getParameter("userName")%>
爱好:<%
String[] hobbys = request.getParameterValues("hobbys");
if (hobbys != null)
{
for (int i = 0; i < hobbys.length; i++)
{
out.println(hobbys[i] + ",");
}
}
%>
密码:<%=request.getParameter("password")%>
</body>
</html>

然后,修改login.jsp。在其中加入一个复选框,并把表单的提交地址改为request.jsp如下所示:

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
<%@ page language="java" contentType="text/html; charset=utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>用户登录</title>
</head>
<body>
</body>
<form action="request.jsp" name="loginForm" method="post">
<table>
<tr>
<td align="right">用户名:</td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td align="right">爱好:</td>
<td>
<input type="checkbox" name="hobbys" value="book">读书
<input type="checkbox" name="hobbys" value="music">音乐
<input type="checkbox" name="hobbys" value="sports">运动
<input type="checkbox" name="hobbys" value="movie">电影
</td>
</tr>
<tr>
<td align="right">密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="reset" value="重置"></td>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</html>

进入登入界面,输入信息,然后点击登录按钮:

此时跳转到request.jsp页面,页面中得到了刚才的输入信息:

当然这种方式,不限于post方法,get方法也可以通过这种方式获取表单提交的数据。

表单输入中文乱码问题

在上面的例子中,如果在login.jsp界面文本框中输入了中文:

request.jsp页面会显示乱码:

post方法乱码解决

对应post方法提交出现的中文乱码,可以通过,request.setCharacterEncoding("请求页面编码");来设置,这里login.jsp页面用的是utf-8编码,所以在request.jsp页面中,在输出文本框的数据之前,设置编码即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<h2>request内置对象</h2>
<%
//解决post提交的数据中的。中文乱码问题.无法解决URL传参方式的中文乱码问题
// request.setCharacterEncoding("ISO-8859-1");
request.setCharacterEncoding("utf-8");
//解决get提交的数据乱码,可以通过tomcat的config目录下的server.xml配置文件来设置。
%>
获取到用户名:<%=request.getParameter("userName")%><br>
爱好:<%
String[] hobbys = request.getParameterValues("hobbys");
if (hobbys != null)
{

for (int i = 0; i < hobbys.length; i++)
{
out.println(hobbys[i] + ",");
}
}
%>
密码:<%=request.getParameter("password")%>
</body>

然后重新输入中文用户名,进行登录就可以看到不会有乱码了:

注意:但是这种方式,只对post方法提交的表单数据有效。

超链接请求传参

我们知道get方法会把参数放在URL里面提交,实际上我们也可以通过超链接的形式来传参。

超链接传参语法

  • 在超链接的后面加上英文半角问号?分割地址与参数。
  • 多个参数(键值对)用单与符号&隔开,
  • 键值对之间用等号=连接。

实例

下面,直接把get方法生成的URL参数直接写到超链接里。这样点击超链接就相当于填写了表单。这便于跳过表单的填写,直接对request.jsp进行测试:

1
<a href="http://localhost:8080/HelloWorld/request.jsp?userName=%E5%B0%8F%E6%98%8E&hobbys=book&password=123">直接提交</a>



需要注意的是,我在上面的超链接中,使用的中文用户名是utf-8编码的:

1
userName=%E5%B0%8F%E6%98%8E

那么如果在上面超链接中使用中文会怎样呢,也就是写成下面的形式:

1
<a href="http://localhost:8080/HelloWorld/request.jsp?userName=小明&hobbys=book&password=123">直接提交</a>

可能会出现中文乱码问题,我这儿里测试没有发现又中文乱码,先记录以备后面查用。

解决get方法提交(URL传参)中文乱码

对于get方法,如果获取到的表达数据乱码,则需要修改Tomcat的conf目录下的配置server.xml配置文件来实现:

找到其中的Connector标签,如下所示:

1
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

在最后添加URIEcoding="utf-8"指定URL的编码为utf-8,如下所示:

1
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEcoding="utf-8"/>

然后记得重启tomcat服务器,这样才会生效。
说个无关的:修改Connector标签的port属性可以修改tomcat的默认端口号。

requset对象其他方法实例

修改requset.jsp如下:

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
<body>
<h2>request内置对象</h2>
<%
//解决post提交的数据中的。中文乱码问题.无法解决URL传参方式的中文乱码问题
// request.setCharacterEncoding("ISO-8859-1");
request.setCharacterEncoding("utf-8");
//解决get提交的数据乱码,可以通过tomcat的config目录下的server.xml配置文件来设置。
request.setAttribute("something", "属性值");
%>
获取到用户名:<%=request.getParameter("userName")%><br> 爱好:<%
String[] hobbys = request.getParameterValues("hobbys");
if (hobbys != null)
{

for (int i = 0; i < hobbys.length; i++)
{
out.println(hobbys[i] + ",");
}
}
%><br> 密码:<%=request.getParameter("password")%><br>
属性值:<%=request.getAttribute("something")%><br>
请求体的MME类型:<%=request.getContentType()%><br>
请求体的长度:<%=request.getContentLength()%>字节<br>
请求用的协议类型及版本号:<%=request.getProtocol()%><br>
请求的服务器主机名:<%=request.getServerName()%><br>
服务器接受此请求所用的端口号:<%=request.getServerPort()%><br>
请求的客户端IP地址:<%=request.getRemoteAddr()%><br>
请求的物理路径:<%=request.getRealPath("request.jsp") %><br>
请求的上下文路径:<%=request.getContextPath() %><br>
</body>

post提交方式

在login.jsp中设置表单提交方式为post,点击登录后requset.jsp页面如下:

get方式提交的

修改login.jsp中表单的提交方式为get,登录后request.jsp界面如下:

可以看到通过get方式传递的参数,request.getContentType()返回null,request.getContentLength()返回-1,这是因为这两个方法都是跟请求体相关的,get方法通过url传参,不存在请求体。

参考链接

http://www.runoob.com/jsp/jsp-client-request.html
GET和POST两种基本请求方法的区别

什么是 CSS

CSS是一种用于描述指定文档如何呈现给用户的语言 — 它们如何被指定样式、布局等。

  • 文档通常是用标记语言结构化的文本文件 — HTML 是最常用的标记语言, 但你依然可以遇见一些其他的标记语言,比如 SVG 或者 XML。
  • 呈现文档给用户意味着将其转换为用户可用的形式。浏览器,比如 Firefox, Chrome 或者 Internet Explorer,被设计用于可视化呈现文档,例如,在计算机屏幕,投影仪或打印机上。

    CSS如何影响HTML

    Web浏览器通过CSS规则来设置HTML标签的显示方式。一个CSS规则由以下组成:
  • **一组属性**,属性的值设置 HTML 标签的显示方式。比如,我想让元素的宽度是其父元素的50%,或者元素背景变为红色。
  • **一个选择器**,选择器负责找到你想要设置的HTML标签。比如,我想将我的CSS规则应用到我HTML文档中的所有段落上。

待续…

样式表中的一组CSS规则确定了网页如何显示,你将在下一篇文章中了解更多关于CSS语法的内容 — CSS 语法。

参考链接

https://developer.mozilla.org/zh-CN/docs/Learn/CSS/Introduction_to_CSS/How_CSS_works