当前位置: 首页 > article >正文

【JavaWeb开发】从零构建前后端交互实战指南

1. JavaWeb前后端交互基础入门第一次接触JavaWeb开发时最让我困惑的就是前后端如何传递数据。记得刚开始做项目时我傻乎乎地用字符串拼接HTML代码返回给前端结果遇到中文乱码问题折腾了一整天。后来才发现现代JavaWeb开发早已形成了一套成熟的前后端交互模式。前后端交互本质上就是浏览器前端和服务器后端之间的对话过程。当你在网页点击一个按钮时前端会通过HTTP协议向后端发送请求后端处理完业务逻辑后再把结果返回给前端展示。这个过程看似简单但实际开发中会遇到各种坑比如跨域问题、数据格式不统一、会话丢失等。JavaWeb开发中Servlet是处理HTTP请求的核心组件。每个Servlet都像是一个小服务员专门负责处理特定类型的请求。比如用户登录请求、数据查询请求等都可以创建对应的Servlet来处理。我在实际项目中最常用的就是HttpServlet它已经帮我们封装好了处理GET、POST等请求的方法。2. Servlet开发实战2.1 创建第一个Servlet让我们从零开始创建一个处理用户登录的Servlet。首先在项目中新建一个类继承HttpServletWebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取前端传递的用户名和密码 String username req.getParameter(username); String password req.getParameter(password); // 这里应该调用Service层验证登录逻辑 boolean isValid UserService.validateLogin(username, password); // 设置响应内容类型 resp.setContentType(application/json;charsetUTF-8); PrintWriter out resp.getWriter(); if(isValid) { out.write({\success\: true, \message\: \登录成功\}); } else { out.write({\success\: false, \message\: \用户名或密码错误\}); } } }这个简单的Servlet演示了几个关键点使用WebServlet注解配置访问路径重写doPost方法处理POST请求通过HttpServletRequest获取请求参数设置响应内容类型为JSON格式通过HttpServletResponse返回处理结果2.2 Servlet生命周期理解Servlet的生命周期是面试常问的知识点也是实际开发中必须掌握的。我在初学阶段经常混淆init()、service()和destroy()方法的调用时机直到自己动手写了测试代码才真正理解public class LifecycleServlet extends HttpServlet { // 第一次访问时调用仅执行一次 Override public void init() throws ServletException { System.out.println(Servlet初始化...); } // 每次请求都会调用 Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println(处理请求...); super.service(req, resp); } // 服务器关闭时调用 Override public void destroy() { System.out.println(Servlet销毁...); } }实际开发中我们通常会在init()方法中初始化一些资源比如数据库连接池在destroy()方法中释放这些资源。而业务逻辑主要写在doGet()或doPost()方法中。3. 过滤器与拦截器应用3.1 编码过滤器实战中文乱码是每个JavaWeb开发者都会遇到的经典问题。记得有一次我调试了2个小时才发现是因为忘记设置请求编码。后来我养成了习惯第一个配置的永远是编码过滤器WebFilter(/*) public class EncodingFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 设置请求编码 request.setCharacterEncoding(UTF-8); // 设置响应编码 response.setContentType(text/html;charsetUTF-8); // 继续执行过滤器链 chain.doFilter(request, response); } }这个过滤器会拦截所有请求/*确保进入Servlet的请求参数都能正确解析中文同时响应也会使用UTF-8编码。配置好后再也不需要在每个Servlet中单独处理编码问题了。3.2 跨域问题解决方案当前后端分离开发时跨域问题一定会出现。我第一次遇到时浏览器控制台报错让我一头雾水。后来才知道这是浏览器的同源策略限制。解决方案是在后端添加CORS过滤器WebFilter(/*) public class CorsFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response (HttpServletResponse) res; HttpServletRequest request (HttpServletRequest) req; // 允许所有域名访问 response.setHeader(Access-Control-Allow-Origin, *); // 允许的请求方法 response.setHeader(Access-Control-Allow-Methods, GET, POST, PUT, DELETE, OPTIONS); // 允许的请求头 response.setHeader(Access-Control-Allow-Headers, Content-Type, Authorization); // 预检请求缓存时间 response.setHeader(Access-Control-Max-Age, 3600); // 允许携带cookie response.setHeader(Access-Control-Allow-Credentials, true); if (OPTIONS.equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } }这个过滤器配置了完整的CORS支持包括允许所有来源访问生产环境应该指定具体域名支持常见的HTTP方法允许自定义请求头支持携带Cookie处理OPTIONS预检请求4. 前后端数据交互格式4.1 JSON数据转换现代Web开发中JSON已经成为前后端交互的事实标准。Java中我们常用Jackson库来处理JSON转换。第一次使用时我被它的各种注解搞得晕头转向后来发现掌握几个基本用法就能应对大部分场景// 实体类 public class User { JsonProperty(user_name) // 自定义JSON字段名 private String username; JsonFormat(pattern yyyy-MM-dd) // 日期格式化 private Date birthDate; JsonIgnore // 忽略该字段 private String password; // 省略getter/setter } // 在Servlet中使用 ObjectMapper mapper new ObjectMapper(); User user new User(张三, new Date(), 123456); // 对象转JSON String json mapper.writeValueAsString(user); // 输出: {user_name:张三,birthDate:2023-07-20} // JSON转对象 User newUser mapper.readValue(json, User.class);实际项目中我通常会封装一个统一的JSON工具类处理日期格式、空值等常见问题。4.2 统一响应格式前后端协作时定义统一的响应格式非常重要。我见过很多项目因为响应格式不统一导致前端解析困难。推荐的基础响应格式如下public class ResultT { private int code; // 状态码 private String message; // 提示信息 private T data; // 业务数据 // 成功静态方法 public static T ResultT success(T data) { return new Result(200, 成功, data); } // 失败静态方法 public static T ResultT error(int code, String message) { return new Result(code, message, null); } // 省略构造方法和getter/setter } // 在Servlet中使用 WebServlet(/api/user) public class UserServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { ListUser users userService.getAllUsers(); ResultListUser result Result.success(users); resp.setContentType(application/json;charsetUTF-8); resp.getWriter().write(new ObjectMapper().writeValueAsString(result)); } catch (Exception e) { ResultObject error Result.error(500, 服务器内部错误); resp.getWriter().write(new ObjectMapper().writeValueAsString(error)); } } }这种统一格式让前端可以标准化处理响应根据code判断请求是否成功通过message展示提示信息data中获取业务数据。5. 会话管理与安全控制5.1 JWT认证实现传统的Session机制在分布式系统中会遇到共享问题JWTJSON Web Token是现代Web开发中常用的无状态认证方案。我第一次实现JWT时踩了不少坑最终总结出以下可靠实现public class JwtUtil { private static final String SECRET your-256-bit-secret; private static final long EXPIRATION 86400L; // 24小时 public static String generateToken(User user) { return JWT.create() .withSubject(user.getUsername()) .withClaim(userId, user.getId()) .withClaim(role, user.getRole()) .withExpiresAt(new Date(System.currentTimeMillis() EXPIRATION * 1000)) .sign(Algorithm.HMAC256(SECRET)); } public static boolean validateToken(String token) { try { JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token); return true; } catch (Exception e) { return false; } } public static User getAuthenticatedUser(String token) { DecodedJWT jwt JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token); User user new User(); user.setId(jwt.getClaim(userId).asLong()); user.setUsername(jwt.getSubject()); user.setRole(jwt.getClaim(role).asString()); return user; } }在登录接口中生成TokenWebServlet(/api/login) public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 验证用户名密码... User user userService.login(username, password); String token JwtUtil.generateToken(user); ResultMapString, String result Result.success( Collections.singletonMap(token, token)); resp.getWriter().write(new ObjectMapper().writeValueAsString(result)); } }5.2 权限控制实现有了JWT后我们可以实现基于过滤器的权限控制WebFilter(/api/*) public class AuthFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) res; // 放行登录接口 if (request.getRequestURI().endsWith(/api/login)) { chain.doFilter(req, res); return; } // 获取Token String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { sendError(response, 401, 未授权访问); return; } // 验证Token token token.substring(7); if (!JwtUtil.validateToken(token)) { sendError(response, 401, Token无效或已过期); return; } // 将用户信息存入请求属性 User user JwtUtil.getAuthenticatedUser(token); request.setAttribute(currentUser, user); chain.doFilter(req, res); } private void sendError(HttpServletResponse response, int code, String message) throws IOException { response.setContentType(application/json;charsetUTF-8); response.setStatus(code); response.getWriter().write( new ObjectMapper().writeValueAsString(Result.error(code, message))); } }这个过滤器会检查请求头中的Authorization字段验证JWT的有效性将认证用户信息存入请求属性对于未授权请求返回401错误6. 前端交互实现6.1 Axios基础封装前端我推荐使用Axios进行HTTP请求。为了统一处理请求和响应通常会进行二次封装// 创建Axios实例 const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 5000 }) // 请求拦截器 service.interceptors.request.use( config { // 添加Token到请求头 const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }, error { return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response { const res response.data // 业务逻辑错误处理 if (res.code ! 200) { alert(res.message || Error) return Promise.reject(new Error(res.message || Error)) } else { return res.data } }, error { // HTTP错误处理 if (error.response.status 401) { alert(请重新登录) router.push(/login) } return Promise.reject(error) } ) export default service6.2 前端请求示例封装好后前端调用API就非常简单了import request from /utils/request // 登录 export function login(data) { return request({ url: /login, method: post, data }) } // 获取用户信息 export function getUserInfo() { return request({ url: /user/info, method: get }) }在Vue组件中使用import { login } from /api/user export default { methods: { handleLogin() { this.$store.dispatch(user/login, this.loginForm) .then(() { this.$router.push({ path: / }) }) .catch(() { this.loading false }) } } }7. 项目优化与最佳实践7.1 接口文档生成前后端协作中接口文档是必不可少的。我推荐使用Swagger来自动生成API文档Configuration EnableSwagger2 public class SwaggerConfig { Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(com.example.controller)) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(API文档) .description(系统接口文档) .version(1.0) .build(); } }添加Swagger注解到ControllerRestController RequestMapping(/api/user) Api(tags 用户管理) public class UserController { GetMapping(/{id}) ApiOperation(获取用户详情) public ResultUser getUser(PathVariable Long id) { // ... } }访问/swagger-ui.html即可看到完整的API文档。7.2 全局异常处理统一的异常处理能让代码更整洁。Spring中可以使用ControllerAdviceControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(Exception.class) ResponseBody public ResultVoid handleException(Exception e) { log.error(系统异常, e); return Result.error(500, 系统繁忙请稍后再试); } ExceptionHandler(BusinessException.class) ResponseBody public ResultVoid handleBusinessException(BusinessException e) { return Result.error(e.getCode(), e.getMessage()); } }这样所有未捕获的异常都会被统一处理返回规范的错误响应。

