web笔记

本文最后更新于:几秒前

Web 笔记


过滤器作用

过滤器常用作:

  1. 权限控制示例:

假设我们有一个需要登录后才能访问的页面 /securePage。我们可以创建一个过滤器,在其中检查用户是否已经登录,如果未登录则重定向到登录页面。

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
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AuthenticationFilter implements Filter {

public void init(FilterConfig config) throws ServletException {
// 过滤器初始化操作
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;

// 检查用户是否已登录
if (httpRequest.getSession().getAttribute("user") == null) {
// 未登录,重定向到登录页面
httpResponse.sendRedirect("/login.jsp");
} else {
// 已登录,继续请求处理
chain.doFilter(request, response);
}
}

public void destroy() {
// 过滤器销毁操作
}
}
  1. 编码转换示例:

在这个示例中,我们创建一个过滤器来统一将请求和响应的字符编码设置为 UTF-8。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
javaCopy Codeimport javax.servlet.*;
import java.io.IOException;

public class EncodingFilter implements Filter {

public void init(FilterConfig config) throws ServletException {
// 过滤器初始化操作
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

// 继续请求处理
chain.doFilter(request, response);
}

public void destroy() {
// 过滤器销毁操作
}
}

过滤器注解的使用:

1
2
3
4
import ...

@WebFilter(urlPatterns = "路径")
...

