tomcat-jsp-servlet
准备
tomcat windows startup.bat shutdown.bat
mac下: startup.sh shutdown.sh
tomcat的运行依赖 JAVA_HOME系统环境变量
tomcat输入地址后 localhost:8080 默认是访问的是ROOT工程
当有工程名时,默认访问index界面
idea 整合 tomcat
创建项目
创建好的web工程
src目录 存放自己编写的java源代码
web目录 专门用来存放web工程的资源文件,比如 html页面、css文件、js文件等等
WEB-INF目录 是一个受服务器保护的目录,浏览器无法访问此目录的内容
WEB-INF/web.xml 它是整个动态web工程的配置描述文件,可以配置很多web工程的组件,比如: servelet程序、filter过滤器、session超时等等
WEB-INF/lib文件夹 用来存放第三方的jar包,IDEA还需要自己配置导入
修改访问路径
Application context是工程路径
更改这里就可以了
修改运行端口号
热部署
Servlet
什么是servlet
- servlet是javaEE规范之一。规范就是接口
- servlet是javaWeb三大组件之一。三大组件就是servlet程序、filter过滤器、listener监听器
- servlet是运行在服务器上的java小程序,他可以接收客户端发过来的请求并相应数据给客户端
手动实现servle程序
- 编写一个类去实现Servlet接口
- 实现service方法、处理请求并相应数据
- 到web.xml配置servlet程序的访问地址
com.kcl.servlet.HelloServlet
点击查看代码
package com.kcl.servlet;
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 HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//处理请求并响应
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello servlet被访问了");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml配置servlet
点击查看代码
<!--servlet标签给Tomcat配置servlet程序,对应servlet类实现servlet接口-->
<servlet>
<!--给servlet程序起一个别名,一般是类名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet的全类名-->
<servlet-class>com.kcl.servlet.HelloServlet</servlet-class>
</servlet>
<!--给servlet程序配置一个访问地址-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
访问
http://localhost:9517/superkcl/hello
servlet生命周期
- 执行servlet构造器方法(自己创建)
- 执行init初始化方法
- 执行servciefangfa
- 执行destroy方法
第一第二步是在创建servlet时被调用
每次调用接口,都会执行service 方法
工程停止时会调用destory方法
HttpservletRequest 继承 ServletRequest
//处理请求并响应
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello servlet被访问了");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String method = request.getMethod();
System.out.println(method);
}
GET
开发时不继承Servlet接口而是其子类HttpServlet方式实现
public class HelloServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("helloservlet 2 doGet方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doPost(req, resp);
System.out.println("helloservlet 2 doPost方法");
}
}
使用idea创建servlet程序
在包目录下点击右键 new->Create new Servlet
配置一下ServletMapping即可
Servlet类继承体系
servlet实现类: GenericServlet实现servlet接口,对servlet接口做了很多空实现
并持有一个ServletConfig类的引用。并对ServletConfig的使用做一些方法。
HttpServlet继承GenericServlet类
HttpServlet是抽象类,主要实现service方法
实现servcie方法,和我们的理解差不多 req.getMethod();
doGet() doPost()负责抛异常
ServletConfig类
三大作用
- 可以获取servlet程序的别名servlet-name的值
- 获取初始化参数init-param
- 获取servletContext对象
<servlet>
<!--给servlet程序起一个别名,一般是类名-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet的全类名-->
<servlet-class>com.kcl.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</init-param>
</servlet>
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init");
//1. 可以获取servlet程序的别名servlet-name的值
System.out.println(servletConfig.getServletName());
//2. 获取初始化参数init-param
System.out.println(servletConfig.getInitParameter("username"));
System.out.println(servletConfig.getInitParameter("url"));
//3. 获取servletContext对象
System.out.println(servletConfig.getServletContext());
}
servlet程序默认是第一次访问的时候创建,servletConfig是每个servlet程序创建时,就创建一个对应的servletConfig对象
继承HttpServlet也可以
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletConfig servletConfig = this.getServletConfig();
String servletName = servletConfig.getServletName();
System.out.println(servletName);
}
ServletContext类
- servletContext是一个接口,表示servlet上下文对象
- 一个web工程只有一个servletContext对象实例!!!
- ServletContext对象是一个域对象
域对象,是可以像Map一样存取数据的对象,叫域对象
这里的域指的是存取数据的操作范围
--- 存数据 取数据 删除数据
Map put() get() remove()
域对象 setAttribute() getAttribute() removeAttribute()
ServletContext类的四个作用
- 获取web.xml中配置的上下文参数context-param
- 获取当前的工程路径,格式: /工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
- 像map一样存取数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 获取web.xml中配置的上下文参数context-param
ServletContext servletContext = getServletContext();
System.out.println("username" + servletContext.getInitParameter("username"));
System.out.println(servletContext.getInitParameter("password"));
//2. 获取当前的工程路径,格式: /工程路径
System.out.println(servletContext.getContextPath()); // /superkcl
//3. 获取工程部署后在服务器硬盘上的绝对路径
System.out.println(servletContext.getRealPath("/")); //斜杠解析为:http://ip:port/工程名/
// D:\编程软件\idea2020.1.2\myFile\testTomcat04\out\artifacts\testTomcat04_war_exploded\
//映射到web目录
System.out.println(servletContext.getRealPath("/css"));
//D:\编程软件\idea2020.1.2\myFile\testTomcat04\out\artifacts\testTomcat04_war_exploded\css
//4. 像map一样存取数据
servletContext.setAttribute("key01","value01");
System.out.println(servletContext.getAttribute("key01"));
}
不同servlet中只要存储了,都可以取到的
在web项目停止后才会销毁。
HttpServletRequet
public interface HttpServletRequest extends ServletRequest
ServletRequest也是一个接口
常用方法
getRequestURI() 获取请求资源路径
getRequestURL() 获取绝对路径
getRemoteHost() 获取客户端ip地址
getHeader() 获取请求头
getParameter() 获取请求的参数
getParameterValues() 获取请求的参数(多个值的时候使用)
getMethod() 获取请求的方式GET或POST
setAttribute(key,val) 设置域数据
getAttribute(key) 获取域数据
getRequestDispatcher() 获取请求转发对象
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//getRequestURI() 获取请求资源路径
//URI => /superkcl/contextServlet
System.out.println("URI => "+ request.getRequestURI());
//getRequestURL() 获取绝对路径
//URL => http://localhost:9517/superkcl/contextServlet
System.out.println("URL => "+request.getRequestURL());
//getRemoteHost() 获取客户端ip地址
//RemoteHost => 0:0:0:0:0:0:0:1
System.out.println("RemoteHost => "+ request.getRemoteHost());
//getHeader() 获取请求头
//Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
System.out.println(request.getHeader("User-Agent"));
//getParameter() 获取请求的参数
String username = request.getParameter("username");
System.out.println("username => " + username);
String password = request.getParameter("password");
System.out.println("password => " + password);
String[] hobby = request.getParameterValues("hobby");
System.out.println("hobby => " + Arrays.asList(hobby));
//getParameterValues() 获取请求的参数(多个值的时候使用)
//getMethod() 获取请求的方式GET或POST
//请求的方式 => GET
System.out.println("请求的方式 => " + request.getMethod());
//setAttribute(key,val) 设置域数据
//getAttribute(key) 获取域数据
//getRequestDispatcher() 获取请求转发对象
}
<form action="http://localhost:9517/superkcl/contextServlet" method="get">
用户名: <input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
兴趣爱好:<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="cpp">cpp
<input type="checkbox" name="hobby" value="js">js
<input type="submit">
</form>
//getParameter() 获取请求的参数
String username = request.getParameter("username");
System.out.println("username => " + username);
String password = request.getParameter("password");
System.out.println("password => " + password);
String[] hobby = request.getParameterValues("hobby");
System.out.println("hobby => " + Arrays.asList(hobby));
post请求也是同样的道理
post请求会出现中文乱码
request.setCharacterEncoding("UTF-8");
在获取请求参数之前调用才有效
get请求不会出现中文乱码
请求转发
服务器接收到请求后,从一个资源跳转到另一个资源的操作叫请求转发
......
req.setAttribute只在请求域中有效
servlet1
RequsetDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2")
requestDispatcher.forward(req,resp)
servlet2
处理自己的业务
特点:
1.浏览器地址栏没有变化
2.他们是一次请求
3.他们共享Request域中的数据
4.可以转发到WEB-INF目录下
浏览器是反问不到WEB-INF目录的
dispatcher可以访问到!"/WEB-INF/form.html"
5.是否可以访问到项目以外的网址? 不可以! 默认是访问当前项目下
base标签作用
/的不同含义
- 如果被浏览器解析 a标签 得到的地址就是 http://ip:port/
<a href="/"
- 如果被服务器解析,得到的地址就是 http://ip:port/工程路径
<url-parttern>/servlet
servletContext.getRealPath("/")
request.getRequestDispatcher("/")
特殊情况:
response.sendRediect("/")
请求重定向,把斜杠发送给浏览器解析。得到http://ip:port
HttpServletResponse
类似于HttpServletRequst,每次请求进来,都会创建一个response对象传递给servlet使用
两个流
字节流-getOutputStream();常用于下载,传递二进制数据
字符流 getWriter() 常用于回传字符串(常用)
两个流只能使用一个
使用了字节流,就不能再使用字符流,否则就会报错
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
ServletOutputStream outputStream = resp.getOutputStream();
//error
}
}
字符流
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("response kcl");
}
but写中文会乱码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
//通过响应头,设置浏览器也是用UTF-8
resp.setHeader("Content-Type","text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("response kcl 寇春雷");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//一行代码同时设置服务器和客户端都使用UTF-8
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("response kcl 寇春雷");
}
请求重定向
客户端请求服务器,服务器返回一个新地址,旧地址废弃
1.浏览器地址栏会发生变化
2.两次请求
3.不共享request域中的数据
4.不能访问WEB-INF下的资源
5.可以重定向至其他网站
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应状态码302,表示重定向
resp.setStatus(302);
//设置响应头设置新的地址在哪里
resp.setHeader("Location","http://localhost:9517/superkcl/hello"); //绝对地址
}
另外一种方法
resp.sendRedirect("http://localhost:9517/superkcl/hello");
JSP
主要作用是代替servlet程序回传html数据
servlet回传html非常繁琐
jsp的本质是什么?
本质上是一个servlet程序
当我第一次访问jsp页面时,Tomcat服务器会帮我们把jsp翻译成一个java源文件。
并且对他进行编译成字节码程序
a_jsp extends HttpJspBase
HttpJspBase extends HttpServlet
page命令
page指令可以修改jsp页面中一些重要的属性
language: jsp翻译后支持的语言,只支持java
contentType:表示jsp返回的数据类型是什么。也是源码中response.setContentType(“text/html;charset=UTF-8”)参数值
pageEncoding:页面本身字符集,默认utf-8
import:导包,和java一样
//------------------
给out输出流使用
autoFlush:设置当out输出流缓冲区满了之后,是否自动刷新缓冲区。默认true
buffer:设置out缓冲区大小,默认8k
//------------
errorPage:设置当jsp页面运行时出错,自动跳转去的错误界面路径,映射到web目录
isErrorPage:设置当前jsp页面是否错误信息界面。默认是false,如果是true可以获取异常信息
session: 默认true穿件HttpSession对象
extends="javax.servlet.HttpServlet": 设置jsp翻译出来的java类默认继承谁
<%@ page contentType="text/html;charset=UTF-8" language="java" autoFlush="true" buffer="8kb" errorPage="/error500.jsp" %>
<%@ page import="java.util.Map" %>
声明脚本(很少使用)
<% ... %>
%!声明数据
<%-- 声明类属性, 翻译后的a_jsp类中就有这些属性--%>
<%!
private Integer id;
private String name;
private static Map<String,Object> map;
%>
<%--声明static静态代码块--%>
<%!
static{
map = new HashMap<>();
map.put("key01","value01");
map.put("key02","value02");
}
%>
<%--声明类的方法--%>
<%!
public int abc(){
return 0;
}
%>
<%--声明内部类--%>
<%!
public static class A{
private Integer id = 12;
private String name = "123";
}
%>
表达式脚本-输出数据
<%=表达式=%>
表达式的作用是:在jsp页面上输出数据
<%= 12%>
<%="我是字符串"%>
<%=map%>
特点:
1.所有的表达式脚本都被翻译到_jspService方法中
2.表达式脚本都会翻译成out.print()输出到页面上
3.由于表达式脚本翻译的内容都在_jspService()方法中,_jspService方法中的对象都可以直接使用
<%=request.getParameter("username")%>
4.表达式脚本中表达式不能以分号结束(out.print(request.getPar...😉)完了!
jsp代码脚本
<% java语句 %>
作用是:可以在jsp页面中,编写我们自己需要的功能(JAVA语句)
<%
boolean isok = true;
if(isok){
System.out.println("yes");
}else{
System.out.println("No");
}
for(int i = 0; i < 10; i++)
System.out.println(i);
String username = request.getParameter("username");
System.out.println(username);
%>
代码脚本特点:
1.翻译在_jspService方法中
2._jspService方法中的多有对象都可以直接用
3.还可以由多个代码脚本块组合成一个完整的java语句
4.代码脚本还可以和表达式脚本一起使用。在jsp页面上输出数据
<%
for(int i = 0; i < 10; i++){
%>
<%=i %>
<%}
%>
<table border="1px solid red" >
<%
for(int i = 0; i < 10; i++){
%>
<tr>
<td>第<%=i%>行</td>
</tr>
<%
}
%>
</table>
jsp中9大内置对象
jsp中的内置对象,是指tomcat在翻译jsp页面成为servlet源码后,内部提供的9大对象。
1.HttpServletRequest request
2.HttpServeletResponse response
3.javax.servlet.jsp.PageContext pageContext;
jsp的上下文对象
4.HttpSession session
5.ServletConfig config
6.JspWriter out;
jsp输出流对象
7.page
: 指向当前jsp的对象
8.application
; servletContext对象
errorpage开启后的exception对象
jsp四大域对象
1.pageContext(PageContextImpl)
当前jsp页面范围内有效
2.request(HttpServletRequest)
一次请求内有效
3.session(HttpSession)
一个会话范围内有效,关闭浏览器失效
4.application(ServletContext)
整个web工程范围内都有效
域对象可以像map一样存取数据
<%
pageContext.setAttribute("key","pageContext");
request.setAttribute("key","request");
session.setAttribute("key","session");
application.setAttribute("key","application");
%>
pageContext是否有值 <%=pageContext.getAttribute("key")%><br/>
request是否有值 <%=request.getAttribute("key")%><br/>
session 是否有值<%=session.getAttribute("key")%><br/>
application是否有值 <%=application.getAttribute("key")%><br/>
<%
request.getRequestDispatcher("/error500.jsp").forward(request,response);
%>
请求转发之后 pageContext就没数据了
out输出和response.getWriter输出的区别
<%
response.getWriter().write("reponse输出1<br/>");
response.getWriter().write("reponse输出2<br/>");
out.write("out输出<br/>"); //9大对象
%>
由于jsp翻译之后,底层源代码都是使用out进行输出,所以一般情况下。
我们在jsp页面中统一使用out来进行输出
out.print(都转化为字符串,最后调用out.write输出)与out.write(没问题)
jsp常用标签
静态包含不会翻译被包含的jsp页面
把被包含的jsp页面的代码拷贝到包含的位置执行输出
<%@include file="/header.jsp"%>
动态包含
会把包含的jsp页面翻译为java代码
动态包含使用JspRuntimeLibrary.include(request,response,"...jsp");
<jsp:include page="index.jsp"></jsp:include>
包含的页面,使用主界面的9大对象
动态包含还可以传递参数
<jsp:forward page="index.jsp"></jsp:forward>
案例
List<User> users = mUserService.getAllUser();
req.setAttribute("users",users);
<table>
<tr>
<td>用户名</td>
<td>密码</td>
<td>年龄</td>
</tr>
<%
List<User> users = (List<User>)request.getAttribute("users");
for(int i = 0; i < users.size(); i++){
%>
<tr>
<td><%=users.get(i).getUsername()%></td>
<td><%=users.get(i).getPassword()%></td>
<td><%=users.get(i).getAge()%></td>
</tr>
<%
}
%>
</table>
listener监听器
listener监听器是javaWeb三大组件之一。三大组件分别是servlet程序、filter过滤器、listener监听器
listener它是JavaEE的规范,就是接口
监听器的作用是监听某种事物的变化,通过回调参数,反馈给客户去做一些处理
EL表达式和 JSTL
什么是EL表达式
全称:Expression Language。是表达是语言
主要是替代jsp页面中的表达式脚本,在jsp页面中进行数据输出
EL表达式更加简洁!
${users}
<%
request.setAttribute("key01","value01");
%>
${key01}
EL表达式输出格式${表达式}
EL表达式输出null值的时候,输出的是空串。
jsp表达式脚本输出null值的时候,输出的是null
EL表达式搜索域数据的顺序
<%
pageContext.setAttribute("key01","pageContext");
request.setAttribute("key01","request");
session.setAttribute("key01","session");
application.setAttribute("key01","application");
%>
${key01}
当4个域中有相同的key
pageContext > request > session > application
EL输出Bean的普通属性、数组属性。List集合、map集合属性
EL关系运算-逻辑运算-算数运算
${5==5}
${12 eq 12}
!= 、 > 、 <
lt gt ne
&& and
|| or
! not
${1+1}
${1-2}
/ 或div
% 或 mod
empty运算
一个数据为空输出true否则输出false
1.值为null值的时候,为空
2.值为空串的时候,为空
3.值是Object类型数组,长度为0的时候
4.list集合元素个数为0
5.map集合元素个数为0
<%
request.setAttribute("key",null);
%>
${empty key}
三元运算
${12==12? 'yes' : 'no'}
对象的.运算和[]运算符
${map['aaa']}
EL 11个隐含对象
1.pageContext jsp9大内置对象
2.pageScope Map<String,Object> 可以获取pageContext域中的数据
3.requestScope Map<String,Object>可以获取Request域中的数据
4.sessionScope Map<String,Object> .....
5.applicationScope ......
6.param Map<String,String> 他可以获取请求参数的值
7.paramValues Map<String,String[]>获取请求参数
8.header Map<String,String> 他可以获取请求头信息
9.headerValues ...
10 cookie Map<String,Cookie> t他可以获取当前请求的cookie信息
11.initParam Map<String,String> 获取web.xml中配置的context-param上下文参数
<%
request.setAttribute("key01","kcl");
%>
${requestScope.key01}
pageContext
1.协议http
${pageContext.request.scheme}<br/>
2.服务器ip
${pageContext.request.serverName}<br/>
3.服务器端口
${pageContext.request.localPort}<br/>
4.获取工程路径:
${pageContext.request.contextPath}<br/>
5.获取请求方法
${pageContext.request.method}<br/>
6.获取客户端ip地址
${pageContext.request.remoteAddr}<br/>
7.获取回话id编号
${pageContext.session.id}
JSTL
全称:JSP Standard Tag Library标准标签库
前缀c -> http://java.sun.com/jsp/jstl/core
前缀fmt -> http://java.sun.com/jsp/jstl/fmt
前缀fn -> http://java.sun.com/jsp/jstl/fnnction
导入这两个包
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--往域中保存数据--%>
<%--scope表示保存到那个域中, 默认pageContext--%>
<c:set scope="page" var="key01" value="value011"/>
${pageScope.key01}
<c:if test="${1==1}">
<h1>1==1</h1>
</c:if>
<c:if test="${1!=2}">
<h1>1!=2</h1>
</c:if>
c:choose c:when c:otherwise
like switch..case..default
<%
pageContext.setAttribute("key01",20);
%>
<c:choose>
<c:when test="${pageScope.key01 > 20}">
<h2> >20 </h2>
</c:when>
<c:when test="${pageScope.key01 < 20}">
<h2> <20 </h2>
</c:when>
<c:otherwise>
=20
</c:otherwise>
</c:choose>
when标签外面一定要是choose标签
c:forEach
<c:forEach begin="1" end="10" var="i">
${i}<br/>
</c:forEach>
<%request.setAttribute("arr",new String[]{"a","b","c"});%>
<c:forEach items="${requestScope.arr}" var="item">
${item}<br/>
</c:forEach>
<%
Map<String,Object> map = new HashMap<>();
map.put("k1","v1");
map.put("k2","v2");
map.put("k3","v3");
request.setAttribute("map",map);
%>
<c:forEach items="${requestScope.map}" var="item">
${item.key}-${item.value}
</c:forEach>
<table border="1 solid red">
<tr>
<td>用户名</td>
<td>密码</td>
<td>年龄</td>
<td>操作</td>
</tr>
<c:forEach items="${requestScope.users}" var="user" >
<tr>
<td>${user.username}</td>
<td>${user.password}</td>
<td>${user.age}</td>
<td>删除、修改</td>
</tr>
</c:forEach>
<%--begin默认从0开始 2表示从第三个开始--%>
<%--step表示遍历的步长值,跳着输出 varStatus表示当前遍历到的数据状态--%>
<c:forEach begin="2" end="9" varStatus="status" items="${requestScope.users}" var="user" >
<tr>
<td>${user.username}</td>
<td>${user.password}</td>
<td>${user.age}</td>
<td>删除、修改</td>
<td>${status.index}</td>
</tr>
</c:forEach>
</table>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了