相关文章:

【JavaWeb开发】从零构建前后端交互实战指南

1. JavaWeb前后端交互基础入门 第一次接触JavaWeb开发时,最让我困惑的就是前后端如何传递数据。记得刚开始做项目时,我傻乎乎地用字符串拼接HTML代码返回给前端,结果遇到中文乱码问题折腾了一整天。后来才发现,现代JavaWeb开发早已…...

SWF逆向工程认证培训师手册:基于JPEXS Free Flash Decompiler的教学指南

SWF逆向工程认证培训师手册:基于JPEXS Free Flash Decompiler的教学指南 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款开源的Flash SWF…...

3步释放华硕笔记本潜能:G-Helper轻量化控制工具的极致优化指南

3步释放华硕笔记本潜能:G-Helper轻量化控制工具的极致优化指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops. Control tool for ROG Zephyrus G14, G15, G16, M16, Flow X13, Flow X16, TUF, Strix, Scar and other models …...

Logisim音乐盒背后的数字电路:计数器、ROM与蜂鸣器如何奏出《终生误》

Logisim音乐盒背后的数字电路:计数器、ROM与蜂鸣器如何奏出《终生误》 当一段熟悉的旋律从蜂鸣器中流淌而出,很少有人会思考这背后隐藏的数字魔法。本文将带您拆解一个基于Logisim的音乐盒设计,揭示计数器如何像指挥家一样协调时序、ROM怎样扮…...

