day50_BOS项目_02

  • day50_BOS项目_02今天内容安排:
    • 1、根据提供的pdm文件生成sql脚本文件
    • 2、持久层和表现层的设计(BaseDao、BaseAction)
    • 3、基于BaseDao和BaseAction实现用户登录功能
    • 4、jQuery EasyUI 消息提示控件
    • 5、jQuery EasyUI 菜单按钮 menubutton
    • 6、自定义struts2拦截器,实现用户未登录自动跳转到登录页面
    • 7、基于ajax实现修改密码功能

1、根据提供的pdm文件生成sql脚本

  • 根据提供的pdm文件生成sql脚本文件(即建表语句文件)
  • 我们通过Mysql命令行的方式,使用sql脚本文件生成对应的数据库表,操作如下图所示:
  • 生成的数据库表结构如下图所示:

2、持久层和表现层的设计(BaseDao、BaseAction)

2.1、持久层的设计(基于泛型+反射)

持久层的设计(基于泛型+反射)图解,如下图所示:

通用接口代码: IBaseDao.java

package com.itheima.bos.dao.base;

import java.io.Serializable;
import java.util.List;

/*
 * 抽取持久层通用方法:增删改查+分页+...
 */
public interface IBaseDao<T> {
    // 增删改查
    public void save(T entity);
    public void delete(T entity);
    public void update(T entity);
    // 因为id不管是int类型还是string类型,他们都实现了Serializable序列化接口,使用Serializable类型,或者更狠一点:就用Object类型
    public T findById(Serializable id);
    public List<T> findAll();

    // 分页

    // ...
}

通用接口实现代码: BaseDaoImpl.java

package com.itheima.bos.dao.base.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.itheima.bos.dao.base.IBaseDao;

/*
 * 持久层通用实现 
 */
public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> {

    // 声明实体类型
    private Class<T> entityClass; // Class也是一个class,Class代表的是类型

    // 在构造方法中动态获取操作要用的实体类型
    public BaseDaoImpl() { // this是当前实例化对象,通过getClass(),得到当前类的类型,getGenericSuperclass() 获得带有泛型的父类,getSuperclass() 获得该类的父类
        // Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
        Type type = this.getClass().getGenericSuperclass();
        // ParameterizedType 参数化类型,即泛型
        ParameterizedType pt = (ParameterizedType)type;
        // getActualTypeArguments() 获取参数化类型的数组,泛型可能有多个
        Type[] actualTypeArguments = pt.getActualTypeArguments();
        entityClass = (Class<T>) actualTypeArguments[0];
    }

    // 使用注解方式进行依赖注入setter方法
    // @Autowired 注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。注意:@Autowired 默认按类型匹配(byType)进行注入的。
    // 如果需要按名称(byName)匹配的话,可以使用@Qualifier注解与@Autowired结合,请注意必须在xml配置中启动注解驱动。

    // @Resource 倘若既不指定name也不指定type属性,Spring容器将通过反射技术默认按byName模式进行注入的。
    // 该注解需导入import javax.annotation.Resource;
    // 此时Spring只会尝试将属性名与bean名称进行匹配,如果找到则注入依赖bean。
    // 由于public final void setSessionFactory(SessionFactory sessionFactory) {...}是final的,所以需要我们自定义方法,再去使用super去调用它。
    @Resource
    public void setMySessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    public void save(T entity) {
        this.getHibernateTemplate().save(entity);
    }

    public void delete(T entity) {
        this.getHibernateTemplate().delete(entity);
    }

    public void update(T entity) {
        this.getHibernateTemplate().update(entity);
    }

    public T findById(Serializable id) {
        this.getHibernateTemplate().get(entityClass, id);
        return null;
    }

    public List<T> findAll() {
        String hql = "from " + entityClass.getSimpleName(); // 注意from后面有空格
        return this.getHibernateTemplate().find(hql);
    }

}

