打开Tomcat的网站webapps目录,扔进去一个写好的用户JSP项目,浏览器输入localhost:8080/xxx,管理一个能跑的网站用户管理页面就出来了。这事放在2005年,用户算前端后端一把梭的管理典型操作。现在看有点土,网站但理解JSP怎么处理用户数据,用户对搞清Java Web的管理底层逻辑仍然有用。
用户管理最核心的网站动作就三个:登录、列表展示、用户增删改。管理JSP本身是网站Servlet的封装,页面里写Java代码,用户`<% %>`包住逻辑,管理`<%= %>`输出变量。我第一次写登录验证时,把用户名密码硬编码在JSP里判断,现在想想确实粗糙,但当时跑通了还挺兴奋。
<% String username = request.getParameter("username"); String password = request.getParameter("password"); if("admin".equals(username) && "123456".equals(password)){ session.setAttribute("user", username); response.sendRedirect("userList.jsp"); } else { out.print("登录失败"); } %> 这段代码暴露了JSP的典型问题——业务逻辑和页面渲染搅在一起。真实项目里,登录验证应该丢给Servlet或Filter,JSP只负责显示。但教学阶段这么写能快速看到效果,理解request、session、response这三个内置对象怎么配合。
用户列表页更典型。从数据库查数据,遍历输出到表格。假设用JDBC连MySQL,代码大概长这样:
<%@ page import="java.sql.*" %> <table> <tr><th>ID</th><th>用户名</th><th>操作</th></tr> <% Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123"); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select * from users"); while(rs.next()){ %> <tr> <td><%= rs.getInt("id") %></td> <td><%= rs.getString("username") %></td> <td><a href="deleteUser.jsp?id=<%= rs.getInt("id") %>">删除</a></td> </tr> <% } %> </table> 这种写法在小型项目里能跑,但连接池、SQL注入、异常处理全没管。我见过一个真实案例:某内部系统用JSP直接拼SQL,结果登录框输入`' or '1'='1`就能进后台。后来加了个PreparedStatement才堵住。
删除用户的逻辑放在单独JSP里,接收id参数执行delete语句,然后重定向回列表页。这里有个坑——如果用户直接改URL里的id,能删掉任意记录。所以后端必须校验当前登录用户有没有权限。JSP时代很多人忽略这点,因为页面跳转看起来“很自然”,但HTTP请求可不管这些。
修改用户稍微麻烦点。先查出来渲染到表单,提交后update。表单里通常藏一个hidden的id字段,防止改错行。我习惯在update之前再查一次数据库,确认这条记录还存在,否则并发场景下容易出问题。当然,JSP页面里写这些逻辑会让代码越来越臃肿,所以后来才有了MVC和框架。
分页也是用户管理绕不开的。JSP里做分页一般用`limit`加`offset`,配合page参数。比如每页10条,当前第2页,SQL就是`select * from users limit 10 offset 10`。页码导航用循环输出链接,当前页高亮。这些细节写一遍就记住了,比看十篇教程管用。
最后说个观察:JSP的`<jsp:include>`和`<%@ include %>`经常被混用。前者是运行时包含,后者是编译时包含。做用户管理时,把页头、页尾、侧边栏拆成单独文件,用`jsp:include`引入,改一处全站生效。但如果你在包含的文件里定义了同名变量,编译时包含会直接报错,运行时包含则可能覆盖——这个区别踩过坑才分得清。
用JSP写用户管理,代码不优雅,但能让你看清一个请求从浏览器到数据库再回到页面的完整路径。现在Spring Boot几行注解搞定的事,当年得手写几十行JSP加Servlet。理解这些笨功夫,后面用框架时才知道它帮你省掉了什么。