别再到处找模板了!我用这套软著申请材料(含用户手册+源代码模板)两个月搞定

两个月高效拿下软著:零基础开发者的材料准备实战指南 第一次提交软著申请时,我盯着官网模糊的材料要求整整发呆了半小时——"用户手册需图文并茂"到底要多详细?"源代码前30页后30页"该怎么截取?连续三个晚上搜…...

终极指南:如何在.NET应用中快速集成VLC多媒体播放功能

终极指南:如何在.NET应用中快速集成VLC多媒体播放功能 【免费下载链接】Vlc.DotNet .NET control that hosts the audio/video capabilities of the VLC libraries 项目地址: https://gitcode.com/gh_mirrors/vl/Vlc.DotNet Vlc.DotNet是一个强大的.NET库&am…...

从SOP到AI Society:MGX多智能体协作平台如何重塑软件开发流程

1. MGX平台如何用SOP机制颠覆传统开发模式 我第一次接触MGX平台时,被它的标准化操作流程(SOP)惊艳到了。这就像把一个混乱的施工现场变成了井然有序的装配线,每个智能体都知道自己该在什么时候做什么事。传统开发中,我…...

SWF逆向工程标准化文档:JPEXS Free Flash Decompiler实施指南

SWF逆向工程标准化文档:JPEXS Free Flash Decompiler实施指南 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款强大的SWF逆向工程工具&…...