我们再补上IUserDao和UserDaoImpl的示例代码: IUserDao.java

package com.itheima.bos.dao;

import com.itheima.bos.dao.base.IBaseDao;
import com.itheima.bos.domain.User;

public interface IUserDao extends IBaseDao<User> {

}

UserDaoImpl.java

package com.itheima.bos.dao.impl;

// import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

import com.itheima.bos.dao.IUserDao;
import com.itheima.bos.dao.base.impl.BaseDaoImpl;
import com.itheima.bos.domain.User;

@Repository // IUserDaoImpl对象默认是单例的,单例对象创建的时机:在applicationContext.xml配置文件加载,执行组件扫描,创建工厂的时候,单例对象被创建了
// @Scope("prototype") 多例,多例对象创建的时机:在getBean() 真正从工厂获取的对象时候才创建
public class UserDaoImpl extends BaseDaoImpl<User> implements IUserDao {

}

2.2、表现层的设计

表现层的设计图解,如下图所示:

表现层通用代码: BaseAction.java

package com.itheima.bos.web.action.base;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class BaseAction<T> extends ActionSupport implements ModelDriven<T> {

    // 声明模型对象
    private T model;

    public T getModel() {
        return model;
    }

    // 在构造方法中动态获取操作要用的实体类型,然后通过反射创建模型对象
    public BaseAction() {
        // Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
        Type type = this.getClass().getGenericSuperclass();
        // ParameterizedType 参数化类型,即泛型
        ParameterizedType pt = (ParameterizedType)type;
        // getActualTypeArguments() 获取参数化类型的数组,泛型可能有多个
        Type[] actualTypeArguments = pt.getActualTypeArguments();
        // 获取操作要用的实体类型
        Class<T> entityClass = (Class<T>) actualTypeArguments[0];

        try {
            // 通过反射创建模型对象
            model = entityClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

我们再补UserAction的示例代码: UserAction.java

package com.itheima.bos.web.action;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.itheima.bos.domain.User;
import com.itheima.bos.web.action.base.BaseAction;

@Controller
@Scope("prototype") // 配置对象多例
public class UserAction extends BaseAction<User> {

    // 简单测试struts是否配置成功,测试完删掉
    public String test() {
        return "test";
    }
}

相应的struts.xml文件需要对userAction进行配置: struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <!-- 设置为开发者模式 -->
    <constant name="struts.devMode" value="true"/>
    <!-- 使Spring对象工厂成为自动默认值,struts2与spring整合,该句不是必须的,在整合jar中已经配置过了 ,这里只是为了强调-->
    <constant name="struts.objectFactory" value="spring"/>

    <package name="basicstruts2" extends="struts-default">
        <!-- 需要进行权限控制的页面访问,使用默认的类和默认的方法,默认的类和默认的方法可以不用写,这里写出来为了强调 -->
        <action name="page_*_*" class="com.opensymphony.xwork2.ActionSupport" method="execute">
            <result name="success" type="dispatcher">/WEB-INF/pages/{1}/{2}.jsp</result>
        </action>
        <!-- 配置userAction-->
        <action name="userAction_*" class="userAction" method="{1}">
            <result>xxx</result>
        </action>
    </package>
</struts>

3、基于BaseDao和BaseAction实现用户登录功能

第一步:修改login.jsp页面,点击登录按钮,提交表单 login.jsp

......
    <form id="loginform" name="loginform" method="post" class="niceform"
        action="${pageContext.request.contextPath}/userAction_login.action">
......
    <%-- <a href="${pageContext.request.contextPath}/page_common_index.action" id="loginform:j_id19" name="loginform:j_id19"> --%>
    <a onclick="document.forms[0].submit()" id="loginform:j_id19" name="loginform:j_id19">
    <span id="loginform:loginBtn" class="btn btn-login" style="margin-top:-36px;">登录</span>
    </a>
......

浏览器页面如下图所示:

第二步:在UserAction中提供login()方法 UserAction.java

package com.itheima.bos.web.action;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.itheima.bos.domain.User;
import com.itheima.bos.service.IUserService;
import com.itheima.bos.web.action.base.BaseAction;

@Controller
@Scope("prototype") // 配置对象多例
public class UserAction extends BaseAction<User> {

    // 注入service
    @Resource
    private IUserService userServie;

    // 通过属性驱动接收传递过来的验证码
    private String checkcode;
    public void setCheckcode(String checkcode) {
        this.checkcode = checkcode;
    }

    public String login() {
        // 判断用户输入的验证码是否正确
        // 先获取我们自己生成的验证码
        String key = (String) ServletActionContext.getRequest().getSession().getAttribute("key");
        // 判断用户是否有输入验证码和输入的验证码是否和我生成的验证码是否相等
        if (StringUtils.isNotBlank(checkcode) && checkcode.equals(key)) {
            // 说明验证码存在且正确
            User user = userServie.login(model);
            if (user != null) {
                // 说明登录成功,将User放入session域中,并跳转到系统首页
                ServletActionContext.getRequest().getSession().setAttribute("loginUser", user);
                return "home";
            } else {
                // 说明登录失败,设置错误提示信息,并跳转至登录页面
                // this.addActionError("用户名或者密码错误"); // 在Struts2中,所有的消息提示都是基于国际化的。
                this.addActionError(this.getText("loginError"));
                return "login";
            }
        } else {
            // 说明验证码错误,设置错误提示信息,并跳转至登录页面
            // this.addActionError("验证码错误"); // 在Struts2中,所有的消息提示都是基于国际化的。
            this.addActionError(this.getText("validatecodeError"));
            return "login";
        }
    }

}

第三步:提供IUserService接口和UserServiceImpl类 IUserService.java

package com.itheima.bos.service;

import com.itheima.bos.domain.User;

public interface IUserService {

    public User login(User model);
}

UserServiceImpl.java

package com.itheima.bos.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.itheima.bos.dao.IUserDao;
import com.itheima.bos.domain.User;
import com.itheima.bos.service.IUserService;
import com.itheima.bos.utils.MD5Utils;

@Service
@Transactional
public class UserServiceImpl implements IUserService {

    // 注入dao
    @Autowired
    private IUserDao userDao;

    public User login(User model) {
        String username = model.getUsername();
        String password = model.getPassword(); // 明文密码
        password = MD5Utils.md5(password); // MD5加密后的密码
        User user = userDao.findByUserNameAndPassWord(username, password);
        return user;
    }

}

第四步:在IUserDao接口中扩展方法和UserDaoImpl实现类,根据用户名和密码查询用户 IUserDao.java

package com.itheima.bos.dao;

import com.itheima.bos.dao.base.IBaseDao;
import com.itheima.bos.domain.User;

public interface IUserDao extends IBaseDao<User> {

    public User findByUserNameAndPassword(String username, String password);
}

UserDaoImpl.java

package com.itheima.bos.dao.impl;

import java.util.List;

import org.springframework.stereotype.Repository;

import com.itheima.bos.dao.IUserDao;
import com.itheima.bos.dao.base.impl.BaseDaoImpl;
import com.itheima.bos.domain.User;

@Repository // IUserDaoImpl对象默认是单例的,单例对象创建的时机:在applicationContext.xml配置文件加载,执行组件扫描,创建工厂的时候,单例对象被创建了
// @Scope("prototype") 多例,多例对象创建的时机:在getBean() 真正从工厂获取的对象时候才创建
public class UserDaoImpl extends BaseDaoImpl<User> implements IUserDao {

    /*
     * 根据用户名和密码查询用户
     */
    public User findByUserNameAndPassword(String username, String password) {
        String hql = "from User u where u.username=? and u.password=?";
        List<User> list = this.getHibernateTemplate().find(hql, username, password);
        if (list != null && list.size() > 0 ) {
            return list.get(0);
        }
        return null;
    }

}

第五步:编写国际化配置文件,在struts.xml中注册(配置)国际化文件 /bos19/config/message.properties

loginError=\u7528\u6237\u540D\u6216\u8005\u5BC6\u7801\u9519\u8BEF
validatecodeError=\u9A8C\u8BC1\u7801\u9519\u8BEF

struts.xml

......
    <!-- 在struts中注册(配置)国际化文件 -->
    <constant name="struts.custom.i18n.resources" value="message"></constant>
......

第六步:在login.jsp页面中使用struts2提供的标签展示错误提示信息 login.jsp

......
<%@ taglib uri="/struts-tags" prefix="s"%>
......
    <font color="red">
        &emsp;&emsp;&emsp;&emsp;<s:actionerror/>
    </font>

4、jQuery EasyUI 消息框控件 messager

示例代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>messager---消息框控件</title>
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/easyui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/easyui/themes/icon.css">
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.8.3.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/jquery.easyui.min.js"></script>
    <!-- 引入中文语言包 -->
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/locale/easyui-lang-zh_CN.js"></script>
    <script type="text/javascript">
        $(function() {
            // alert();
            // window.alert();
            // 消息提示框
            $.messager.alert("标题", "内容信息", "question");
            window.setTimeout(function() {
                // 消息提示框(在屏幕的右下角显示一个消息窗口)
                $.messager.show({
                    title:'欢迎信息',
                    msg:'欢迎张三登录系统',
                    timeout:3000,
                    showType:'slide'
                }); 
            }, 3000);

            // 消息确认框
            $.messager.confirm("标题", "你确定删除当前数据吗?", function(r) {
                alert(r);
            });

            // 带有输入功能的消息确认框
            $.messager.prompt("标题", "你确定删除当前数据吗?", function(r) {
                alert(r);
            });

            // 显示进度提示框
            $.messager.progress();
            // 延时3秒后关闭进度提示框
            window.setTimeout(function() {
                $.messager.progress('close');
            }, 3000);
        });
    </script>
</head>
<body>
</body>
</html>

5、jQuery EasyUI 菜单按钮 menubutton

示例代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>menubutton---菜单按钮</title>
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/easyui/themes/default/easyui.css">
    <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/easyui/themes/icon.css">
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.8.3.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/jquery.easyui.min.js"></script>
    <!-- 引入中文语言包 -->
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/locale/easyui-lang-zh_CN.js"></script>
</head>
<body>
    <a data-options="iconCls:'icon-help',menu:'#mm'" class="easyui-menubutton">控制面板</a>
    <!-- 使用div制作下拉菜单选项 -->
    <div id="mm">
        <!-- 使用子div制作具体的一个选项 -->
        <div onclick="alert(111)" data-options="iconCls:'icon-edit'">修改密码</div>
        <div>联系管理员</div>
        <div class="menu-sep"></div>
        <div>退出系统</div>
    </div>
</body>
</html>

效果如下图所示:

6、自定义struts2拦截器,实现用户未登录时自动跳转到登录页面

第一步:自定义一个拦截器类 BOSLoginInterceptor.java

package com.itheima.bos.web.intereptor;

import org.apache.struts2.ServletActionContext;

import com.itheima.bos.domain.User;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

/*
 * 自定义一个struts2拦截器,实现用户未登录时,自动跳转到登录页面
 */
public class BOSLoginInterceptor extends MethodFilterInterceptor{

    // 拦截方法
    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        // 测试自定义拦截器是否工作
        // ActionProxy proxy = invocation.getProxy();
        // String namespace = proxy.getNamespace();
        // String actionName = proxy.getActionName();
        // String url = namespace + actionName;
        // System.out.println("自定义的struts拦截器执行了" + url);

        User user = (User) ServletActionContext.getRequest().getSession().getAttribute("loginUser");
        if (user == null) {
            // 说明用户未登录,跳转到登录页面
            return "login";
        }
        // 否则说明用户登录,就放行
        return invocation.invoke();
    }
}

第二步:在struts.xml中注册(配置/声明)自定义的拦截器

......
        <!-- 注册(配置/声明)拦截器  -->
        <interceptors>
            <!-- 注册(配置/声明)自定义的拦截器 -->
            <interceptor name="BOSLoginInterceptor" class="com.itheima.bos.web.intereptor.BOSLoginInterceptor"></interceptor>
            <!-- 我的全局拦截器栈中包括: -->
            <interceptor-stack name="myStack">
                <!-- 1、默认的拦截器栈 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <!-- 2、我自定义的拦截器 -->
                <interceptor-ref name="BOSLoginInterceptor">
                    <!-- 自定义的拦截器要配置:需要拦截哪些方法,和需要放过哪些方法 -->
                    <param name="excludeMethods">login</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 重新定义默认的拦截器栈 -->
        <default-interceptor-ref name="myStack"></default-interceptor-ref>
        <!-- 配置/声明全局逻辑结果视图 -->
        <global-results>
            <result name="login">/login.jsp</result>
        </global-results>
......

7、基于ajax实现修改密码功能

/WEB-INF/pages/common/index.jsp

第一步:为密码输入框制定输入校验规则,使用easyUI提供的form表单控件中的easyui-validatebox

......
    <!-- 注意:该表单不是用来提交用的,而是用来制定输入校验规则用的 -->
    <form id="editPasswordForm">
        <table cellpadding=3>
            <tr>
                <td>新密码:</td>
                <td><input id="txtNewPass" type="Password" class="txt01 easyui-validatebox"
                    data-options="required:true, validType:'length[4,8]'"
                /></td>
            </tr>
            <tr>
                <td>确认密码:</td>
                <td><input id="txtRePass" type="Password" class="txt01 easyui-validatebox" 
                    data-options="required:true, validType:'length[4,8]'"
                /></td>
            </tr>
        </table>
    </form>
......

第二步:为修改密码的“确定”按钮绑定事件

    // 为修改密码的“确定”按钮绑定事件
    $("#btnEp").click(function() {
        // 进行表单验证
        // 基于jQuery的表单验证插件Validation Engine
        var v = $("#editPasswordForm").form("validate"); // 先对该表单中的所有输入框进行校验(前提:你先要有校验规则)
        // alert(v); // true 或 false
        if (v) { 
            // 说明表单校验通过
            // 再判断两次密码输入是否一致
            var v1 = $("#txtNewPass").val();
            var v2 = $("#txtRePass").val();
            if (v1 == v2) {
                // 说明两次输入一致,发送ajax请求,修改当前用户的密码
                var url = "${pageContext.request.contextPath}/userAction_editPassword.action";
                $.post(url, {"password":v1}, function(data) {
                    // alert(data);
                    if (data == '1') {
                        // 密码修改成功
                         $.messager.alert("提示信息", "密码修改成功!", "info");
                    } else {
                        // 密码修改失败
                        $.messager.alert("提示信息", "密码修改失败!", "warning");
                    } 
                    // 关闭修改密码的窗口
                    $('#editPwdWindow').window('close');
                });
            } else {
                // 说明两次密码输入不一致,提示用户:两次输入密码不一致
                $.messager.alert("提示信息", "两次输入密码不一致", "warning");
            }
        }
    });

第三步:在UserAction中提供editPassword方法,用于修改当前用户的密码

    /*
     * 修改当前用户的密码
     */
    public String editPassword() throws IOException {
        User user = (User) ServletActionContext.getRequest().getSession().getAttribute("loginUser");
        // 获取新密码
        String password = model.getPassword();
        // MD5加密
        password = MD5Utils.md5(password);
        user.setPassword(password);

        // 此法不好,User的所有字段都要更新,更新的数据太多了
        // userServie.update(user); // update t_user set name=?,password=?,... 

        String flag = "1";
        try {
            // 使用通用的更新方法
            userServie.editPassword(password, user.getId());
        } catch (Exception e) {
            // 修改密码失败
            flag = "0";
        }
        // 响应给浏览器一个状态码,这种手法常用
        ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
        ServletActionContext.getResponse().getWriter().print(flag);

        return "none";
    }

第四步:在IBaseDao中扩展一个通用的更新方法 IBaseDao.java

    // 提供通用修改方法,可变参数
    public void executeUpdate(String queryName, Object ...objects);

BaseDaoImpl.java

    /*
     * 通用更新方法
     */
    public void executeUpdate(String queryName, Object... objects) {
        // 从本地线程中获得session对象
        Session session = this.getSession();
        // 使用命名查询语句获得一个查询对象
        Query query = session.getNamedQuery(queryName);
        // 循环为HQL语句中的?设置值(赋值)
        int i = 0;
        for (Object arg : objects) {
            query.setParameter(i++, arg);
        }
        // 执行更新
        query.executeUpdate();
    }

第五步:在User.hbm.xml中定义一个HQL语句,用于修改密码 注意:<query>标签与<class>标签同级

    <!-- 命名查询语句 -->
    <query name="editPassword">
        update User set password=? where id=?
    </query>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏分布式系统进阶

ReplicaManager源码解析1-消息同步线程管理

基本上就是作三件事: 构造FetchRequest, 同步发送FetchRequest并接收FetchResponse, 处理FetchResponse, 这三...

1502
来自专栏腾讯云API

腾讯云API:无服务器函数

无服务器函数是一个很好玩的东西,可以通过这个程序跑一些脚本,在一定程度上,是很方便的。但是作为新鲜事物,一般很难被大家接受,所以,我今天在这里,就做一个小例子,...

8445
来自专栏菩提树下的杨过

Oracle中使用Entity Framework 6.x Code-First方式开发

去年写过一篇EF的简单学习笔记,当时EF还不支持Oracle的Code-First开发模式,今天无意又看了下Oracle官网,发现EF6.X已经支持了,并且给出...

2485
来自专栏SHERlocked93的前端小站

Node中的事件循环和异步API

单线程编程会因阻塞I/O导致硬件资源得不到更优的使用。多线程编程也因为编程中的死锁、状态同步等问题让开发人员头痛。 Node在两者之间给出了它的解决方案:利用单...

1553
来自专栏ChaMd5安全团队

Real World CTF国际大赛 部分WP

题目描述里写平台很安全,请不要攻击。 所以尝试抓包,往Cookie的uid进行sqli

1481
来自专栏代码世界

AJAX

先了解JSON 什么是JSON? JSON 指的是JavaScript对象表示法(JavaScript Object Notation) JSON 是轻量级的文...

4177
来自专栏葡萄城控件技术团队

七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理

? 第三天我们将学习Asp.Net中数据处理功能,了解数据访问层,EF,以及EF中常用的代码实现方式,创建数据访问层和数据入口,处理Post数据,以及数据验...

31210
来自专栏Java 源码分析

SpringBoot 笔记 ( 二 ):自定义配置

SpringBoot 笔记 ( 二 ) 1. 配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: application.propert...

3966
来自专栏linux驱动个人学习

kmalloc、vmalloc、__get_free_pages()的区别

一、分布位置上的区别: kmalloc()和__get_free_pages()函数申请的内存位于物理内存的映射区域,而且在物理上也是连续的,它们与真实的物理地...

6025
来自专栏比原链

剥开比原看代码02:比原启动后去哪里连接别的节点

Gitee地址:https://gitee.com/BytomBlockchain/bytom

1182

扫码关注云+社区

领取腾讯云代金券