单页网站怎么做竞价/网络营销的十种方法
一、项目开发流程
程序框架图
项目具体分层方案
MVC
1、说明是MVC
MVC全称: Mode模型、View视图、Controller控制器。
MVC最早出现在JavaEE三层中的Web层,它可以有效的指导WEB层的代码如何有效分离,单独工作。
View视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工(Vue/JSP/Thymeleaf/HTML)
Controller控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个"调度者"的角色(Servlet)
Model模型:将与业务逻辑相关的数据封装为具体的JavaBean类,其中不掺杂任何与数据处理相关的代码(JavaBean/Domain/Pojo)
2、MVC是一种思想
MVC的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了解耦合) ,也有很多落地的框架比如SpringMVC
二、实现1 正确加载静态页面
前端人员给的静态页面
三、实现功能02 会员注册前端JS校验
1.验证用户名:必须字母,数字下划线组成,并且长度为6到10位 => JQuery + 正则表达式
2.验证密码:必须由字母,数字下划线组成,并且长度为6到10位
3.邮箱格式验证:常规验证即可
4.验证码:后面实现
<script type="text/javascript" src = "../../script/jquery-3.6.0.min.js"></script><script>$(function () {//页面加载完成后执行function//绑定点击事件$("#sub-btn").click(function (){//获取输入的用户名 => 自己看前端给的页面var $userName = $("#username").val();// alert("usernameVal = " + $userName)//使用正则表达式进行验证var usernamePattern = /^\w{6,10}$/;if(!usernamePattern.test($userName)){//查看前端给的代码是否有错误提示信息// <span class="errorMsg"// style="float: right; font-weight: bold; font-size: 20pt; margin-left: 10px;"></span>//jquery的属性过滤器$("span[class = 'errorMsg']").text("用户格式不对 需要6-10字符");return false;//不提交 需要返回false 不返回false会导致页面跳转}var password = $("#password").val();var passwordPattern = /^\w{6,10}$/;if(!passwordPattern.test(password)){//jquery的基本过滤器$("span.errorMsg").text("密码格式不对 需要6-10字符");return false;}//验证两次密码是否正确var repwd = $("#repwd").val();if(repwd != password){$("span.errorMsg").text("输入的两次密码不同");return false;}var email = $("#email").val();var emailPattern = /^[\w-]+@([a-zA-Z]+\.)+[a-zA-Z]+$/;if(!emailPattern.test(email)){$("span[class = 'errorMsg']").text("电子邮件格式不对");return false;}//到这里就全部过关 => 我们暂时不提交$("span.errorMsg").text("验证通过");return false;})})</script>
四、实现功能03 - 会员注册后端
导入mhl使用的BasicDAO以及JDBCbyDruid 测试是否成功
BasicDAO
package com.yinhai.furns.dao;import com.yinhai.furns.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;/*** @author 韩顺平* @version 1.0* 开发BasicDAO , 是其他DAO的父类*/
public class BasicDAO<T> { //泛型指定具体类型private QueryRunner qr = new QueryRunner();//开发通用的dml方法, 针对任意的表public int update(String sql, Object... parameters) {Connection connection = null;try {//这里从数据库连接池获取connection//老师说明: 每次从连接池中取出Connection , 不能保证是同一个//1.我们目前已经是从当前线程关联的ThreadLocal获取的connection//2.所以我们可以保证是同一个连接(在同一个线程/同一个请求)connection = JDBCUtilsByDruid.getConnection();int update = qr.update(connection, sql, parameters);return update;} catch (SQLException e) {throw new RuntimeException(e); //将编译异常->运行异常 ,抛出}}//返回多个对象(即查询的结果是多行), 针对任意表/**** @param sql sql 语句,可以有 ?* @param clazz 传入一个类的Class对象 比如 Actor.class* @param parameters 传入 ? 的具体的值,可以是多个* @return 根据Actor.class 返回对应的 ArrayList 集合*/public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);} catch (SQLException e) {throw new RuntimeException(e); //将编译异常->运行异常 ,抛出}}//查询单行结果 的通用方法public T querySingle(String sql, Class<T> clazz, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);} catch (SQLException e) {throw new RuntimeException(e); //将编译异常->运行异常 ,抛出}}//查询单行单列的方法,即返回单值的方法public Object queryScalar(String sql, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new ScalarHandler(), parameters);} catch (SQLException e) {throw new RuntimeException(e); //将编译异常->运行异常 ,抛出} }}
JDBC工具类
package com.yinhai.furns.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @author 韩顺平* @version 1.0* 基于druid数据库连接池的工具类*/
public class JDBCUtilsByDruid {private static DataSource ds;//定义属性ThreadLocal, 这里存放一个Connectionprivate static ThreadLocal<Connection> threadLocalConn =new ThreadLocal<>();//在静态代码块完成 ds初始化static {Properties properties = new Properties();try {//因为我们是web项目,他的工作目录在out, 文件的加载,需要使用类加载器//找到我们的工作目录properties.load(JDBCUtilsByDruid.class.getClassLoader().getResourceAsStream("druid.properties"));//properties.load(new FileInputStream("src\\druid.properties"));ds = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}//编写getConnection方法//public static Connection getConnection() throws SQLException {// return ds.getConnection();//}/*** 从ThreadLocal获取connection, 从而保证在同一个线程中,* 获取的是同一个Connection* @return* @throws SQLException*/public static Connection getConnection() {Connection connection = threadLocalConn.get();if (connection == null) {//说明当前的threadLocalConn没有连接//就从数据库连接池中,取出一个连接放入, threadLocalConntry {connection = ds.getConnection();//将连接设置为手动提交, 即不要自动提交connection.setAutoCommit(false);} catch (SQLException throwables) {throwables.printStackTrace();}threadLocalConn.set(connection);}return connection;}/*** 提交事务, java基础 mysql事务+线程+过滤器机制+ThreadLocal*/public static void commit() {Connection connection = threadLocalConn.get();if(connection != null) {//确保该连接是有效try {connection.commit();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {connection.close();//关闭连接} catch (SQLException throwables) {throwables.printStackTrace();}}}//老师说明//1. 当提交后,需要把connection从 threadLocalConn 清除掉//2. 不然,会造成 threadLocalConn 长时间持有该连接, 会影响效率//3. 也因为我们Tomcat底层使用的是线程池技术threadLocalConn.remove();}/*** 老师说明: 所谓回滚,是回滚/撤销和 connection管理的操作删掉,修改,添加*/public static void rollback() {Connection connection = threadLocalConn.get();if(connection != null) {//保证当前的连接是有效try {connection.rollback();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}threadLocalConn.remove();}//关闭连接, 老师再次强调: 在数据库连接池技术中,close 不是真的断掉连接//而是把使用的Connection对象放回连接池public static void close(ResultSet resultSet, Statement statement, Connection connection) {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}
}
实现Member的功能 查询等
一个规范接口
package com.yinhai.furns.dao;import com.yinhai.furns.javabean.Member;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public interface MemberDAO {//小伙伴要自己分析,需要哪些方法//提供一个通过用户名返回对应的Memberpublic Member queryMemberByUsername(String username);//提供一个保存Member对象到数据库/表member表public int saveMember(Member member);/*** 根据用户名和密码返回Member* @param username 用户名* @param password 密码* @return 返回的对象,如果不存在,返回null**/public Member queryMemberByUsernameAndPassword(String username, String password);
}
实现Member的功能 查询 添加等
package com.yinhai.furns.dao.impl;import com.yinhai.furns.dao.BasicDAO;
import com.yinhai.furns.dao.MemberDAO;import com.yinhai.furns.javabean.Member;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public class MemberDAOImpl extends BasicDAO<Member> implements MemberDAO {/*** 通过用户名返回对应的Member** @param username 用户名* @return 对应的Member, 如果没有该Member, 返回 null*/@Overridepublic Member queryMemberByUsername(String username) {//老师提示,sql 先在sqlyog 测试,然后再拿到程序中//这里可以提高我们的开发效率,减少不必要的bugString sql = "SELECT `id`,`username`,`password`,`email` FROM `member`\n" +"WHERE `username` = ?";return querySingle(sql, Member.class, username);}/*** 保存一个会员** @param member 传入Member对象* @return 返回-1 就是失败,返回其它的数字就是受影响的行数*/@Overridepublic int saveMember(Member member) {String sql = "INSERT INTO `member`(`username`,`password`,`email`) " +" VALUES(?,MD5(?), ?)";return update(sql, member.getUsername(),member.getPassword(), member.getEmail());}@Overridepublic Member queryMemberByUsernameAndPassword(String username, String password) {String sql = "SELECT `id`,`username`,`password`,`email` FROM `member` " +" WHERE `username`=? and `password`=md5(?)";return querySingle(sql, Member.class, username, password);}}
测试
package com.yinhai.furns.test;import com.yinhai.furns.dao.MemberDAO;
import com.yinhai.furns.dao.impl.MemberDAOImpl;
import com.yinhai.furns.javabean.Member;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public class MemberTest {public static void main(String[] args) {MemberDAO memberDAO = new MemberDAOImpl();if (memberDAO.queryMemberByUsername("admin") == null){System.out.println("null");}else {System.out.println("exist");}Member member = new Member(null,"jack","jack","135465@qq.com");if(memberDAO.saveMember(member) == 0){System.out.println("添加失败");}else{System.out.println("添加成功");}}
}
服务端 提供注册
package com.yinhai.furns.test;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;
import org.junit.jupiter.api.Test;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public class MemberServiceTest {public static void main(String[] args) {MemberService memberService = new MemberServiceImpl();if (memberService.isExistsUsername("admin")){System.out.println("用户存在");}else{System.out.println("用户不存在");}}@Testpublic void test(){Member member = new Member(null, "tom", "tom", "643013242@qq.com");MemberService memberService = new MemberServiceImpl();boolean b = memberService.registerMember(member);if (b){System.out.println("注册成功");}else{System.out.println("注册失败");}JDBCUtilsByDruid.commit();}
}
一个Servlet提供前后端交流
注册成功 请求转发到注册完成的页面
package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "RegisterServlet",urlPatterns = "/registerServlet")
public class RegisterServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");String email = request.getParameter("user-email");if(!memberService.isExistsUsername(username)){System.out.println(username + "用户可用" + password + email);Member member = new Member(null,username,password,email);if (memberService.registerMember(member)) {request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request,response);JDBCUtilsByDruid.commit();}else {request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request,response);}}else{// System.out.println("用户不存在 返回注册页面");request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request,response);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
五、实现功能04-会员登录
1.输入用户名、密码后提交
2.判断会员是否存在
3.会员存在(数据库),显示登录成功页面
在DAO类编写对数据库操作 也需要在父类以及接口内写该方法
public class MemberDAOImpl extends BasicDAO<Member> implements MemberDAO {@Overridepublic Member queryMemberByUsernameAndPassword(String username, String password) {String sql = "SELECT `id`,`username`,`password`,`email` FROM `member` " +" WHERE `username`=? and `password`=md5(?)";return querySingle(sql, Member.class, username, password);}}
在Service调用该方法
public class MemberServiceImpl implements MemberService {@Overridepublic Member login(Member member) {//返回对象return memberDAO.queryMemberByUsernameAndPassword(member.getUsername(), member.getPassword());}
}
LoginServlet 用于验证前端
package com.yinhai.furns.web;import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "LoginServlet",urlPatterns = "/loginServlet")
public class LoginServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");if (!memberService.isExistsUsername(username)){System.out.println("不存在 请重新登录");request.getRequestDispatcher("/views/member/login.html").forward(request,response);return;}if(memberService.login(new Member(null,username,password,null)) == null){System.out.println("密码错误 重新登录");request.getRequestDispatcher("/views/member/login.html").forward(request,response);return;}System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
六、实现功能05 - 登录错误提示 表单回显
在LoginServlet内添加回显以及消息提示
@WebServlet(name = "LoginServlet",urlPatterns = "/loginServlet")
public class LoginServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");if (!memberService.isExistsUsername(username)){System.out.println("用户名或者密码错误");request.setAttribute("msg","用户名或者密码错误");request.setAttribute("user-name",username);request.getRequestDispatcher("/views/member/login.jsp").forward(request,response);return;}if(memberService.login(new Member(null,username,password,null)) == null){System.out.println("密码错误 重新登录");request.setAttribute("msg","密码错误 重新登录");request.setAttribute("user-name",username);request.getRequestDispatcher("/views/member/login.jsp").forward(request,response);return;}System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}
将前段页面改为jsp 并使用EL表达式
<div id="lg1" class="tab-pane active"><div class="login-form-container"><div class="login-register-form"><span style="float: right; font-weight: bold; font-size: 20pt; margin-left: 10px;">${msg}</span>
添加动态显示用户名
在对应的地方使用el表达式即可
七、实现功能06 - 合并servlet
1.使用if else解决
使用switch - case进行判断
package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "MemberServlet", urlPatterns = "/memberServlet")
public class MemberServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");String email = request.getParameter("user-email");String action = request.getParameter("action");System.out.println(action);switch (action) {case "login":if (!memberService.isExistsUsername(username)) {System.out.println("用户不存在");request.setAttribute("msg", "用户不存在");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);return;}if (memberService.login(new Member(null, username, password, null)) == null) {System.out.println("密码错误 重新登录");request.setAttribute("msg", "密码错误 重新登录");request.setAttribute("username", username);request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);return;}System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request, response);break;case "register":if (!memberService.isExistsUsername(username)) {System.out.println(username + "用户可用" + password + email);Member member = new Member(null, username, password, email);if (memberService.registerMember(member)) {request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request, response);JDBCUtilsByDruid.commit();} else {request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request, response);}} else {System.out.println("用户存在 无法注册");request.setAttribute("msg", "用户存在 无法注册");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}break;}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}
2.反射 + 模版设计 + 动态绑定
package com.yinhai.furns.web;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public abstract class BasicServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//解决接收到的数据中文乱码问题request.setCharacterEncoding("utf-8");//System.out.println("BasicServlet doPost()");//获取到action的值//老韩提示:如果我们使用了模板模式+反射+动态绑定,要满足action的value 和 方法名一致!!!String action = request.getParameter("action");//System.out.println("action=" + action);//使用反射,获取当前对象的方法//老韩解读//1.this 就是请求的Servlet//2.declaredMethod 方法对象就是当前请求的servlet对应的"action名字" 的方法, 该方法对象(declaredMethod)// 是变化的,根据用户请求//3.使用模板模式+反射+动态机制===> 简化多个 if--else if---..try {Method declaredMethod =this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);System.out.println("declaredMethod=" + declaredMethod);//使用方法对象,进行反射调用declaredMethod.invoke(this, request, response);} catch (Exception e) {//java基础->异常机制//将发生的异常,继续throw//老师心得体会: 异常机制是可以参与业务逻辑throw new RuntimeException(e);}}}
然后子类servlet继承该Servlet 随后只写login以及register方法即可
package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "MemberServlet", urlPatterns = "/memberServlet")
public class MemberServlet extends BasicServlet {private MemberService memberService = new MemberServiceImpl();/*** 处理会员的注册** @param request* @param response* @throws ServletException* @throws IOException*/protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("======MemberServlet register()========");//接收用户注册信息-> 一定要去看前端页面字段..//用户名String username = request.getParameter("user-name");String password = request.getParameter("user-password");String email = request.getParameter("user-email");//获取用户提交验证码String code = request.getParameter("code");//从session中获取到验证码// String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);//立即删除session验证码->防止该验证码被重复使用// request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);//如果token为空,并且和用户提交的验证码一致,就继续// if (token != null && token.equalsIgnoreCase(code)) {//判断这个用户名是不是可用if (!memberService.isExistsUsername(username)) {//注册//System.out.println("用户名 " + username + " 不存在, 可以注册");//构建一个Member对象Member member = new Member(null, username, password, email);if (memberService.registerMember(member)) {//请求转发request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request, response);} else {//请求转发request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request, response);}} else {//返回注册页面//后面可以加入提示信息...request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}// } else { //验证码不正确// request.setAttribute("msg", "验证码不正确~");// //如果前端需要回显某些数据// request.setAttribute("username", username);// request.setAttribute("email", email);// //带回一个信息 要显示到注册选项页// request.setAttribute("active", "register");// request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);// }}/*** 处理会员登录** @param request* @param response* @throws ServletException* @throws IOException*/protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("======MemberServlet login()========");//System.out.println("LoginServlet 被调用..");//老韩说明:如果在登录页面, 用户没有输入内容,就直接提交,后台接收到的是""String username = request.getParameter("user-name");String password = request.getParameter("user-password");Member member = memberService.login(new Member(null, username, password, null));if (member == null) { //用户没有在DB//System.out.println(member + " 登录失败...");//把登录错误信息,放入到request域 => 如果忘了,可以看servlet / jsprequest.setAttribute("msg", "用户名或者密码错误");request.setAttribute("username", username);//页面转发request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);} else { //用户在DB//System.out.println(member + " 登录成功~...");//将得到member对象放入到sessionrequest.getSession().setAttribute("member", member);//老师做了一个简单处理if ("admin".equals(member.getUsername())) {request.getRequestDispatcher("/views/manage/manage_menu.jsp").forward(request, response);} else {request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request, response);}}}
}
八、功能07 - 后台管理家具
创建furn表
package com.yinhai.furns.web;import com.yinhai.furns.dao.BasicDAO;
import com.yinhai.furns.javabean.Furn;
import com.yinhai.furns.service.FurnService;
import com.yinhai.furns.service.impl.FurnServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "FurnServlet",urlPatterns = "/manager/furnServlet")
public class FurnServlet extends BasicServlet {private FurnService furnService = new FurnServiceImpl();/*** 这里我们使用前面的模板设计模式+反射+动态绑定来的调用到list方法** @param req* @param resp* @throws ServletException* @throws IOException*/protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("FurnServlet list方法被调...");List<Furn> furns = furnService.queryFurns();//把furns集合放入到request域req.setAttribute("furns", furns);for (Furn furn : furns) {System.out.println(furn);}//请求转发req.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(req, resp);}
}
通过jstl标签取出并输出
<c:forEach items="${requestScope.furns}" var="furn"><tr><td class="product-thumbnail"><a href="#"><img class="img-responsive ml-3" src="${furn.imgPath}"alt=""/></a></td><td class="product-name"><a href="#">${furn.name}</a></td><td class="product-name"><a href="#">${furn.maker}</a></td><td class="product-price-cart"><span class="amount">${furn.price}</span></td><td class="product-quantity">${furn.sales}</td><td class="product-quantity">${furn.stock}</tr>
编写admin的DAO
public class AdminDAOImpl extends BasicDAO implements AdminDAO {@Overridepublic int saveAdmin(Admin admin) {String sql = "INSERT INTO `admin`(`username`,`password`) " +"VALUES(?,MD5(?))";return update(sql, admin.getUsername(),admin.getPassword());}@Overridepublic Admin queryAdminByUsernameAndPassword(String username, String password) {String sql = "SELECT `id`,`username`,`password` FROM `admin` " +" WHERE `username`=? and `password`=md5(?)";return (Admin) querySingle(sql, Admin.class,username,password);}}
编写对应的和前端交互的servlet
@WebServlet(name = "AdminServlet",urlPatterns = "/adminServlet")
public class AdminServlet extends BasicServlet {private AdminService adminService = new AdminServiceImpl();protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");Admin admin = new Admin(null, username, password);if(adminService.login(admin) == null){System.out.println("管理员不存在");request.getRequestDispatcher("/views/manage/manage_login.jsp").forward(request,response);return;}request.getRequestDispatcher("/views/manage/manage_menu.jsp").forward(request,response);}
}
九、功能08 - 后台管理 添加家具
@WebServlet(name = "FurnServlet",urlPatterns = "/manage/furnServlet")
public class FurnServlet extends BasicServlet {private FurnService furnService = new FurnServiceImpl();protected void add(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {//获取家居信息String uname = request.getParameter("name");String maker = request.getParameter("maker");String price = request.getParameter("price");String sales = request.getParameter("sales");String stock = request.getParameter("stock");String defaultPath = "assets/images/product-image/default.jpg";Furn furn = new Furn(null, uname, maker, new BigDecimal(price), new Integer(sales), new Integer(stock), defaultPath);System.out.println(furn);furnService.addFurn(furn);request.getRequestDispatcher("/manage/furnServlet?action=list").forward(request, response);}
public class FurnServiceImpl implements FurnService {private FurnDAO furnDAO = new FurnDAOImpl();//定义属性FurnDAO对象/*** 返回家居信息* @return*/@Overridepublic List<Furn> queryFurns() {return furnDAO.queryFurns();}@Overridepublic int addFurn(Furn furn) {return furnDAO.addFurn(furn);}
}
public class FurnDAOImpl extends BasicDAO implements FurnDAO {@Overridepublic int addFurn(Furn furn) {String sql = "INSERT INTO furn(`id`,`name`,maker,price,sales,stock,img_path)\n" +"\tVALUES(NULL,?,?,?,?,?,?)";return update(sql,furn.getName(),furn.getMaker(),furn.getPrice(),furn.getSales(),furn.getStock(),furn.getImgPath());}
}
细节 解决中文乱码问题 在BasicDAO上设置request response的文本格式
细节 解决表重复提交问题 使用重定向即可
细节 后端验证添加家具的合法性
//我们可以对获取的到数据, 进行一个校验//1. 使用java的正则表达式来验证 sales是一个正整数//2. 如果没有通过校验,则直接返回furn_add.jsp -> request.setAttribute("mes","xx")//3. 这里可以直接进行转换//try {// int i = Integer.parseInt(sales);//}catch (NumberFormatException e) {// //System.out.println("转换异常...");// req.setAttribute("mes", "销量数据格式不对...");// //返回到furn_add.jsp// req.getRequestDispatcher("/views/manage/furn_add.jsp")// .forward(req, resp);// return;//}//String stock = req.getParameter("stock");//图片的路径 imgPath 使用默认即可//Furn furn = null;//try {// furn = new Furn(null, name, maker, new BigDecimal(price),// new Integer(sales), new Integer(stock), "assets/images/product-image/default.jpg");//} catch (NumberFormatException e) {// req.setAttribute("mes", "添加数据格式不对...");// //返回到furn_add.jsp// req.getRequestDispatcher("/views/manage/furn_add.jsp")// .forward(req, resp);// return;//}//后面我们会学习SpringMVC -> 专门的用于数据校验的规则/框架 JSR303... Hibernate Validator
细节 使用工具类DataUtils 完成自动封装JavaBean
1. BeanUtils工具类,它可以一次性的把所有请求的参数注入到JavaBean中。
2. BeanUtils工具类,经常用于把Map中的值注入到JavaBean中,或者是对象属性值的拷贝操作
3. BeanUtils不是Jdk的类,需要导入需要的jar包: commons-beanutils-1.8.0.jar
commons-logging-1.1.1.jar
//使用BeanUtils完成javabean对象的自动封装.//// Furn furn = new Furn();// try {// //讲 req.getParameterMap() 数据封装到furn 对象// //使用反射将数据封装, 有一个前提就是表单提交的数据字段名// //<input name="maker" style="width: 90%" type="text" value=""/>// //需要和封装的Javabean的属性名一致// BeanUtils.populate(furn, request.getParameterMap());// } catch (Exception e) {// e.printStackTrace();// }// 自动将提交的数据,封装到Furn对象Furn furn =DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(furn);furnService.addFurn(furn);
public class DataUtils {//将方法,封装到静态方法,方便使用public static <T> T copyParamToBean(Map value, T bean) {try {BeanUtils.populate(bean, value);} catch (Exception e) {e.printStackTrace();}return bean;}}
在构造javabean的时候在Furn内赋予一个默认值 给这个类自动装入
十、功能09 后台管理 删除家具
前端对x图标进行绑定事件 弹出是否删除该名字的家具
Servlet增加功能
@WebServlet(name = "FurnServlet",urlPatterns = "/manage/furnServlet")
public class FurnServlet extends BasicServlet {
protected void del(HttpServletRequest request,HttpServletResponse response){int id = DataUtils.parseInt(request.getParameter("id"), 0);System.out.println(furnService.deleteFurnById(id));}
}
Service增加功能
public int deleteFurnById(int id) {return furnDAO.deleteFurnById(id);}
DAO类增加功能
public class FurnDAOImpl extends BasicDAO implements FurnDAO {public int deleteFurnById(int id) {String sql = "DELETE FROM furn WHERE id = ?";return update(sql,id);}
}
十一、功能实现 10 后台管理 修改家具
查询对应的id的家具
protected void showFurn(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {int id = DataUtils.parseInt(request.getParameter("id"),0);Furn furn = furnService.queryFurnById(id);System.out.println(furn);request.setAttribute("furn",furn);//请求转发request.getRequestDispatcher("/views/manage/furn_update.jsp").forward(request,response);}
以上完成回显操作 下一步做修改的操作
@Overridepublic int updateFurn(Furn furn) {String sql = "UPDATE furn SET `name` = ? , `maker` = ? , `price` = ? , sales = ?" +" , stock = ? , `img_path` = ?" +" WHERE id = ?";return update(sql,furn.getName(),furn.getMaker(),furn.getPrice(),furn.getSales(),furn.getStock(),furn.getImgPath(),furn.getId());}
前端页面也调整 使用jstl标签拿出
十二、功能实现11 分页显示
将分页作为一个Bean模型
package com.yinhai.furns.javabean;import java.util.List;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com* 一个分页的数据模型 包含了分页的各种信息*/
//用一个泛型 分页模型对应的数据类型是不确定的
public class Page<T> {//每页显示多少条记录可以在其他地方也用到 建议置为常量//ctrl + shift + u 切换大小写public static final Integer PAGE_SIZE = 3;//表示显示当前页private Integer pageNo;//每页显示多少记录private Integer pageSize = PAGE_SIZE;//表示共有多少页private Integer pageTotalCount;//表示的是共有多少条记录 通过totalRow和pageSize计算得到pageTotalCountprivate Integer totalRow;//表示当前页要显示的数据private List<T> items;//分页导航的字符串private String url;public Integer getPageNo() {return pageNo;}public void setPageNo(Integer pageNo) {this.pageNo = pageNo;}public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPageTotalCount() {return pageTotalCount;}public void setPageTotalCount(Integer pageTotalCount) {this.pageTotalCount = pageTotalCount;}public Integer getTotalRow() {return totalRow;}public void setTotalRow(Integer totalRow) {this.totalRow = totalRow;}public List<T> getItems() {return items;}public void setItems(List<T> items) {this.items = items;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}
}
分析 page的那些属性可以从数据库获取 就把对应的属性交给DAO赋值
@Overridepublic int getTotalRow() {String sql = "SELECT COUNT(*) FROM furn";// return (int) queryScalar(sql); => 会报转换异常return ((Number) queryScalar(sql)).intValue();}@Overridepublic List<Furn> getPageItems(int begin, int pageSize) {String sql = "SELECT `id`,`name`,maker,price,sales,stock,img_path imgPath\n" +" FROM furn ";return null;}
其他的交给Service处理
public class FurnServiceImpl implements FurnService {@Overridepublic Page<Furn> page(int pageNo, int pageSize) {Page<Furn> page = new Page<>();page.setPageNo(pageNo);page.setPageSize(pageSize);int totalRow = furnDAO.getTotalRow();page.setTotalRow(totalRow);//pageTotalCount最大页数 需要通过算法计算得到int pageTotalCount = totalRow / pageSize;if(totalRow % pageSize > 0){pageTotalCount += 1;}page.setPageTotalCount(pageTotalCount);//private List<T> items//计算begin//private List<T> items//老师开始计算begin-> 小小算法//验证: pageNo = 1 pageSize = 3 => begin =0//验证: pageNo = 3 pageSize = 2 => begin =4//OK => 但是注意这里隐藏一个坑, 现在你看不到, 后面会暴露int begin = (pageNo - 1) * pageSize;List<Furn> pageItems = furnDAO.getPageItems(begin, pageSize);page.setItems(pageItems);//还差一个url => 分页导航,先放一放return page;}
}
Servlet调用
protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);//调用service方法, 获取Page对象Page<Furn> page = furnService.page(pageNo, pageSize);//将page放入到request域req.setAttribute("page", page);//请求转发到furn_manage.jspreq.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(req, resp);}
十三、功能实现 12 - 分页导航
<!-- Pagination Area Start 分页导航条 --><div class="pro-pagination-style text-center mb-md-30px mb-lm-30px mt-6" data-aos="fade-up"><ul><%--如果当前页 > 1 , 就显示上一页--%><c:if test="${requestScope.page.pageNo > 1}"><li><a href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageNo - 1}">上一页</a></li></c:if><%--<li><a class="active" href="#">3</a></li>--%><%--<li><a href="#">4</a></li>--%><%--<li><a href="#">5</a></li>--%><%-- 显示所有的分页数, 先容易,再困难老师思路: 先确定开始页数 begin 第1页再确定结束页数 end 第pageTotalCount页学生困惑:如果页数很多,怎么办? => 算法最多显示5页[这个规则可以由程序员决定.]希望,小伙伴自己先想一想...=> 后面老师分析1. 如果总页数<=5, 就全部显示2. 如果总页数>5, 按照如下规则显示(这个规则是程序员/业务来确定):2.1 如果当前页是前3页, 就显示1-52.2 如果当前页是后3页, 就显示最后5页2.3 如果当前页是中间页, 就显示 当前页前2页, 当前页 , 当前页后两页这里的关键就是要根据不同的情况来初始化begin, end--%><c:choose><%--如果总页数<=5, 就全部显示--%><c:when test="${requestScope.page.pageTotalCount <=5 }"><c:set var="begin" value="1"/><c:set var="end" value="${requestScope.page.pageTotalCount}"/></c:when><%--如果总页数>5--%><c:when test="${requestScope.page.pageTotalCount > 5}"><c:choose><%--如果当前页是前3页, 就显示1-5--%><c:when test="${requestScope.page.pageNo <= 3}"><c:set var="begin" value="1"/><c:set var="end" value="5"/></c:when><%--如果当前页是后3页, 就显示最后5页--%><c:when test="${requestScope.page.pageNo > requestScope.page.pageTotalCount - 3}"><c:set var="begin" value="${requestScope.page.pageTotalCount - 4}"/><c:set var="end" value="${requestScope.page.pageTotalCount}"/></c:when><%--如果当前页是中间页, 就显示 当前页前2页, 当前页 , 当前页后两页--%><c:otherwise><c:set var="begin" value="${requestScope.page.pageNo - 2}"/><c:set var="end" value="${requestScope.page.pageNo + 2}"/></c:otherwise></c:choose></c:when></c:choose><c:forEach begin="${begin}" end="${end}" var="i"><%--如果i是当前页, 就使用class="active" 修饰--%><c:if test="${i == requestScope.page.pageNo}"><li><a class="active" href="manage/furnServlet?action=page&pageNo=${i}">${i}</a></li></c:if><c:if test="${i != requestScope.page.pageNo}"><li><a href="manage/furnServlet?action=page&pageNo=${i}">${i}</a></li></c:if></c:forEach><%--如果当前页 < 总页数 , 就显示下一页--%><c:if test="${requestScope.page.pageNo < requestScope.page.pageTotalCount}"><li><a href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageNo + 1}">下一页</a></li></c:if><li><a href="#">共 ${requestScope.page.pageTotalCount} 页</a></li></ul></div><!-- Pagination Area End -->
进行修改 删除 添加 家具之后 能够回显到原来操作所在的页面
修改一步步转发 到最后重定向到page页面
这几个都这么做都在修改请求转发地址上完成
@WebServlet(name = "FurnServlet", urlPatterns = "/manage/furnServlet")
public class FurnServlet extends BasicServlet {protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取家居信息// String uname = request.getParameter("name");// String maker = request.getParameter("maker");// String price = request.getParameter("price");// String sales = request.getParameter("sales");////// String stock = request.getParameter("stock");// String defaultPath = "assets/images/product-image/default.jpg";// Furn furn = new Furn(null, uname, maker, new BigDecimal(price), new Integer(sales), new Integer(stock), defaultPath);//我们可以对获取的到数据, 进行一个校验//1. 使用java的正则表达式来验证 sales是一个正整数//2. 如果没有通过校验,则直接返回furn_add.jsp -> request.setAttribute("mes","xx")//3. 这里可以直接进行转换//try {// int i = Integer.parseInt(sales);//}catch (NumberFormatException e) {// //System.out.println("转换异常...");// req.setAttribute("mes", "销量数据格式不对...");// //返回到furn_add.jsp// req.getRequestDispatcher("/views/manage/furn_add.jsp")// .forward(req, resp);// return;//}//String stock = req.getParameter("stock");//图片的路径 imgPath 使用默认即可//Furn furn = null;//try {// furn = new Furn(null, name, maker, new BigDecimal(price),// new Integer(sales), new Integer(stock), "assets/images/product-image/default.jpg");//} catch (NumberFormatException e) {// req.setAttribute("mes", "添加数据格式不对...");// //返回到furn_add.jsp// req.getRequestDispatcher("/views/manage/furn_add.jsp")// .forward(req, resp);// return;//}//后面我们会学习SpringMVC -> 专门的用于数据校验的规则/框架 JSR303... Hibernate Validator//这里我们使用第二种方式, 完成将前端提交的数据, 封装成Furn的Javabean对象//使用BeanUtils完成javabean对象的自动封装.//// Furn furn = new Furn();// try {// //讲 req.getParameterMap() 数据封装到furn 对象// //使用反射将数据封装, 有一个前提就是表单提交的数据字段名// //<input name="maker" style="width: 90%" type="text" value=""/>// //需要和封装的Javabean的属性名一致// BeanUtils.populate(furn, request.getParameterMap());// } catch (Exception e) {// e.printStackTrace();// }// 自动将提交的数据,封装到Furn对象Furn furn =DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(furn);furnService.addFurn(furn);//老师说明: 因为这里使用请求转发, 当用户刷新页面时, 会重新发出一次添加请求// request.getRequestDispatcher("/manage/furnServlet?action=list")// .forward(request, response);//就会造成数据重复提交: 解决方案使用 重定向即可.//因为重定向实际是让浏览器重新发请求, 所以我们回送的url , 是一个完整url// response.sendRedirect(request.getContextPath() + "/manage/furnServlet?action=list");//以分页的方式显示response.sendRedirect(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));}protected void del(HttpServletRequest request, HttpServletResponse response) throws IOException {int id = DataUtils.parseInt(request.getParameter("id"), 0);System.out.println(furnService.deleteFurnById(id));response.sendRedirect(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));}protected void showFurn(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int id = DataUtils.parseInt(request.getParameter("id"), 0);Furn furn = furnService.queryFurnById(id);System.out.println(furn);request.setAttribute("furn", furn);//再把获取到的showPage再传回去// request.setAttribute("pageNo",request.getParameter("pageNo"));// 如果是在同一个作用域request内的请求是不需要再转发的 在下个页面可以用param.pageNo获取//请求转发request.getRequestDispatcher("/views/manage/furn_update.jsp").forward(request, response);}protected void update(HttpServletRequest request, HttpServletResponse response) throws IOException {Furn furn = DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println("update" + furn);System.out.println(furnService.updateFurn(furn));//请求重定向// response.sendRedirect(request.getContextPath() + "/manage/furnServlet?action=list");//这里考虑分页转发System.out.println(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));response.sendRedirect(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));}protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);//调用service方法, 获取Page对象Page<Furn> page = furnService.page(pageNo, pageSize);if(page.getItems().size() == 0){page = furnService.page(page.getPageTotalCount(), pageSize);}//将page放入到request域req.setAttribute("page", page);//请求转发到furn_manage.jspreq.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(req, resp);}}
十四、功能实现13 - 首页分页
相关文章:

【JavaWeb学习笔记】19 - 网购家居项目开发(上)
一、项目开发流程 程序框架图 项目具体分层方案 MVC 1、说明是MVC MVC全称: Mode模型、View视图、Controller控制器。 MVC最早出现在JavaEE三层中的Web层,它可以有效的指导WEB层的代码如何有效分离,单独工作。 View视图:只负责数据和界面的显示&…...

强化学习的数学原理学习笔记 - RL基础知识
文章目录 Roadmap🟡基础概念贝尔曼方程(Bellman Equation)基本形式矩阵-向量形式迭代求解状态值 vs. 动作值 🟡贝尔曼最优方程(Bellman Optimality Equation,BOE)基本形式迭代求解 本系列文章介…...

winSCP是什么?它有什么功能和特性?它值不值得我们去学习?我们该如何去学习呢?
WinSCP是一款免费的开源SFTP、SCP、FTP和WebDAV客户端,用于Windows操作系统。它提供了一个图形化界面,使用户可以方便地在本地计算机和远程计算机之间传输文件。 WinSCP支持SSH加密通信和多种认证方法,包括密码、公钥和键盘交互。它还支持自…...

SpringBoot的数据层解决方案
🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎 📚系列专栏:Java全栈,…...

极客时间-《如何成为学习高手》文章笔记 + 个人思考
极客时间-《如何成为学习高手》文章笔记 个人思考 底层思维高效学习05|教你全面提升专注力,学习时不再走神06|教你高效复习:巧用学习神器取得好成绩07|我考北大中文系时,15 天背下 10 门专业课的连点成线法…...

【前端】下载文件方法
1.window.open 我最初使用的方法就是这个,只要提供了文件的服务器地址,使用window.open也就是在新窗口打开,这时浏览器会自动执行下载。 2.a标签 其实window.open和a标签是一样的,只是a标签是要用户点击触发,而wind…...

虚幻UE 材质-纹理 1
本篇笔记主要讲两个纹理内的内容:渲染目标和媒体纹理 媒体纹理可以参考之前的笔记:虚幻UE 媒体播放器-视频转成材质-播放视频 所以本篇主要讲两个组件:场景捕获2D、场景捕获立方体 两个纹理:渲染目标、立方体渲染目标 三个功能&am…...

回归预测 | Matlab实现RIME-HKELM霜冰算法优化混合核极限学习机多变量回归预测
回归预测 | Matlab实现RIME-HKELM霜冰算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现RIME-HKELM霜冰算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现RIME-HKELM霜冰算法优化混合核极限学习机多变…...

【AWS系列】巧用 G5g 畅游Android流媒体游戏
序言 Amazon EC2 G5g 实例由 AWS Graviton2 处理器提供支持,并配备 NVIDIA T4G Tensor Core GPU,可为 Android 游戏流媒体等图形工作负载提供 Amazon EC2 中最佳的性价比。它们是第一个具有 GPU 加速功能的基于 Arm 的实例。 借助 G5g 实例,游…...

GNSS数据及产品下载地址(FTP/HTTP)
GNSS数据/产品下载地址 天线改正文件(atx)下载Index of /pub/station/general 通用广播星历(brdc/brdm):ftp://cddis.gsfc.nasa.gov/pub/gps/data/daily/YYYY/brdcftp://cddis.gsfc.nasa.gov/pub/gps/data/campaign/mgex/daily/rinex3/YYYY/brdmftp://epncb.oma.b…...

【STM32】STM32学习笔记-DMA数据转运+AD多通道(24)
00. 目录 文章目录 00. 目录01. DMA简介02. DMA相关API2.1 DMA_Init2.2 DMA_InitTypeDef2.3 DMA_Cmd2.4 DMA_SetCurrDataCounter2.5 DMA_GetFlagStatus2.6 DMA_ClearFlag 03. DMA数据单通道接线图04. DMA数据单通道示例05. DMA数据多通道接线图06. DMA数据多通道示例一07. DMA数…...

即时设计:设计流程图,让您的设计稿更具条理和逻辑
流程图小助手 更多内容 在设计工作中,流程图是一种重要的工具,它可以帮助设计师清晰地展示设计思路和流程,提升设计的条理性和逻辑性。今天,我们要向您推荐一款强大的设计工具,它可以帮助您轻松为设计稿设计流程图&a…...

单个独立按键控制直流电机开关
/*----------------------------------------------- 内容:对应的电机接口需用杜邦线连接到uln2003电机控制端 使用5V-12V 小功率电机皆可 ------------------------------------------------*/ #include<reg52.h> //包含头文件,一般情况…...

前端插件库-VUE3 使用 JSEncrypt 插件
JSEncrypt 是一个用于在客户端进行加密的 JavaScript 库。它基于 RSA 加密算法,可以用于在浏览器中对数据进行加密和解密操作。 以下是使用 JSEncrypt 进行加密和解密的基本示例: 第一步:安装 JSEncrypt 首先,你需要引入 JSEn…...

Neo4j备份
这里主要讲Neo4j在windows环境下如何备份,Linux环境同理 Neo4j恢复看这里:Neo4j恢复-CSDN博客 Step1:停服 关闭neo4j.bat console会话窗口即可 Step2: 备份 找到数据目录,并备份、压缩 copy即可 data - 20240108.7z Step3: 启动服务 进入命令行&am…...

【LangChain学习之旅】—(5) 提示工程(上):用少样本FewShotTemplate和ExampleSelector创建应景文案
【LangChain学习之旅】—(5) 提示工程(上):用少样本FewShotTemplate和ExampleSelector创建应景文案 提示的结构LangChain 提示模板的类型使用 PromptTemplate使用 ChatPromptTemplateFewShot 的思想起源使用 FewShotPr…...

Python从入门到精通秘籍一
Python速成,知识点超详细,跟着这个系列边输入边学习体会吧! 一、字面量 下面是一些使用代码示例来说明Python的字面量的具体用法: 1.数字字面量: integer_literal = 42 # 整数字面量 float_literal = 3.14 # 浮点数字面量 complex_literal = 2 + 3j # 复数字面量# …...

【IC设计】移位寄存器
目录 理论讲解背景介绍什么是移位寄存器按工作模式分类verilog语法注意事项 设计实例循环移位寄存器算术双向移位寄存器5位线性反馈移位寄存器伪随机码发生器3位线性反馈移位寄存器32位线性反馈移位寄存器串行移位寄存器(打4拍)双向移位寄存器࿱…...

【Flutter 开发实战】Dart 基础篇:最基本的语法内容
在深入了解 Dart 这门编程语言之前,我们需要了解一些关于 Dart 的最基本的知识,像是常量、变量、函数等等,这样才能够让我们的开发效率更上一层楼。在本节,我们将探讨一些基础语法,包括入口方法 main、变量、常量以及命…...

中国光伏展
中国光伏展是中国最大的光伏产业展览会,每年在国内举办一次。该展览会汇集了国内外光伏行业的领先企业和专业人士,展示最新的光伏技术、产品和解决方案。 中国光伏展旨在促进光伏行业的发展和创新,提升光伏产业的国际竞争力。展览会涵盖了光伏…...

Nacos的统一配置管理
Nacos的统一配置管理 一 项目添加nacos和bootstrap依赖二 nacos客户端配置2.1 创建命名空间2.2 创建配置 三、配置bootstrap.yml四 不同环境配置切换步骤一:nacos中添加开发、测试配置步骤二:指定bootstrap.yml中spring.profiles.active参数值 扩展链接 …...

SpringBoot项目docker镜像生成
1. 本文思路 拉取基础镜像基于镜像创建容器在容器中,安装所需依赖部署脚本提交容器,生成新的镜像编写Dockerfile,添加启动命令,生成最终镜像导出镜像 2. 操作步骤 2.1 基础环境 # 拉取镜像 docker pull centos:7.6.1810 # 运行…...

JDBC初体验(二)——增、删、改、查
本课目标 理解SQL注入的概念 掌握 PreparedStatement 接口的使用 熟练使用JDBC完成数据库的增、删、改、查操作 SQL注入 注入原理:利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行能力,它可以通过在…...

Eva.js是什么(互动小游戏开发)
前言 Eva.js 是一个专注于开发互动游戏项目的前端游戏引擎。 易用:Eva.js 提供开箱即用的游戏组件供开发人员立即使用。是的,它简单而优雅! 高性能:Eva.js 由高效的运行时和渲染管道 (Pixi.JS) 提供支持,这使得释放设…...

监听 beforeunload 事件,阻止页面刷新导致的信息丢失
尤其是一个有编辑器的页面,可以监听 windwo.beforeunload 事件,在用户试图关闭当前标签页的时候提醒用户,内容可能会丢失。 Window:beforeunload 事件 - Web API 接口参考 | MDN...

Java 常见缓存详解以及解决方案
一. 演示Mybatis 一级缓存 首先我们准备一个接口 两个实现的方法, 当我们调用这个queryAll()方法时我们需要调用selectAll()方法来查询数据 调用此接口实现效果 这个时候我们就可以发现了问题,我们调用方法…...

Golang 交叉编译之一文详解
博客原文 文章目录 Golang 中的交叉编译不同操作系统间的编译Linux 下编译windowsmacos windows 下编译Linuxmacos macos 下编译Linuxwindows 不同架构下的编译amd64x86 参考 Golang 中的交叉编译 在 Golang 中,交叉编译指的是在同一台机器上生成针对不同操作系统或…...

最新ThinkPHP版本实现证书查询系统,实现批量数据导入,自动生成电子证书
前提:朋友弄了一个培训机构,培训考试合格后,给发证书,需要一个证书查询系统。委托我给弄一个,花了几个晚上给写的证书查询系统。 实现功能: 前端按照姓名手机号码进行证书查询证书信息展示证书展示&#x…...

windows安装运行Apache James(基于spring的版本)
下载地址 下载列表 https://james.apache.org/download.cgi 直接下载基于spring版本 https://www.apache.org/dyn/closer.lua/james/server/3.8.0/james-server-app-3.8.0-app.zip 设置签名 解压,并切换到james-server-spring-app-3.8.0目录下,在powe…...

Elasticsearch 基本概念:快速入门指南【记录】
简单记录,后续整理补充 介绍: Elasticsearch是一个分布式、可扩展、实时的搜索和分析引擎,建立在开源搜索库Lucene之上。它提供了强大的全文搜索功能和复杂的分析能力,适用于各种场景,包括应用日志分析、电子商务搜索…...