I know, i know
地球另一端有你陪我
一、单机版
package com.fgh.spring.test;
import com.fgh.spring.util.JDBCUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/*
@RestController 返回数据
@Controller 返回页面(即文件夹)
一般存放于resources\templates(html)
需要下载包和指定路径
Spring自动识别注解
@RestController当前类与前段地址绑定
@RequestMapping("/name") 把类下的方法,与注解路径绑定
http://localhost/8080/name
name不可重复!被注释了也不行!
http://localhost:8080/login?name=root&pass=123456
传参的格式
第一种方式:全堆在一起
*/
@RestController
public class UserController {
@RequestMapping("/test")
public String test() {
return "start2";
}
@RequestMapping("/login")
public String login(String name, String pass) {
if (!"root".equals(name) || !"123456".equals(pass)) {
return "失败";
}
return "成功";
}
@RequestMapping("/userlogin")
public String userlogin(String name, String pass) {
try {
JDBCUtil.getConn();
String sql = "select * from user where username=?";
PreparedStatement ps = JDBCUtil.getPs(sql);
ps.setString(1,name);
ResultSet rs = JDBCUtil.getRs();
if (!rs.next()) {
return "用户名不存在";
}
User user = new User(rs.getString("id"),
rs.getString("username"),
rs.getString("password"));
if (!user.getPassword().equals(pass)) {
return "密码错误";
}
} catch (Exception e) {
e.printStackTrace();
}
return "登录成功";
}
}
二、引入分层
bean :存放资源文件
controller :表现层 / 前端交互
service :业务逻辑层 / 逻辑验证
dao :持久层 / 连接SQL
bean
存储对象类的基本信息
需要导包
lombok.jar
package com.fgh.spring.mvc.bean;
/*
lombok.jar
可以在自定义类中自动添加
有(无)参构造
get、set方法
tosString方法等
*/
import lombok.*;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private String id;
private String username;
private String password;
}
dao :持久层 / 连接SQL
package com.fgh.spring.mvc.dao;
import com.fgh.spring.mvc.bean.User;
import com.fgh.spring.util.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDao {
//连接数据库
//按照输入的name从数据库中获得对应的数据
//存储到 user 对象之中,并返回
public User getuser(String username){
User user=null;
try {
Connection conn = JDBCUtil.getConn();
String sql = "select * from user where username=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,username);
ResultSet rs = ps.executeQuery();
if(rs.next()){
user = new User();
user.setId(rs.getString("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
rs.close();
ps.close();
//此处连接的关闭,是将连接放回连接池
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
}
service :业务逻辑层 / 逻辑验证
package com.fgh.spring.mvc.service;
import com.fgh.spring.mvc.bean.User;
import com.fgh.spring.mvc.dao.UserDao;
//业务逻辑层 验证
public class UserService {
public String checkUser(String username, String password) {
if (username == null) {
return "请填写用户名";
}
UserDao ud = new UserDao();
User user = ud.getuser(username);
if (user == null) {
return "用户名不存在";
}
if (!user.getPassword().equals(password)) {
return "用户名或密码错误";
}
return "登陆成功";
}
}
controller :表现层 / 前端交互
package com.fgh.spring.mvc.controller;
import com.fgh.spring.mvc.service.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@RequestMapping("/login")
public String login(String username,String password){
UserService us = new UserService();
String message = us.checkUser(username, password);
return message;
}
}
1、优化:连接池
需要导包
dbcp2.jar
一个池子里塞多个连接
JDBCUtil JDBC工具
package com.fgh.spring.util;
/*
连接池,同时储存多个连接
可以让系统在使用连接的时候
拥有一定的容错
例如当网络中断后,
原本的静态代码块只会运行一次,所有就会彻底中断连接
而连接池可以保证再次联网后,可以使用另一个连接
*/
import org.apache.commons.dbcp2.BasicDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class JDBCUtil {
private static BasicDataSource bds;
//创建连接池
static{
//创建连接池对象
bds = new BasicDataSource();
//配置连接池大小
bds.setInitialSize(5);
//配置连接信息
bds.setUrl("jdbc:mysql://master:3306/fghdata?useUnicode=true&characterEncoding=utf-8");
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUsername("root");
bds.setPassword("123456");
}
public static Connection getConn(){
try {
return bds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
2、优化:加入缓冲
缓冲是应对被高频访问的对象
将对象提前提前取出并储存,跳过搜索数据库步骤
可以大幅度提高效率
考虑到其特性,此处使用 HashMap 实现
service
//创建 HashMap 作为缓冲区
private static HashMap<String, User> map = new HashMap<String, User>();
public String selectUser(String id) {
/**
* 1.先查缓存
* 1.1有:直接返回数据
* 1.2没有:去数据库中查,并把结果保存到缓存
*/
// 先查缓存 有:直接返回数据
if (map.containsKey(id)) {
System.out.println("存在");
return map.get(id).toString();
}
//1.2没有:去数据库中查,并把结果保存到缓存
UserDao userDao = new UserDao();
User students = userDao.select(id);
if (students == null) {
return "用户不存在";
}
map.put(students.getId(), students);
System.out.println("存储到缓存" + map.get(id).getId());
return students.toString();
}
3、优化:加入接口
为了应对不同场景下的自由切换,如 mysql 和其他数据库的切换
尽可能的减少代码的修改,会使用不同的类来加载同名的方法
此时引入接口,将会让代码变得更为规范和易处理
interface UserDao {
//连接数据库
//按照输入的name从数据库中获得对应的数据
//存储到 user 对象之中,并返回
public abstract User getuser(String username);
public User select(String id);
}
public class UserDaoMySqlImp implements UserDao{
//连接数据库
//按照输入的name从数据库中获得对应的数据
//存储到 user 对象之中,并返回
public User getuser(String username){
User user=null;
try {
Connection conn = JDBCUtil.getConn();
String sql = "select * from user where username=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,username);
ResultSet rs = ps.executeQuery();
if(rs.next()){
user = new User();
user.setId(rs.getString("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
rs.close();
ps.close();
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
public User select(String id){
User user=null;
try {
Connection conn = JDBCUtil.getConn();
PreparedStatement ps =
conn.prepareStatement("select * from students where id=?");
ps.setString(1,id);
ResultSet rs = ps.executeQuery();
if(rs.next()){
user = new User();
user.setId(rs.getString("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
rs.close();
ps.close();
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
}
总结
1、@RequestMapping 不允许重名
2、地址中,使用?username=xxx&password=xxx,进行传参
3、executequarry() 返回的并不是一个集合,可以理解为是一个 sql 表格
可以通过列名获得一整列元素
4、连接池中的 close,是将连接放回连接池中