JavaBean

JavaBean是一个有如下特征的实体类

  • 必须有一个无参构造函数
  • 属性必须私有化
  • 必须有对应的get/set方法

一般用于和数据库的字段做映射

ORM(Object Relation Mapping,对象关系映射):

  • 表 —-> 类
  • 字段 —-> 属性
  • 行记录 —-> 对象

什么是MVC架构

  • M:Model 模型

    • 业务处理:Service层
    • 数据持久化:DAO(Data Access Object)层
  • V:View 视图

    JSP,用于展示数据,提供可供操作的请求

  • C:Controller 控制器

    Servlet,接收用户的请求,将请求交给业务层,控制视图的跳转

MVC三层架构

由架构示意图可知,由于JSP就是一种Servlet,因此控制器和视图会存在功能重合,为了易于维护和使用,做了人为规定:

  • Servlet专注于处理请求,以及控制视图跳转
  • JSP专注于展示数据

现象

Tomcat控制台提示:

信息 [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanJars 至少有一个JAR被扫描用于TLD但尚未包含TLD。 为此记录器启用调试日志记录,以获取已扫描但未在其中找到TLD的完整JAR列表。 在扫描期间跳过不需要的JAR可以缩短启动时间和JSP编译时间。

阅读全文 »

JSP概述

JSP(Java Server Pages)是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码。JSP是一种Java Servlet主要用于实现Java Web应用程序的用户界面部分

JSP原理

阅读全文 »

Cookie和Session是什么

Cookie和Session是两种会话数据的保存方式。其中,Cookie是客户端技术,Session是服务端技术。

两者具体的类封装在javax.servlet.http(时代变了)jakarta.servlet.http包中,依赖jakarta.servlet-api包即可使用jakarta.servlet.http下的类。

  1. 存储位置
    存储在客户端,一般保存在本地用户目录下的appdata

  2. 生命周期
    默认会话结束后消失(存于内存中)。

    通过setMaxAge(int time)可以设置cookie的有效期(单位是s,存到硬盘):

    • 默认值为-1
    • 如果设为0,立即删除
  3. 缺陷
    大小和数量限制:一般每个站点大约能保存20个cookie,大小限制在4kb以内。浏览器一般有300个cookie上限。
    数据安全性问题:http请求中的cookie是明文传递的。

  4. 以存储网站的上次访问时间为例:

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 CookieDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决中文乱码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html");

PrintWriter out = resp.getWriter();

// 从客户端获取Cookie
Cookie[] cookies = req.getCookies();

// 判断cookies是否存在
if (cookies != null) {
out.write("你上次访问的时间是:");

for (Cookie cookie : cookies) {
if (cookie.getName().equals("lastLoginTime")) {
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
SimpleDateFormat dateFormat = (SimpleDateFormat) DateFormat.getDateTimeInstance();
out.write(dateFormat.format(date));
break;
}
}
} else {
out.write("这是你第一次访问本站");
}

// 服务器给客户端响应一个cookie
Cookie cookie = new Cookie("lastLoginTime", Long.toString(System.currentTimeMillis()));
// 设置cookie过期时间,以秒为单位
cookie.setMaxAge(24 * 60 * 60);
resp.addCookie(cookie);
}
}

Session

服务器会自动每一个用户(浏览器)创建一个Session对象,一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在。

服务器在自动创建Session的时候,会同时生成一个Cookie,存储sessionId

1
2
Cookie cookie = new Cookie("JSESSIONID", sessionId);
resp.addCookie(cookie);
  1. 存储位置
    保存于服务端。

  2. 使用场景

    • 保存登录用户的信息
    • 保存购物车信息
    • 其他在整个网站中经常会使用的数据
  3. 生命周期

    • 有效期30min,可以通过两种方式设置有效期:
      • setMaxInactiveTnterval(int time),单位是s
      • web.xml中配置session有效期,单位是min
    1
    2
    3
    <session-config>
    <session-timeout>time</session-timeout>
    </session-config>
    • 还可以通过HttpSession的invalidate()方法,手动使session失效
  4. 相关方法

    Session也能和ServletContext一样,实现不同Servlet之间的通信。并且该方式**优于利用ServletContext**。

1
2
3
4
5
6
7
8
9
10
11
String password = request.getParameter("password");
HttpSession session = request.getSession();

String name = (String)session.getAttribute("userName");
session.setMaxInactiveTnterval(30 * 60);

session.setAttribute("password", password);

session.removeAttribute("password");

session.invalidate();

Servlet是什么

Servlet(Server + Applet),一个Servlet就是一个Java类,并提供 基于请求-响应模式 的Web服务

