登录效果
---->index.jsp
index.jsp资源
输入账号
输入密码
点击登录---->login
LoginController
获取请求传递的账号和密码
找寻业务层处理
根据登录结果String给予响应
welcome.jsp
欢迎xx进入系统 xx---昵称
1.在service层中添加一个新的方法 专门获取昵称
登录(查询) 昵称(查询) 影响性能问题
2.在service层原有的登录方法上进行修改
返回值改为user对象(保证业务的判断放在service里)
返回值修改之后 之前的使用习惯有影响
ThreadLocal
1.将所有的资源部署在tomcat上 war包
2.启动tomcat 带着这些资源一起运行
3.浏览器发送请求
请求(资源)----> tomcat解析请求 寻找资源(参考配置文件) html jsp servlet
带着参数 找到一个servlet request.getParameter
将参数传递给service
service将参数传递给dao
dao传递参数给JDBC 负责拼接 SQL
将SQL发送给数据库 执行sql update query
数据库查询的结果ResultSet
交给JDBC(ORM) 将ResultSet拆开 变成对象domain
dao接收JDBC的返回值 交给Service
Service调用dao的方法 获取方法返回值(对象 集合)
Service将返回值拆开 做业务判断 将结果返回给Controller
controller做转发(带着service的返回值)
浏览器解析响应
最终展示
参数浏览器触发通常通过方法传递参数的形式进去的
数据得到的查询结果通常通过方法返回值形式出来的
V: View视图层 HTML(静态信息)+JSP(动态信息) 信息(String)
JSP(HTML标签+EL+JSTL+JS+CSS) EL取值拼接----响应
C: Controller控制层 控制的是信息 Servlet setAttribute(结果);
Servlet(获取请求参数+调用业务+给予响应 转发 重定向 自己给)
通过request接收参数 传递给业务 返回值(业务判断结果)
M: Model模型层 数据模型(数据处理+数据读写+数据存储)
Service数据处理 业务逻辑 domain对象(不通过返回值)
接收方法参数的传递 传递给dao
Dao 数据读写 存储CURD ResultSet拆成对象
接收方法参数的传递 传递给JDBC(ORM) 拼串儿SQL ResultSet返回值
Domain数据存储 一行记录--一个对象
DB: DataBase数据层
MySQL
session对象的管理类
SessionManager{//Tomcat内部的 看不见 sessionMap是单例
private Map<JSESSIONID,HttpSession> sessionMap;
public HttpSession getSession(String JSESSIONID){
return sessionMap.get(JSESSIONID);
}
}
使用的session类 好多个session对象 每一个对象一个人使用
HttpSession{
private Map<String key,Object value> attributeMap;
public Object getAttribute(String key){
return attributeMap.get(key);
}
public void setAttribute(String key,Object value){
attributeMap.put(key,value);
}
}
JSESSIONID(String 标识)-------------> t 当前线程(Thread类型 标识)
通过标识找session(一个箱子)---------->通过t找ThreadLocalMap(一个箱子)
通过session.setAttribute(key,value); ThreadLocalMap.set(this,value);
key自己定义 key已经固定了 this当前对象(ThreadLocal)
我是一个线程t t本身是找箱子的密码
t负责找到我的箱子ThreadLocalMap
这个箱子只有一个格子
找到箱子打开才能获取里面的value
打开箱子需要另一个密码(ThreadLocal对象)
当前t线程配着一个Threadlocal对象 map就是唯一的
value只能存储一个信息 想要存储多个 将多个信息包装起来
Thread
ThreadLocal
ThreadLocalMap(ThreadLocal的内部类)
我们可以通过ThreadLocal来将service的数据保存起来,然后在页面中取出来
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>controller.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
工具类:MySpring
package util;
import java.util.HashMap;
public class MySpring {
private static HashMap<String,Object> beanMap = new HashMap<String,Object>();
public static <T>T getBean(String className){
T obj = (T)beanMap.get(className);
if(obj==null){
try {
Class clazz = Class.forName(className);
obj = (T)clazz.newInstance();
beanMap.put(className,obj);
} catch (Exception e) {
e.printStackTrace();
}
}
return obj;
}
}
工具类:ThreadLocalManager
package util;
import java.util.HashMap;
public class ThreadLocalManager {
//管理不同的ThreadLocal对象 一个人分配一个ThreadLocal
//用每一个人登录的账号作为key 每一个ThreadLocal对象作为值
private static HashMap<String,ThreadLocal> localMap = new HashMap<>();
//通过登录账号获取自己对应的那一个local对象
public static ThreadLocal getThreadLocal(String name){
ThreadLocal local = localMap.get(name);
if(local==null){
local = new ThreadLocal();
localMap.put(name,local);
}
return local;
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<form action="login" method="post">
账号:<input type="text" name="uname" value=""><br>
密码:<input type="password" name="upassword" value=""><br>
<input type="submit" value="登录"><br>
</form>
</body>
</html>
User
package domain;
public class User {
private String uname;
private String upassword;
private String nickname;
public User() {
}
public User(String uname, String upassword,String nickname) {
this.uname = uname;
this.upassword = upassword;
this.nickname = nickname;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpassword() {
return upassword;
}
public void setUpassword(String upassword) {
this.upassword = upassword;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
LoginController
package controller;
import domain.User;
import service.UserService;
import util.MySpring;
import util.ThreadLocalManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginController extends HttpServlet {
private UserService service = MySpring.getBean("service.UserService");
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理字符集
request.setCharacterEncoding("UTF-8");
//获取请求发过来的参数
String uname = request.getParameter("uname");
String upassword = request.getParameter("upassword");
//如果service不改变结构
String result = service.login(uname,upassword);
//根据结果转发
if(result.equals("登录成功")){
//获取service中的那个domain对象
//对象.get("user");
ThreadLocal local = ThreadLocalManager.getThreadLocal(uname);
User user = (User)local.get(); // 将user从ThreadLocal对象的ThreadLocalMap中取出
request.setAttribute("user",user); //然后再将user存入request域中,方便页面的取值
request.getRequestDispatcher("welcome.jsp").forward(request,response);
}else{
request.getRequestDispatcher("index.jsp").forward(request,response);
}
//调用业务层方法做事---原有的
// String result = service.login(uname,upassword);
// //根据结果给予响应(通常转发)
// if(result.equals("登录成功")){
// //需要将昵称带走 交给welcome进行拼接--展示
// String nickName = service.getNickName(uname);
// request.setAttribute("nickName",nickName);
//
// }else{
// request.getRequestDispatcher("index.jsp").forward(request,response);
// }
//如果按照方案二修改原有的service登录方法 返回值类型与平时习惯不一样
// User user = service.login(uname,upassword);
// if(user!=null){
// request.setAttribute("nickName",user.getNickname());
// request.getRequestDispatcher("welcome.jsp").forward(request,response);
// }else{
// request.getRequestDispatcher("index.jsp").forward(request,response);
// }
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
UserService
package service;
import dao.UserDao;
import domain.User;
import util.MySpring;
import util.ThreadLocalManager;
public class UserService {
private UserDao dao = MySpring.getBean("dao.UserDao");
//方案一 再设计一个方法 获取昵称 性能问题
// public String getNickName(String uname){
// String nickName = dao.selectOne(uname).getNickname();
// System.out.println(nickName);
// return nickName;
// }
//方法负责登录
// public User login(String uname,String upassword){
// User user = dao.selectOne(uname);//user对象 包含所有信息 name pass nick
//// if(user!=null && user.getUpassword().equals(upassword)){
//// return "登录成功";
//// }
//// return "用户名或密码错误";
//
// //方案二 修改原有的登录方法
// //方案二 将user对象整体返回 返回值类型与之前一个登录结果看似不同 不习惯
// if(user!=null && user.getUpassword().equals(upassword)){
// return user;
// }
// return user;
// }
//方案三 不改变原有登录方法结构的情况下 将domain对象带走
//想要将结果带走 通常是返回值
//想到了session的特点 某一个地方存储信息 隔着的地方取
public String login(String uname,String upassword){
User user = dao.selectOne(uname);
//将domain对象拆开 做业务逻辑判断
if(user!=null && user.getUpassword().equals(upassword)){
// 对象.set("user",user);
ThreadLocal local = ThreadLocalManager.getThreadLocal(uname);
local.set(user);// local value 将user放入ThreadLocal对象的ThreadLocalMap中
return "登录成功";
}
return "用户名或密码错误";
}
}
UserDao
package dao;
import domain.User;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class UserDao {
//查询单条记录
public User selectOne(String uname){
User resultUser = null;
try {
//JDBC
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/shopping?useSSL=true";
String user = "root";
String password = "root";
String sql = "SELECT UNAME,UPASSWORD,NICKNAME FROM USER WHERE UNAME = ?";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url,user,password);
PreparedStatement pstat = conn.prepareStatement(sql);
pstat.setString(1,uname);
ResultSet rs = pstat.executeQuery();
if(rs.next()){
resultUser = new User();
resultUser.setUname(rs.getString("uname"));
resultUser.setUpassword(rs.getString("upassword"));
resultUser.setNickname(rs.getString("nickname"));
}
rs.close();
pstat.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
return resultUser;
}
}
ThreadLocal的set方法源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); // 获取线程t中的ThreadLocalMap
if (map != null)
map.set(this, value); // 见代码1
else
createMap(t, value); // 创建新的ThreadLocalMap
}
welcome.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
欢迎${requestScope.user.nickname}进入系统<br>
</body>
</html>
网友评论