Pixel Fashion Atelier保姆级教程:如何将生成结果无缝导入Aseprite进行二次编辑

Pixel Fashion Atelier保姆级教程:如何将生成结果无缝导入Aseprite进行二次编辑 1. 教程概述 Pixel Fashion Atelier是一款基于Stable Diffusion与Anything-v5的像素风格图像生成工具,特别适合创作复古RPG风格的时尚设计。本教程将手把手教你如何将生成…...

ai辅助开发:让快马平台为你的arduino项目注入智能决策与学习能力

AI辅助开发:让快马平台为你的Arduino项目注入智能决策与学习能力 最近在做一个智能垃圾分类的小项目,用Arduino控制各种传感器和舵机来实现自动分类。这个过程中发现,手动编写所有判断逻辑和阈值调整特别耗时,于是尝试用InsCode(…...

OpenClaw多模态探索:Qwen3-32B+RTX4090D镜像截图转报告实践

OpenClaw多模态探索:Qwen3-32BRTX4090D镜像截图转报告实践 1. 为什么选择这个技术组合 上周团队头脑风暴时,我遇到了一个典型痛点:会议室白板上写满了讨论要点,但拍照后整理成电子版纪要需要手动誊写半小时。作为技术负责人&…...

SGMICRO圣邦微 SGM6512YTS28G/TR TDFN-8L(2x2) 模拟开关/多路复用器

特性 典型导通电阻240120开路电阻平坦度3.3V至6V双电源供电操作3.3V至13.2V单电源工作电压-3dB带宽:70MHz轨到轨操作提供绿色TQFN-5x5-32L和TSSOP-28封装 工作温度范围:-40C至85C...

ai辅助开发:告诉快马你的想法,自动生成jdk17最佳实践代码

今天想和大家分享一个特别实用的开发技巧——如何用AI辅助快速掌握JDK17的新特性。作为一个经常需要升级Java版本的开发者,我发现每次版本更新都要花大量时间学习新语法,直到遇到了InsCode(快马)平台的AI辅助功能。 传统开发方式的痛点 以前用JDK8写代码…...

从数据采集到模型部署:用Lerobot+本地数据集训练一个会抓积木的机械臂(避坑指南)

从数据采集到模型部署:用Lerobot本地数据集训练一个会抓积木的机械臂(避坑指南) 当机械臂第一次准确抓取乐高积木并放入指定盒子时,那种成就感远超单纯调通代码的快感。Lerobot框架的出现,让机器人学习从实验室走向个人…...

Win10下mitie安装失败:subprocess.CalledProcessError的深度排查与实战修复

1. 问题现象与初步分析 最近在Windows10系统上折腾MITIE这个自然语言处理工具包时,遇到了一个让人头疼的错误。当时按照常规流程,先下载了mitie的源码压缩包,解压后执行python setup.py install,结果命令行突然弹出一堆红色报错&a…...

每日算法题 17---205.同构字符串

题目 205.同构字符串 要求 给定两个字符串 s 和 t ,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一…...

Stable-Diffusion-v1-5-archive多分辨率实践:512×512 vs 768×768出图质量与耗时对比

Stable-Diffusion-v1-5-archive多分辨率实践:512512 vs 768768出图质量与耗时对比 你是不是也好奇,用Stable Diffusion出图时,分辨率到底该怎么选?是选经典的512512,还是追求更高清的768768?选高了怕电脑跑…...

猫抓插件:革新性浏览器资源捕获工具,让媒体下载效率倍增

猫抓插件:革新性浏览器资源捕获工具,让媒体下载效率倍增 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字内容爆炸的时代,如何高效获取网页中的视频、音频和图…...

LangChainJS性能优化:大规模AI应用的高效处理指南

LangChainJS性能优化:大规模AI应用的高效处理指南 【免费下载链接】langchainjs 项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs LangChainJS是一个强大的JavaScript/TypeScript框架,专门用于构建基于大语言模型(LLM…...

【Python AI 工具实战宝典】:20个高复用AI用例+开箱即用代码模板,限时开源库清单泄露!

第一章:Python AI 工具生态全景与实战价值定位Python 已成为人工智能开发的事实标准语言,其核心优势不在于单一库的性能,而在于高度协同、分层清晰的工具生态体系。从底层计算(NumPy、CuPy)、模型构建(PyTo…...

告别SIFT/ORB!用LoFTR+Transformer搞定低纹理场景的图片匹配(附Python实战代码)

低纹理场景图像匹配实战:LoFTR与Transformer的革新应用 在计算机视觉领域,图像特征匹配一直是三维重建、视觉定位等任务的基础环节。传统方法如SIFT、ORB依赖于特征检测器提取关键点,但在低纹理、重复图案或运动模糊场景中表现往往不尽如人意…...

ArduPilot电机控制逻辑与PWM输出机制剖析

1. ArduPilot电机控制基础概念 当你第一次接触无人机飞控时,最让人困惑的莫过于电机控制逻辑了。想象一下,你手里拿着遥控器,轻轻推动摇杆,无人机就能平稳地上升、下降或者转向。这背后到底发生了什么?让我用最直白的…...

PCap04电容测量实战:从传感器连接到串口通信的完整指南

PCap04电容测量实战:从传感器连接到串口通信的完整指南 当工程师面对高精度电容测量需求时,PCap04芯片往往成为解决复杂问题的关键。这款集成了数字信号处理能力的电容数字转换器(CDC),能够将皮法级电容变化转化为精确的数字信号。不同于传统…...

P15801 [GESP202603 六级] 完全二叉树

[GESP202603 六级] 完全二叉树 https://www.bilibili.com/video/BV1jQAEz3Eir/ 1.4满二叉树与完全二叉树 https://www.bilibili.com/video/BV1T44y1P7Xx/ 数据结构合集 - 二叉树&完全二叉树(定义, 性质) https://www.bilibili.com/video/BV1eQ3RzxEoS/ 202603GESP六级C第2题…...

YOLOv5在边缘设备上部署实战:从Jetson Nano到树莓派,实现实时路面障碍检测

YOLOv5边缘计算部署实战:从Jetson Nano到树莓派的高性能路面检测方案 当自动驾驶小车需要识别前方突然出现的石块,或是智慧路侧单元要实时监控道路异常时,边缘设备上的AI推理能力就成为关键。本文将带您深入探索如何将YOLOv5模型部署到Jetson…...

Zotero-GPT插件:如何正确配置API密钥以激活AI文献分析功能

Zotero-GPT插件:如何正确配置API密钥以激活AI文献分析功能 【免费下载链接】zotero-gpt GPT Meet Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-gpt Zotero-GPT是一款将GPT人工智能能力深度整合到Zotero文献管理软件中的开源插件&#xff0c…...

QobuzDownloaderX-MOD:一站式高品质音乐下载解决方案

QobuzDownloaderX-MOD:一站式高品质音乐下载解决方案 【免费下载链接】QobuzDownloaderX-MOD Downloads streams directly from Qobuz. Experimental refactoring of QobuzDownloaderX by AiiR 项目地址: https://gitcode.com/gh_mirrors/qo/QobuzDownloaderX-MOD…...

SWF逆向工程行业报告:JPEXS Free Flash Decompiler市场份额2025深度分析

SWF逆向工程行业报告:JPEXS Free Flash Decompiler市场份额2025深度分析 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler 在Flash技术逐渐退出主流但仍有大量历史资产需要维护…...

SemanticKITTI数据集评测:DarkNet53Seg、PointNet++等模型谁更强?附复现代码

SemanticKITTI点云语义分割实战:模型选型与性能优化指南 点云语义分割技术正在重塑自动驾驶、机器人导航和三维场景理解等领域的研究范式。作为该领域最具挑战性的基准之一,SemanticKITTI数据集凭借其大规模、高密度标注和真实场景多样性,已成…...

WSABuilds GitHub Actions构建流程解析:自动化CI/CD管道配置

WSABuilds GitHub Actions构建流程解析:自动化CI/CD管道配置 【免费下载链接】WSABuilds Run Windows Subsystem For Android on your Windows 10 and Windows 11 PC using prebuilt binaries with Google Play Store (MindTheGapps) and/or Magisk or KernelSU (ro…...