要使用servlet需要添加javax.servlet-apiJar包(时代变了)jakarta.servlet-api


Servlet的处理流程

  1. 接收客户端的HTTP请求路径及请求内容

  2. 根据web.xml(属于web应用程序的一部分,部署描述符),找到请求路径对应的Servlet

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
    <servlet>
    <servlet-name>servlet名称(最好与类名相同)</servlet-name>
    <servlet-class>类路径</servlet-calss>
    </servlet>
    <servlet-mapping>
    <servlet-name><servlet>元素中的该元素内容相同</servlet-name>
    <url-pattern>映射路径</url-pattern>
    </servlet-mapping>
  3. 将请求转发给Servlet对应的service方法(会传递HttpServletRequest对象和HttpServletResponse对象作为方法参数)

  4. service方法根据请求是 get/post/… 转发给 doGet/doPost方法处理

  5. 通过HttpResponse对象,将响应返回给客户端


Servlet生命周期

init → service(doGet、doPost…) → destroy


管理Servlet的配置信息

通过ServletConfig对象获取配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
<servlet>
<init-param>
<param-name>参数名1</param-name>
<param-value>参数值1</param-value>
</init-param>
...
<servlet-name>servlet名称(最好与类名相同)</servlet-name>
<servlet-class>类名</servlet-calss>
</servlet>
<servlet-mapping>
<servlet-name>与<servlet>元素中的该元素内容相同</servlet-name>
<url-pattern>映射路径</url-pattern>
</servlet-mapping>

每个Servlet支持设置多个<init-param>,Servlet初始化过程中,<init-param>参数将被封装到ServletConfig对象中。在Servlet中,通过调用ServletConfig对象,就可以利用配置信息:

1
2
ServletConfig config = this.getServletConfig();
String value1 = config.getParameter("参数名1");//根据查找参数名,获取参数值

通过ServletContext共享Servlet的配置信息

Servlet容器在启动时,会为每个Web应用创建一个对应的ServletContext对象,它代表当前的Web应用。在一个Servlet中保存的数据,可以在另一个Servlet中获取。

1
2
3
4
5
<context-param>
<param-name>参数名1</param-name>
<param-value>参数值1</param-value>
</context-param>
...

<context-param>是在各个具体的<servlet>元素之外的,同样可以设置多个<context-param>。在任意具体的Servlet中,通过调用ServletContext对象,就可以利用配置信息:

1
2
ServletContext context = this.getServletContext();
String globalValue1 = context.getInitParameter("参数名");

通过ServletContext的属性(attribute)实现不同Servlet之间的通信

事先不知道,无法预先配置的信息,应该如何共享?(比如将购物车中的商品共享给结算页面)

在具体的Serlvet中,通过ServletContext对象的属性(attribute)设置希望共享的信息:

1
2
3
4
ServletContext context = this.getServletContext();
context.setAttribute("属性名","属性值");
String attribute = (String) context.getAttribute("属性名");//getAttribute的返回值是Object类型
context.removeAttribute("属性名");

读取外部资源配置文件信息

通过ServletContext的方法读取。

  • Properties文件

    • java目录下新建的properties

      默认不会被打包,需要在pom.xml文件中配置如下内容:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <build>
      <resource>
      <directory>src/main/java</directory>
      <includes>
      <include>**/*.properties</include>
      <include>**/*.xml</include>
      </includes>
      <filtering>t</filtering>
      </resource>
      </build>
    • resource目录下新建的properties

      默认会被打包到classes路径下

    都会被打包到classes路径下,俗称这个路径为classpath

getResource(“外部资源配置文件的路径”)

1
2
3
4
5
6
7
ServletContext context = this.getServletContext();
URL url = context.getResource("外部资源配置文件的相对路径");
InputStream in = url.openStream();
/**
利用编写的一个工具类,读取属性值
String property1 = GeneralUtil.getProperty("属性名", in);
*/

getResourceAsStream(“外部资源配置文件的路径”)

1
2
3
4
5
6
7
8
9
10
11
12
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 开头的"/"表示当前web项目,具体为target下的servlet-02-1.0-SNAPSHOT目录 (目录名根据pom.xml生成)
// 参数s 为相对路径
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String username = prop.getProperty("username");
String passwd = prop.getProperty("passwd");
resp.getWriter().print(username + ": " + passwd);
}

getRealPath(“外部资源配置文件的相对路径”)

获取外部资源配置文件的绝对路径

1
String realPath = context.getRealPath("外部资源配置文件的相对路径");

HttpServletRequest类

常见应用

获取前端传递的参数

  1. getParameter()
  2. getParameterValues()

