Пользовательский модуль
Вы можете купить его только после входа в систему, поэтому давайте сначала напишем модуль покупки.
объект дизайна
private String id;
private String username;
private String password;
private String email;
private String cellphone;
private String address;
//各种setter、getter
Проектировать таблицы базы данных
CREATE TABLE user (
id VARCHAR(40) PRIMARY KEY,
username VARCHAR(20) NOT NULL,
cellphone VARCHAR(20) NOT NULL,
address VARCHAR(40) NOT NULL,
email VARCHAR(30),
password VARCHAR(30) NOT NULL
);
##Написать ДАО##
/**
* 用户的登录注册模块
* 1:登陆
* 2:注册
* 3:根据id查找具体的用户
*/
public class UserDaoImpl {
public void register(User user) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "INSERT INTO user (id,username,cellphone,address,email,password) VALUES(?,?,?,?,?,?)";
try {
queryRunner.update(sql, new Object[]{user.getId(),user.getUsername(), user.getCellphone(), user.getAddress(), user.getEmail(), user.getPassword()});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public User login(String username, String password) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM user WHERE username = ? AND password=?";
try {
return (User) queryRunner.query(sql, new Object[]{username, password}, new BeanHandler(User.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public User find(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM user WHERE id=?";
try {
return (User) queryRunner.query(sql, id, new BeanHandler(User.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Протестируйте ДАО
public class UserDemo {
UserDaoImpl userDao = new UserDaoImpl();
@Test
public void add() {
User user = new User();
user.setId("1");
user.setUsername("zhong");
user.setPassword("123");
user.setCellphone("10085");
user.setAddress("广州萝岗");
user.setEmail("40368324234234@QQ.com");
userDao.register(user);
}
@Test
public void find() {
String id = "1";
User user = userDao.find(id);
System.out.println(user.getEmail());
}
@Test
public void login() {
String username = "zhong";
String password = "123";
User user = userDao.login(username, password);
System.out.println(user.getAddress());
}
}
Извлечь DAO
public interface UserDao {
void register(User user);
User login(String username, String password);
User find(String id);
}
Служба записи
private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);
public void registerUser(User user) {
userDao.register(user);
}
public User loginUser(String username,String password) {
return userDao.login(username, password);
}
public User findUser(String id) {
return userDao.find(id);
}
Передний стиль
- head.jsp
<div id="User">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<button name="login">登陆</button>
<button name="register">注册</button>
</div>
- head.css
#body {
position: relative;
}
#user {
position: absolute;
margin-top: 130px;
margin-left: 1364px;
}
- Эффект:
Реализовать функцию входа и регистрации
При нажатии кнопки входа данные передаются сервлету, и сервлет вызывает метод BusinessService для реализации входа в систему.. Регистрация такая же... Поэтому нам нужно использовать код JavaScript
- head.jsp
<c:if test="${user==null}" >
<div id="User">
用户名:<input type="text" id="username">
密码:<input type="password" id="password">
<button name="login" onclick="login()">登陆</button>
<button name="register" onclick="register()">注册</button>
</div>
</c:if>
<c:if test="${user!=null}" >
<div id="User">
欢迎您:${user.username} <a href="${pageContext.request.contextPath}/UserServlet?method=Logout">注销</a>
</div>
</c:if>
- JavaScript-код
<script type="text/javascript">
function login() {
//得到输入框的数据
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
//跳转到相对应的Servlet上
window.location.href = "${pageContext.request.contextPath}/UserServlet?method=login&username=" + username + "&password=" + password;
}
function register() {
//跳转到注册页面
window.location.href = "${pageContext.request.contextPath}/client/register.jsp";
}
</script>
- UserServlet
String method = request.getParameter("method");
BussinessServiceImpl service = new BussinessServiceImpl();
if (method.equals("login")) {
try {
//得到页面传递过来的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = service.loginUser(username, password);
request.getSession().setAttribute("user",user);
request.getRequestDispatcher("/client/head.jsp").forward(request, response);
} catch (Exception e) {
request.setAttribute("message", "登陆失败了!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
} else if (method.equals("register")) {
try {
//得到JSP传递过来的数据,封装成Bean对象
User user = WebUtils.request2Bean(request, User.class);
user.setId(WebUtils.makeId());
service.registerUser(user);
request.setAttribute("message", "注册成功了!");
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "注册失败了!");
}
request.getRequestDispatcher("/message.jsp").forward(request, response);
} else if (method.equals("Logout")) {
//销毁session
request.getSession().invalidate();
//回到首页
request.getRequestDispatcher("/client/head.jsp").forward(request, response);
}
купить модуль
При отображении книги добавить гиперссылку на покупку кстати
<li><a href="#">购买</a></li>
Дизайн корзины покупок
Если вы не уверены, почему он разработан таким образом, вы можете обратиться к моему предыдущему сообщению в блоге:blog.CSDN.net/hon_3 has/Aretti…
- Корзина
public class Cart {
private Map<String, CartItem> map = new HashMap<>();
private double price;
//提供把商品添加到购物的功能
public void addBook2Cart(Book book) {
//得到对应的购物项
CartItem cartItem = map.get(book.getId());
//如果是null,说明购物车还没有该购物项
if (cartItem == null) {
cartItem = new CartItem();
cartItem.setQuantity(1);
cartItem.setBook(book);
cartItem.setPrice(book.getPrice());
//把购物项加到购物车中
map.put(book.getId(), cartItem);
} else {
//如果购物车有该购物项了,那么将购物项的数量+1
cartItem.setQuantity(cartItem.getQuantity() + 1);
}
}
//购物车的价钱是购物项价钱的总和
public double getPrice() {
double totalPrice = 0;
for (Map.Entry<String, CartItem> me : map.entrySet()) {
CartItem cartItem = me.getValue();
totalPrice += cartItem.getPrice();
}
return totalPrice;
}
public Map<String, CartItem> getMap() {
return map;
}
public void setMap(Map<String, CartItem> map) {
this.map = map;
}
public void setPrice(double price) {
this.price = price;
}
}
Создание сущности предмета покупок
public class CartItem {
private Book book;
private double price;
private int quantity;
public double getPrice() {
return this.book.getPrice() * this.quantity;
}
public void setPrice(double price) {
this.price = price;
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
Сервлет, который обрабатывает книгу, которую пользователь хочет купить
<li><a href="${pageContext.request
.contextPath}/BuyServlet?book_id=${book.id}">购买</a></li>
- BuyServlet
BussinessServiceImpl service = new BussinessServiceImpl();
//先检查该用户是否登陆了。
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "您还没登陆,请登陆了再来购买");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return ;
}
//如果登陆了...
//得到该用户的购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
request.getSession().setAttribute("cart", cart);
}
//得到用户想买的书籍
String book_id = request.getParameter("book_id");
Book book = service.findBook(book_id);
//把书籍添加到购物车中
service.buyBook(cart, book);
request.setAttribute("message", "该商品已添加到购物车中");
request.getRequestDispatcher("/message.jsp").forward(request,response);
Предоставляет сервлет, отображающий товары в корзине.
//先判断该用户是否登陆了
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "您还没有登陆呢!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//如果登陆了.....
Cart cart = (Cart) request.getSession().getAttribute("cart");
//把该用户的购物车给JSP页面显示
request.setAttribute("cart", cart);
request.getRequestDispatcher("/client/listCart.jsp").forward(request, response);
Страница JSP с корзиной покупок
<c:if test="${empty(cart.map)}">
您还没有购买过任何商品哦!!!
</c:if>
<table border="1px">
<c:if test="${!empty(cart.map)}">
<h1>您购物车下有如下的商品:</h1><br>
<tr>
<td>书名:</td>
<td>作者:</td>
<td>数量:</td>
<td>价钱:</td>
</tr>
<c:forEach items="${cart.map}" var="cartItme">
<tr>
<td>${cartItme.value.book.name}</td>
<td>${cartItme.value.book.author}</td>
<td>${cartItme.value.quantity}</td>
<td>${cartItme.value.price}</td>
</tr>
</c:forEach>
</c:if>
</table>
Эффект:
модуль заказа
Во внешнем пользовательском интерфейсе, когда пользователь хочет заплатить за корзину, должна быть предоставлена гиперссылка для создания заказа....
Сущность заказа на проектирование
Заказ должен содержать id, информацию о грузополучателе, время оформления заказа, общую стоимость заказа, статус заказа [с доставкой или без]. Он не должен содержать информацию о продукте. Информация о продукте представлена в виде отдельной позиции.
Заказ соответствует нескольким позициям, что является отношением «один ко многим»!
private String id;
//下单的时间、日期、状态
private Date date;
private double price;
private boolean state;
//一个用户可以有多个订单,把用户记住
private String user_id;
//一个订单中有多个订单项
private Set<OrderItem> items = new HashSet<>();
//各种的setter和getter
Дизайн позиции позиции
private String id;
//一本书对应多个订单项,订单项一定是由书组成,记住书
private String book_id;
private double price;
private int quantity;
//各种的setter和getter
Проектировать таблицы базы данных
- форма заказа
mysql не может создать таблицу с именем «порядок», просто добавьте после нее s
CREATE TABLE orders (
id VARCHAR(40) PRIMARY KEY,
date DATE NOT NULL,
user_id VARCHAR(40) NOT NULL,
state BOOLEAN,
price DOUBLE,
CONSTRAINT user_id_FK FOREIGN KEY (user_id) REFERENCES user (id)
);
- Заказать Таблица предметов:
CREATE TABLE orderItem (
id VARCHAR(40) PRIMARY KEY,
price DOUBLE,
quantity INT,
order_id VARCHAR(40) ,
book_id VARCHAR(40) ,
CONSTRAINT order_id_FK FOREIGN KEY (order_id) REFERENCES orders (id),
CONSTRAINT book_id_FK FOREIGN KEY (book_id) REFERENCES book (id)
);
- Структура между таблицами:
Дизайн Дао
public class OrderDaoImpl implements zhongfucheng.dao.OrderDao {
@Override
public void addOrder(Order order) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql1 = "INSERT INTO orders(id,ordertime,user_id,state,price) VALUES(?,?,?,?,?)";
try {
//订单的基本信息
queryRunner.update(sql1, new Object[]{order.getId(), order.getOrdertime(), order.getUser_id(), order.isState(), order.getPrice()});
//订单项的信息
String sql2 = "INSERT INTO orderItem(id,price,quantity,order_id,book_id) VALUES(?,?,?,?,?)";
Set<OrderItem> items = order.getItems();
for (OrderItem item : items) {
queryRunner.update(sql2, new Object[]{item.getId(), item.getPrice(), item.getQuantity(), item.getOrder_id(), item.getBook_id()});
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Order findOrder(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
Order order;
try {
//找出订单的基本信息
String sql = "SELECT * FROM orders WHERE id=?";
order = (Order) queryRunner.query(sql, new BeanHandler(Order.class), new Object[]{id});
//找出订单的所有订单项
String sql2 = "SELECT * FROM orderItem WHERE order_id=?";
List<OrderItem> list = (List<OrderItem>) queryRunner.query(sql2, new BeanListHandler(OrderItem.class), new Object[]{order.getId()});
System.out.println("这是数据库拿到的list集合:"+list.size());
//将所有订单项装到订单里边
order.getItems().addAll(list);
System.out.println("这是数据库拿到的"+order.getItems().size());
//找出该订单是属于哪一个用户的
String sql3 = "SELECT * FROM orders o,user u WHERE o.user_id=u.id AND o.id=? ";
User user = (User) queryRunner.query(sql3, new BeanHandler(User.class), new Object[]{order.getId()});
order.setUser_id(user.getId());
return order;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//更新订单的状态
public void updateState(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "UPDATE orders SET state=? WHERE id=?";
try {
queryRunner.update(sql, new Object[]{true, id});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//查看已经发货或没发货的订单信息
public List<Order> getAllOrder(boolean state) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM orders WHERE state=? ";
try {
return (List<Order>) queryRunner.query(sql, new BeanListHandler(Order.class), new Object[]{state});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//通过用户的id查找用户的订单,可能不止一个
public List<Order> findUserOrder(String user_id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT * FROM orders WHERE user_id=? ";
try {
return List<Order> queryRunner.query(sql, new BeanHandler(Order.class), new Object[]{user_id});
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Второе обновление
При написании дао, особенно метод Add. Он инкапсулирует все данные в объект Order, затем извлекает данные и вставляет данные в таблицу данных.
- На самом деле наши операции Order и OrderItem можно разделить. OrderItem также может написать другой Dao, затем после того, как мы вставим объект Order,Получите первичный ключ, возвращенный объектом Order, а затем вызовите метод OrderItemDao, чтобы вставить данные OrderItem.Поэтому я думаю, что это делает код более понятным.
- CORDUTITEMDAO получен в списке, потому что мы закажем соответствующее количество строк элементов.
Извлечь в интерфейс DAO
public interface OrderDao {
void addOrder(Order order);
Order findOrder(String id);
List<Order> getAllOrder(boolean state);
void updateState(String user_id);
List<Order> findUserOrder(String user_id);
}
BussinessService
private OrderDao orderDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.OrderDaoImpl", OrderDao.class);
public void createOrder(Cart cart, User user) {
//订单的基本信息
String order_id = WebUtils.makeId();
Order order = new Order();
order.setId(order_id);
order.setPrice(cart.getPrice());
order.setOrdertime(new Date());
order.setState(false);
order.setUser_id(user.getId());
//订单项的基本信息
//得到每个购物项,购物项就作为订单项
for (Map.Entry<String, CartItem> me : cart.getMap().entrySet()) {
OrderItem orderItem = new OrderItem();
CartItem cartItem = me.getValue();
orderItem.setId(WebUtils.makeId());
orderItem.setPrice(cartItem.getPrice());
orderItem.setBook_id(cartItem.getBook().getId());
orderItem.setQuantity(cartItem.getQuantity());
orderItem.setOrder_id(order_id);
order.getItems().add(orderItem);
}
orderDao.addOrder(order);
}
public Order findOrder(String user_id) {
return orderDao.findOrder(user_id);
}
public List<Order> getAllOrder(boolean state) {
return orderDao.getAllOrder(state);
}
public void sendOutOrder(String id) {
orderDao.updateState(id);
}
public List<Order> findUserOrder(String user_id) {
return orderDao.findUserOrder(user_id);
}
Сервлет, генерирующий порядок
BussinessServiceImpl service = new BussinessServiceImpl();
//检查该用户的购物车是否有商品
Cart cart = (Cart) request.getSession().getAttribute("cart");
if (cart == null) {
request.setAttribute("message", "您购物车没有商品,无法生成订单");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//如果有商品,得到当前用户
User user = (User) request.getSession().getAttribute("user");
service.createOrder(cart, user);
request.setAttribute("message", "订单已经生成了,准备好钱来收货把");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
Пользователи запрашивают свой собственный сервлет заказа
<a href="${pageContext.request.contextPath}/LookOrder" target="body">查看订单</a>
BussinessServiceImpl service = new BussinessServiceImpl();
//检查该用户是否登陆了
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
request.setAttribute("message", "您还没登陆,等您登陆了再来看把");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//用户登陆了!
Order order = service.findUserOrder(user.getId());
//交给相对应的JSP 显示
request.setAttribute("order", order);
request.setAttribute("user",user);
request.getRequestDispatcher("/client/listOrder.jsp").forward(request, response);
return ;
JSP, показывающий данные заказа
<c:if test="${order==null}">
您还没有下过任何订单!!
</c:if>
<c:if test="${order!=null}">
<table border="1px">
<tr>
<td>下单人:</td>
<td>订单时间</td>
<td>订单状态</td>
<td>订单价钱</td>
</tr>
<tr>
<td>${user.username}</td>
<td>${order.ordertime}</td>
<td>${order.state==false?"未发货":"已发货"}</td>
<td>${order.price}</td>
</tr>
</table>
</c:if>
Эффект:
Сервлет состояния заказа фонового запроса
<a href="${pageContext.request.contextPath}/OrderServlet?state=false" target="body">待处理订单</a><br>
<a href="${pageContext.request.contextPath}/OrderServlet?state=true" target="body">已发货订单</a><br>
BussinessServiceImpl service = new BussinessServiceImpl();
String state = request.getParameter("state");
if (state.equals("true")) {
List<Order> list = service.getAllOrder(true);
request.setAttribute("list",list);
} else if (state.equals("false")) {
List<Order> list = service.getAllOrder(false);
request.setAttribute("list", list);
}
request.getRequestDispatcher("/background/listOrder.jsp").forward(request, response);
JSP, показывающий статус заказа
<c:if test="${empty(list)}">
还没有任何订单哦!
</c:if>
<c:if test="${!empty(list)}">
<table border="1px">
<tr>
<td>下单人:</td>
<td>订单时间</td>
<td>订单状态</td>
<td>订单价钱</td>
<td>操作</td>
</tr>
<c:forEach items="${list}" var="order">
<tr>
<td>${order.user_id}</td>
<td>${order.ordertime}</td>
<td>${order.state==false?"未发货":"已发货"}</td>
<td>${order.price}</td>
<td>
<a href="${pageContext.request.contextPath}/orderItemServlet?order_id=${order.id}">查看详细信息</a>
<a href="#">删除</a>
</td>
</tr>
</c:forEach>
</table>
</c:if>
Просмотр сведений о конкретном сервлете заказа
BussinessServiceImpl service = new BussinessServiceImpl();
//得到用户想要查看详细信息的表单
String order_id = request.getParameter("order_id");
Order order = service.findOrder(order_id);
//将该order对象给相对应的JSP显示
request.setAttribute("order", order);
request.getRequestDispatcher("/background/listDetail.jsp").forward(request, response);
Просмотр сведений о конкретном заказе JSP
<table border="1px">
<tr>
<td>书籍的编号</td>
<td>价钱</td>
<td>数量</td>
<td>操作</td>
</tr>
<c:forEach items="${order.items}" var="item">
<tr>
<td>${item.book_id}</td>
<td>${item.price}</td>
<td>${item.quantity}</td>
<td><a href="${pageContext.request.contextPath}/SendOutServlet?id=${order.id}">发货</a></td>
</tr>
</c:forEach>
</table>
Сервлет для обработки отгрузки##
BussinessServiceImpl service = new BussinessServiceImpl();
String id = request.getParameter("id");
service.sendOutOrder(id);
request.setAttribute("message", "已发货!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
Эффект:
Добавить контроль разрешений
До сих пор мы узнали о технологии динамических прокси и технологии аннотаций. Итак, мы хотим добавить контроль разрешений в предыдущий проект bookStore.....
Только когда у пользователя есть разрешение, фоновое управление может выполнять соответствующую операцию......
Реализовать идеи
Когда мы использовали систему управления разрешениями, мы судили, нужно ли ссылке разрешение, на основе URI, запрошенного пользователем. На этот раз мы используем технологию динамического прокси и аннотации, чтобы судить:Когда пользователь вызывает метод, проверьте, требует ли метод разрешения...
В соответствии с шаблоном MVC мы вызываем сервисный уровень в веб-слое для реализации функций. Итак, наша конкретная идея заключается в следующем:
- Когда веб-слой вызывает сервисный слой,Мы получаем не объект ServiceDao, а наш прокси-объект
- Добавьте аннотацию к методу на сервисном уровне. Если есть аннотация к методу, это означает, что для вызова метода требуется разрешение...
- Когда веб-уровень вызывает метод прокси-объекта, прокси-объект определяет, требуется ли методу разрешение, а затем выдает соответствующий запрос. …
Объекты дизайна, таблицы базы данных
Система управления разрешениями, которую мы сделали в прошлый раз, представила концепцию ролей, на этот раз она предназначена в основном для практики динамических прокси и технологии аннотаций, поэтому мы сосредоточимся на простоте и не будем вводить сущность роли. напрямуюОтношения между пользователями и разрешениями.
Привилегированный объект
public class Privilege {
private String id ;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Таблица базы данных
- таблица привилегий
CREATE TABLE privilege (
id VARCHAR(40) PRIMARY KEY,
name VARCHAR(40)
);
Привилегия и пользователь находятся в отношениях «многие ко многим», поэтому для поддержания их отношений используется сторонняя таблица.
- таблица user_privacy
CREATE TABLE user_privilege (
privilege_id VARCHAR(40),
user_id VARCHAR(40),
PRIMARY KEY (privilege_id, user_id),
CONSTRAINT privilege_id_FK FOREIGN KEY (privilege_id) REFERENCES privilege(id),
CONSTRAINT user_id_FK1 FOREIGN KEY (user_id) REFERENCES user(id)
);
Добавить тестовые данные
Для удобства данные добавляются напрямую. Я не буду писать подробный DAO.
- Добавлено два разрешения в базу данных
- Добавлено два разрешения для пользователя с id 1
Написание DAO
Позже в динамическом прокси нам нужно проверить, есть ли у пользователя разрешения... затем мы должны выяснитьКакие права есть у пользователя. Проверьте, есть ли у пользователя соответствующие разрешения
//查找用户的所有权限
public List<Privilege> findUserPrivilege(String user_id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = "SELECT p.* FROM privilege p, user_privilege up WHERE p.id = up.privilege_id AND up.user_id = ?";
try {
return (List<Privilege>) queryRunner.query(sql, new Object[]{user_id}, new BeanListHandler(Privilege.class));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
извлечь в интерфейс
List<Privilege> findUserPrivilege(String user_id);
Модуль аннотаций
- писать аннотации
@Retention(RetentionPolicy.RUNTIME)
public @interface permission {
String value();
}
- Добавьте аннотацию CategoryServiceImpl, где требуется разрешение в методе уровня службы.
@permission("添加分类")
/*添加分类*/
public void addCategory(Category category) {
categoryDao.addCategory(category);
}
/*查找分类*/
public void findCategory(String id) {
categoryDao.findCategory(id);
}
@permission("查找分类")
/*查看分类*/
public List<Category> getAllCategory() {
return categoryDao.getAllCategory();
}
Извлечение службы
Извлеките метод Service в ServiceDao. В Servlet объект Service также получается через ServiceFactory [аналогично DaoFactory]
CategoryService
@permission("添加分类")
/*添加分类*/ void addCategory(Category category);
/*查找分类*/
void findCategory(String id);
@permission("查找分类")
/*查看分类*/ List<Category> getAllCategory();
ServiceFactory
public class ServiceDaoFactory {
private static final ServiceDaoFactory factory = new ServiceDaoFactory();
private ServiceDaoFactory() {
}
public static ServiceDaoFactory getInstance() {
return factory;
}
//需要判断该用户是否有权限
public <T> T createDao(String className, Class<T> clazz, final User user) {
System.out.println("添加分类进来了!");
try {
//得到该类的类型
final T t = (T) Class.forName(className).newInstance();
//返回一个动态代理对象出去
return (T) Proxy.newProxyInstance(ServiceDaoFactory.class.getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, PrivilegeException {
//判断用户调用的是什么方法
String methodName = method.getName();
System.out.println(methodName);
//得到用户调用的真实方法,注意参数!!!
Method method1 = t.getClass().getMethod(methodName,method.getParameterTypes());
//查看方法上有没有注解
permission permis = method1.getAnnotation(permission.class);
//如果注解为空,那么表示该方法并不需要权限,直接调用方法即可
if (permis == null) {
return method.invoke(t, args);
}
//如果注解不为空,得到注解上的权限
String privilege = permis.value();
//设置权限【后面通过它来判断用户的权限有没有自己】
Privilege p = new Privilege();
p.setName(privilege);
//到这里的时候,已经是需要权限了,那么判断用户是否登陆了
if (user == null) {
//这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。
throw new PrivilegeException("对不起请先登陆");
}
//执行到这里用户已经登陆了,判断用户有没有权限
Method m = t.getClass().getMethod("findUserPrivilege", String.class);
List<Privilege> list = (List<Privilege>) m.invoke(t, user.getId());
//看下权限集合中有没有包含方法需要的权限。使用contains方法,在Privilege对象中需要重写hashCode和equals()
if (!list.contains(p)) {
//这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。
throw new PrivilegeException("您没有权限,请联系管理员!");
}
//执行到这里的时候,已经有权限了,所以可以放行了
return method.invoke(t, args);
}
});
} catch (Exception e) {
new RuntimeException(e);
}
return null;
}
}
PrivilegeExcetption
Когда пользователь не вошел в систему или не имеет разрешений, мы должны дать пользователю несколько дружественных подсказок... Итак, мы настроили PrivilegeException
public class PrivilegeException extends Exception {
public PrivilegeException() {
super();
}
public PrivilegeException(String message) {
super(message);
}
public PrivilegeException(String message, Throwable cause) {
super(message, cause);
}
public PrivilegeException(Throwable cause) {
super(cause);
}
}
То, что мы наследуем, — это Exception, которое вызывается именем метода. но мыМетоды вызываются через прокси-объекты, поэтому стратегия Sun состоит в том, чтобы преобразовать их в исключения времени выполнения и отбросить..
Поэтому мыПолучите исключение для сервлета, а затем дайте дружескую подсказку. .
Эффект:
- Если вы не вошли в систему:
- Когда вы вошли в систему, но не имеете соответствующих разрешений
- вошли в систему и имеют разрешение
Резюме
Этот контроль разрешений очень элегантный,Пока я добавляю аннотацию к сервисному слою... Затем, когда веб-уровень вызывает этот метод, ему нужно определить, есть ли у пользователя разрешение....
- Способ вызвать уровень службы из внешнего мира — это вызвать метод invoke() через прокси.Его можно улучшить в методе invoke()!
- Внутренняя часть метода invoke() заключается в том, чтобы запросить наличие аннотации к методу для его вызова.Если аннотации нет, его можно вызвать напрямую. Если есть аннотация, получите информацию об аннотации, чтобы определить, есть ли у пользователя разрешение на доступ к этому методу.
- При отражении конкретных методов необходимо не забывать давать соответствующие параметры!
- В исключении времени компиляции, созданном методом invoke(), java автоматически преобразует его в исключение времени выполнения и выдаст его...
- При использовании метода contains() вам необходимо переопределить hashCode() и equals() объекта.