此处的路径可以有这几种表达

  • /*:这种模式匹配所有路径,但不包括子路径。例如,如果你配置了一个 URL 模式为 /*,那么它将匹配所有路径,如 /home, /about, /contact 等,但不会匹配子路径,如 /home/user, /about/us 等。
  • /**:这种模式匹配所有路径,包括子路径(递归匹配)。如果你使用 /** 这样的模式,它将匹配所有路径及其子路径。例如,/home, /home/user, /about, /about/us 都会被匹配。(存疑!)
  • /specificPath/*:这种模式匹配特定路径下的所有子路径。例如,如果你配置了 /specificPath/* 这样的模式,它将匹配以 /specificPath/ 开头的所有子路径,如 /specificPath/page1, /specificPath/page2/subpage 等。

Gson的使用

java servlet返回json数据时用到Gson,例:

1

1
2
3
4
5
6
7
Gson gson = new Gson();
String json = gson.toJson(getProvinces());
//这里getProvince返回的是一个ArrayList<String>类型的对象,其实不论是对象还是基本数据类型都能通过这种方法转换为json
response.setContentType("application/json");
//设置响应内容
response.getWriter().write(json);
//写入响应体

ajax取出数据方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
            axios({
url: "./AreaServlet",
//这里是设置发送请求到这个servlet
method: "get",
//发送方法为get
params: {
province: e.target.value
}
//携带的参数,如果有参数则可以在request中以request.getParameter("key")的方法拿到,例如:我现在这里的key是province,那直接在servlet写request.getParameter("province")的方法拿到e.target.value
}).then(result => {
doms[2].innerHTML = ''
console.log(result)
let data = result.data
data = data.map(e => "<option>" + e + "</option>")
doms[1].innerHTML = data.join("")
})
//这里是对正常情况下拿到的数据进行处理并改变dom元素的内容

实现实现前后端数据交流!

JDBC(防忘记)

1
2
3
4
5
            Class.forName("com.mysql.cj.jdbc.Driver");//加载驱动类
String url = "jdbc:mysql://localhost:3306/area";
//"jdbc://mysql://localhost:3306"是固定的,后面直接加数据库名称即可
Connection connection = DriverManager.getConnection(url, "root", "123456");
//三要素,数据库url(你得找到它),用户名,密码

获取connection后即可编写SQL语句

1
String sql = "???";

然后可以使用PreparedStatement来执行,这样即方便也能防止SQL注入

1
2
3
            PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, province);
//这里setString第一个参数指的是SQL语句中第几个问号,后面的就是其值

执行更改直接

1
ps.execute();

即可,如果是查询,要返回值,那就要用executeQuery(),然后用ResultSet来接收。

  1. execute() 方法:
  • execute() 方法用于执行任何类型的 SQL 语句,包括 DDL(数据定义语言)语句(如 CREATE、ALTER、DROP 等)、DML(数据操作语言)语句(如 INSERT、UPDATE、DELETE 等)以及 DCL(数据控制语言)语句(如 GRANT、REVOKE 等)。
  • 当执行 execute() 方法时,它会返回一个布尔值,表示执行的 SQL 语句是否返回了结果集。如果执行的是 DDL 或 DML 语句,则返回 false;如果执行的是查询语句,则返回 true
  • 如果 SQL 语句执行成功,并且返回了一个结果集,可以通过调用 getResultSet() 方法获取该结果集。
  1. executeQuery() 方法:
  • executeQuery() 方法专门用于执行查询(SELECT)语句,并且只能用于执行查询语句。
  • 当执行 executeQuery() 方法时,它会返回一个 ResultSet 对象,表示查询语句执行后返回的结果集。如果查询语句没有返回结果集,那么将返回一个空的 ResultSet 对象。
  • 如果执行的 SQL 语句不是查询语句,而是 DDL 或 DML 语句,则调用 executeQuery() 方法将会抛出 SQLException 异常。

两者的获取数据方式的区别:

  1. 返回值类型不同
  • executeQuery方法返回一个ResultSet对象,该对象包含了查询的结果集。
  • execute方法返回一个boolean值,表示执行SQL语句后是否返回了结果集。如果返回了结果集,需要通过getResultSet方法获取该结果集。
  1. 用法不同
  • executeQuery方法通常用于执行SELECT语句,因为它会返回一个结果集对象,可以通过该对象遍历查询结果。
  • execute方法可以用于执行任何SQL语句,包括SELECT、INSERT、UPDATE、DELETE等,但是在执行SELECT语句时,需要通过getResultSet方法获取结果集。
  1. **异常处理不同**:
  • executeQuery方法在执行失败时会抛出SQLException异常。
  • execute方法在执行失败时也会抛出SQLException异常,但是在执行SELECT语句时,如果没有返回结果集,会抛出SQLException,此时需要通过getUpdateCount方法获取受影响的行数。(重点)

读取ResultSet方法如下

1
2
3
4
while (rs1.next()) {
cities.add(rs1.getString("name"));
//getString 里面填写表的属性名,他将根据游标位置取出对应属性的值
}

ResultSetnext() 方法有以下作用:

  1. 移动指针: ResultSet 对象内部维护一个指针,初始时指向第一条记录之前的位置(称为游标)。调用 next() 方法会使游标向下移动一行,指向下一条记录。
  2. 判断是否有下一行数据: next() 方法返回一个布尔值,表示是否存在下一行数据。如果存在下一行数据,则返回 true;如果已经到达结果集的末尾,没有更多数据可供读取,则返回 false

注意:resultSetObject.next仅仅返回一个bool值并移动游标,数据的获取不能通过next方法,而是通过getString(Property Colum)或getInt(Property Colum)方法获取。

label标签的for属性

for属性:

  1. 关联表单控件: 使用 for 属性可以将 label 标签与对应的表单控件(如输入框、复选框、单选框等)进行关联。通过为 for 属性指定与之相关联的表单控件的 id 值,用户在点击 label 标签时就会触发相关联表单控件的行为,例如选中复选框或激活输入框。
  2. 增强可访问性: 通过将 label 标签与表单控件关联,可以提高页面的可访问性。这样用户不仅可以通过点击表单控件本身来操作,还可以通过点击与之关联的 label 标签来触发相应行为,使得页面更易于操作和理解。

前后端数据交换

使用ajax可以实现将前端数据发送到后端,也能获取后端返回的数据。首先来说一下axios的使用方法,axios其实就是包装好了的ajax,基本使用方法如下:

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
axios({
//这里面是一个config对象,用于设置
url: "path-to?",
//用于填写后端的路径
method: "get/post",
//用于设置request的方式
header: {

},
//用于设置请求头的参数
params: {
key: "value",

},
//用于设置method为get时的参数,等于在url后面加上 ...?key=value&... 默认content-type为application/x-www-form-urlencoded
data: {
key: "value",
},
//用于设置method为post时的参数,默认content-type为json

// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',
}).then(result=> {
//result中含有data,为后端传回的数据
}).catch(e=> {
//这里使用了链式编程
//用于处理服务器错误等情况
})

千万要注意method为post不能直接使用getParameter来获取数据,此时有两种方法:

  1. 前端:content-type改为application/x-www-form-urlencoded
  2. 后端:这样获取
1
2
3
4
5
6
BufferedReader reader = request.getReader();
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(reader, JsonObject.class);
String text = jsonObject.get("text").getAsString();
String password = jsonObject.get("password").getAsString();
System.out.println(text + " " + password);

这里用到了之前提到的GsonJsonObject类和Gson的基本使用方法。

还有,axios使用前记得加上<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

一些错误的解决

相当可怕的错误

过滤器中未调用

1
filterChain.doFilter(servletRequest, servletResponse);

导致所有页面全部为空白。

原因是设置的CharacterFilter过滤器是全局筛选:

1
2
@WebFilter("/*")
public class CharchaterFilter implements Filter

不小心删掉了代码:

1
2
3
filterChain.doFilter(req,rep);
//filterChain.doFilter(request,response);

导致拦截后未放行,任何页面都等接收却不报错,把放行的代码加上问题即解决。

Tomcat控制台乱码

在Tomcat的conf目录下找到logging.propertiesctrl+f输入UTF-8,将所有的替换为GBK即可解决问题。

jsp文件调入html/js/css文件乱码

解决方法:

WEB-INF下的web.xml文件中假如以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<jsp-config>
<jsp-property-group>
<display-name>HtmlConfiguration</display-name>
<url-pattern>*.html</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
<jsp-property-group>
<display-name>JspConfiguration</display-name>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
<jsp-property-group>
<display-name>JsConfiguration</display-name>
<url-pattern>*.js</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>

原理尚不清楚。

解决maven出现插件问题方法

问题:Plugin‘org.apache.maven.plugins:maven-clean-plugin:’ not found

解决方法:

将maven home path改成如图所示的选项。

MVC分层思想

最终:

  • 前台用jsp实现。

  • servlet存放在controller包下。

  • service分为接口和实现,实现类放在service包下的serviceImpl包下。

  • DAO同样也分为接口类和实现类,实现类放在DAO包下的DAOImpl包下。

  • M与C层或M与M层之间数据的传递要用到一个对象,也就是Bean对象,放在pojo包下。

  • 其余如监听器过滤器则分别放在FilterListener包下。


web笔记
https://www.webzank.site/2649c50c.html
作者
Zank
发布于
2024年3月29日
许可协议