请求转发

请求转发就是将当前的HttpServletRequestHttpServletResponse对象交给指定的web组件处理。对客户端来说,是一次请求,一次响应,浏览器的URL不变。

步骤:

  1. 获取请求转发对象
    即获取RequestDispatcher类的对象(由Servlet容器创建,封装由路径所标识的服务器资源)。
    获取请求转发对象有两种方式:
    • 通过HTTPServletRequest对象获取:
      RequestDispatcher rd = request.getRequestDispatcher("绝对路径/相对路径");
    • 通过ServleContext对象获取:
      RequestDispatcher rd = this.getServletContext().getNamedDispatcher("servlet-name"); 或者RequestDispatcher rd = this.getServletContext().getRequestDispatcher("绝对路径");
  2. 调用转发对象的forward(HttpServletRequest req, HttpServletResponse resp)方法

例子:

1
2
3
4
5
6
7
8
9
10
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
// 路径"/getInitParam"是在web.xml文件中配置的<servlet-mapping>的<url-pattern>
// 开头的"/"表示当前web项目,已涵盖tomcat设置的application context部分
// forward 实现请求转发
context.getRequestDispatcher("/getInitParam").forward(req, resp);
}
}

HttpServletResponse类

向浏览器发送数据的方法

  1. getOutputStream()
  2. getWriter()

向浏览器发送响应头的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void setCharacterEncoding(String var1);

void setContentLength(int var1);

void setContentLengthLong(long var1);

void setContentType(String var1);

void setDateHeader(String var1, long var2);

void addDateHeader(String var1, long var2);

void setHeader(String var1, String var2);

void addHeader(String var1, String var2);

void setIntHeader(String var1, int var2);

void addIntHeader(String var1, int var2);

常见应用

向浏览器输出消息

1
2
3
4
5
6
7
8
9
10
11
12
13
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");

// 设置响应内容的类型
resp.setContentType("text/html");
//resp.setCharacterEncoding("utf-8");
resp.getWriter().print("用户名:" + username);
}
}

下载文件

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
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取下载文件的路径
String realPath = "C:\\Users\\Hunter\\IdeaProjects\\javaweb-02-servlet\\response\\src\\main\\resources\\20180422 卡特迈国家公园和自然保护区里午睡的灰熊幼崽,阿拉斯加州 1920x1080.jpg";
System.out.println("下载文件的路径:" + realPath);

// 2. 下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 让浏览器能够支持下载,支持中文文件名编码
resp.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
// 4. 获取下载文件的输入流
FileInputStream fis = new FileInputStream(realPath);
// 5. 创建缓冲输入流
BufferedInputStream bis = new BufferedInputStream(fis);
// 6. 获取Outputstream对象
ServletOutputStream sos = resp.getOutputStream();
// 7. 将FileOutputStream流写入到缓冲区数组,使用OutputStream将缓冲区中的数据输出到客户端
byte[] bytes = new byte[1024]; // 存储每次读取的数据
int len = 0; // 记录每次读取的字节个数
while ((len = bis.read(bytes)) != -1) {
sos.write(bytes, 0, len);
}
bis.close(); // 关闭缓冲流,基本流也会被自动关闭
sos.close();
}
}

验证码功能

实现方式:

  1. 前端实现
  2. 后端实现,需要用到java的图片类,产生一个图片

实现重定向

请求重定向就是通过HttpServletResponse对象发送给客户端一个新的URL地址,让其重新请求。对客户端来说,是两次请求,两次响应

请求重定向的方法:resp.sendRedirect("绝对路径");,其中路径需要写明tomcat设置的application context前缀,可用req.getContextPath()获取绝对路径前缀。

Maven是什么

Maven是一个免费、开源的,用Java编写的项目构建和依赖管理工具

Maven的特点

  • 默认的目录结构
  • 第三方依赖管理
    通过配置pom.xml文件,从远程仓库下载相关Jar包。解决了依赖维护问题
  • 提供了一致的项目构建管理方式
    生命周期。减少了构建工作量
  • 插件式架构,大量的可重用插件
  • 方便地集成于IDE
阅读全文 »

Tomcat简介

Tomcat是一个典型的Web应用服务器软件,通过运行Tomcat服务器,我们就可以快速部署我们的Web项目,并交由Tomcat进行管理,我们只需要直接通过浏览器访问我们的项目即可。


安装及配置

当前支持的版本:

Apache Tomcat® - Which Version Do I Want?

Servlet Spec JSP Spec EL Spec Apache Tomcat Version Supported Java Versions
6.1 4.0 6.0 11.0.x 17 and later
6.0 3.1 5.0 10.1.x 11 and later
4.0 2.3 3.0 9.0.x 8 and later

Apache Tomcat® - Apache Tomcat 10 Software Downloads下载压缩包64-bit Windows zip,解压到合适的目录文件下,运行bin目录下的startup.bat/shutdown.bat,即可启动/关闭 Tomcat。

conf文件夹

conf文件夹下放置tomcat的配置文件,其中server.xml是服务器核心配置文件。

  • 连接端口相关设置

  • 主机相关设置

    默认端口号为8080.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <Serveice name="Catalina">
    <!-- 默认端口号:8080 -->
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" />

    <!-- 默认主机名称:localhost 等价于127.0.0.1 -->
    <!-- 默认网站应用存放的根目录:webapps -->
    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true">
    </Serveice>

环境变量

环境变量的配置可选,真实的开发环境,都是在IDEA中操作。

如有需要,后续补充


部署项目到Tomcat

一般的项目结构:

  • webapps:Tomcat服务器的web目录

    • ROOT

    • 项目名

      • WEB-INF

        • classes:java程序
        • lib:依赖的jar包
        • web.xml:网站的配置文件
      • index.html:默认的首页

      • static

        • css
          • style.css
        • js
        • img

手动

将自己写的网页放到tomcat中网站应用(webapps)文件夹下,就可以访问了。

版本控制工具

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。版本控制能方便查看更改历史,备份以及恢复以前的版本,保证多人协作不出问题。

Git对待数据的方式,更像是把数据看作是对小型文件系统的一组快照。每次提交更新或者在Git中保存项目状态时,它主要对当时的全部文件制作一个快照保存这个快照的索引。为了高效,如果文件没有修改,Git不再重新存储该文件,而只是保留一个链接指向之前存储的文件,Git对待数据更像是一个快照流

阅读全文 »

概述

水杉码园使用Go语言,基于Gitea开发。本文用于记录如何入坑开发。


开发机

先用Cisco的VPN登录,再连接开发机。

待完善……


Windows环境下clone代码

水杉码园的代码存储在gitlab上:ShuiShan / Gitea / gitea · GitLab。并且该地址需要拥有项目管理权限的人员(徐柴笛、周成义、李苗进、顾业鸣)进行授权才可访问。

clone代码的操作:

  1. 安装Git
  2. Clone With HTTPS
    1. 先在命令行执行git config --global http.sslVerify false
    2. git clone https://code.kfcoding.com/ShuiShan/Gitea/gitea.git

Windows下环境搭建

  1. 安装go

  2. 安装node.js(一定要勾选会附带安装chocolatey的选项)

  3. 安装make(choco install make

  4. 设置npm的国内镜像代理npm config set registry https://registry.npm.taobao.org

  5. Clone的项目文件夹下(\gitea),执行TAGS="bindata" make build

  6. 本地测试,执行./gitea web

  7. 浏览器访问http://localhost:3000/

  8. 登录水杉码园,配置本地数据库信息,记住要在可选设置中设置管理员账号

    管理员账号设置

node版本如何升级 - 知乎


使用VS Code进行开发


课程批量导入学生

  • 入口:/org/:org/teams/new_all_student

导入完成后,课程团队下会生成指定的团队:

团队为成员-仓库的形式

  • Owners

    管理员-管理的仓库

  • AllStuRead

    教师有操作权限,学生只有读权限。用于老师布置作业,分享数据、资料。

  • AllStuWrite

    所有学生都有操作权限

课程中的仓库,除了AllStuWrite和AllStuRead这两个公开仓库之外,每个学生还有自己的个人仓库,目前以学号作为仓库名。仓库描述为student u.Name(学号) u.FullName(用户名)'s repo


代码

  1. routes.go下,m.Post("/teams/new_all_student", bindIgnErr(auth.CreateAllStuTeamForm{}), org.NewAllStuTeamPost)

    • auth.CreateAllStuTeamForm{}相当于是前端的表单

      其中的Studentlist表示的上传的excel文件

    这个Post函数将前端的表单传入后端的NewAllStuTeamPost函数,

  2. 细看一下NewAllStuTeamPost方法

    • 首先是通过前端的form获取相应的基本信息

    • 再来我们可以先看一下这个函数最后的部分GetCache().Set

      这里把课程ID(Organization.ID)设置了1分钟的缓存

    • 再回过头来看上边的代码,如果能在缓存中获取到课程ID的缓存,说明之前一分钟内有过成功导入的记录,就会给出一个不要多次导入的提示并结束导入学生的操作


批量移除选中的仓库


批量删除成员

0%