精华内容
下载资源
问答
  • Springboot+Ajax+Mybatis+Mysql实现异步登录 欢迎访问我的个人博客:http://www.xhcoder.com/ 本人大学生,搞了三年的PHP,感觉PHP的生态还是不行,但是PHP仍然是全世界最好的语言!!!上手简单,能快速搭建起一...

    Springboot+Ajax+Mybatis+Mysql实现异步登录


    欢迎访问我的个人博客:http://www.xhcoder.com/

    本人大学生,搞了三年的PHP,感觉PHP的生态还是不行,但是PHP仍然是全世界最好的语言!!!上手简单,能快速搭建起一个项目。由于快要找工作了想花一年的时间来搞搞Java,搞了一段时间后发现Java整套是真是完善,可扩展性很强,Java牛逼不是没有道理的。

    搭建Springboot项目

    springboot是建立在的spring生态的基础上的,以前看spring的时候,有两大概念是纠结了很久的,IOC(控制反转)以及AOP(面向切面的编程)。其实控制反转就是依赖注入,spring提供了一个IOC容器来初始化对象,解决对象间依赖管理和对象的使用,如@Bean、@Autowired等可以实现依赖注入,AOP目前理解是在一些日志框架场景中用到。
    平时我们常见的web项目开发,使用的mvc框架、maven管理在springboot依然使用到,springboot最明显的好处是简化了新建一个项目时的各种配置过程,就连tomcat都不用配置了。可以看到我新建一个maven项目大目录结构是这样的
    在这里插入图片描述
    Maven依赖:

    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.0.1</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    

    application.yml

    server:
      port: 8080
    
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver
        type: com.zaxxer.hikari.HikariDataSource
      thymeleaf:
        cache: false
    

    login.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="utf-8">
        <title>用户登录</title>
    
        <!-- CSS -->
        <link rel="stylesheet" href="assets/css/reset.css">
        <link rel="stylesheet" href="assets/css/supersized.css">
        <link rel="stylesheet" href="assets/css/style.css">
    </head>
    <body>
    <div class="page-container">
        <h1>用户登录</h1>
        <form>
            <input type="text" id="username" name="username" value="" placeholder="用户名">
            <input type="password" id="password" name="password" value="" placeholder="密码">
            <button type="button" onclick="login()">提交</button>
        </form><br />
    </div>
    
    <!-- Javascript -->
    <script src="assets/js/jquery-1.8.2.min.js"></script>
    <script src="assets/js/supersized.3.2.7.min.js"></script>
    <script src="assets/js/supersized-init.js"></script>
    <script src="assets/js/scripts.js"></script>
    <!--<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>-->
    <script>
        function login() {
            var username = document.getElementById("username").value;
            var password = document.getElementById("password").value;
            $.ajax({
                type: "POST",
                url: "/login_ht",
                data: {
                    username: username,
                    password: password
                },
                dataType: "json",
                success: function(data){
                    var msg = data.msg;
                    alert(msg);
                }
            })
        }
    </script>
    </body>
    </html>
    

    实体类(entity里的Users类)

    package com.example.demo.entity;
    
    public class Users {
        private Integer id;
        private String username;
        private String password;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

    定义基本的几个属性后,可以通过键盘上的“alt+insert”键,来进行自动添加该类自带的get和set方法,以及toString方法

    mapper(mapper里的UserMapper类):

    package com.example.demo.mapper;
    
    
    import com.example.demo.entity.Users;
    import org.apache.ibatis.annotations.*;
    
    
    @Mapper
    public interface UserMapper {
    
        @Select("select * from user where id=#{id}")
        public Users getUserById(Integer id);
    
        @Select("select username from user where username=#{username} and password=#{password}")
        public String login(@Param("username") String username,@Param("password") String password);
    
        @Delete("delete from user where id=#{id}")
        public int deleteUserById(Integer id);
    
        @Options(useGeneratedKeys = true,keyProperty = "id")
        @Insert("insert into user(username,password) values(#{username},#{password})")
        public int insertUser(Users users);
    
        @Update("update user set password=#{password} where id=#{id}")
        public int updateUser(Users users);
    }
    

    这里我使用的是mybatis的注解的形式实现增删改查的,mybatis还提供了一个xml配置的方式,但是我觉得小demo还是使用注解的方式比较简单。当然这里的登录功能只需要用到查询。

    注意一定要加上@Mapper注解,不然容器扫描不到。

    UserService:
    书写service,业务层,控制业务,主要负责业务逻辑模块的逻辑应用设计

    package com.example.demo.service;
    
    
    import com.example.demo.mapper.UserMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
    
        @Autowired
        UserMapper userMapper;
    
        public String login(String username,String password){
            return userMapper.login(username,password);
        }
    }
    

    LoginController:
    controller控制层,负责具体的业务模块流程的控制,即页面访问控制,调用service层里面的接口控制具体的业务流程

    package com.example.demo.controller;
    
    import com.example.demo.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import javax.swing.*;
    import java.util.HashMap;
    import java.util.Map;
    
    @Controller
    public class LoginController {
    
        @Autowired
        UserService userService;
    
        @RequestMapping("/login")
        public String login(){
            return "login";
        }
    
        @ResponseBody
        @RequestMapping(value = "/login_ht", method = {RequestMethod.POST, RequestMethod.GET})
        public Map<String,Object> login(HttpServletRequest request, HttpSession session){
            Map<String,Object> map = new HashMap<String,Object>();
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String name = userService.login(username,password);
            System.out.println(username+password);
            System.out.println(name);
            session.setAttribute("name", name);
            if (name == null) {
                map.put("msg","用户名或密码错误");
            } 
            return map;
        }
    
        @RequestMapping("/success")
        public String success(){
            return "success";
        }
    }
    

    @RequestMapping(value = “/login_ht”, method ={RequestMethod.POST,RequestMethod.GET})
    HttpServletRequest request

    该value的值/login_ht要与ajax中url值一样,

    注意这里一定要加上@ResponseBody注解!!这样才能将数据以Json格式返回到前台!

    欢迎访问我的个人博客:http://www.xhcoder.com/

    展开全文
  • JAVA异步编程

    2021-08-14 10:58:47
    文章目录前言异步的使用场景:异步好处:在JAVA中异步的实现方式一:实现异步工厂需要依赖的工具类线程池配置异步任务管理器关闭线程池实现异步调用工厂异步工厂测试用例二:使用JDK1.8中 CompletableFuture...

    前言

    今天来简单总结一下JAVA中的异步执行,那么有异步肯定就有同步,他们有什么区别呢?我们为什么要进行异步操作呢?

    • 同步:在所有操作执行完毕后返回给客户端,在这个过程中需要在不断的等待,且客户端不能关闭。
    • 异步:将本次请求放入消息队列,直接反馈给用户结果,然后由程序去按照队列顺序执行业务逻辑。

    那么了解了同步与异步的区别之后,我们自然也就能明白为什么要进行异步操作了。
    在某些比较特殊的场合下,我们需要及时给出响应,又不想因为业务逻辑的执行导致需要等待的时候,就需要用到我们今天的主角“异步”了。

    异步的使用场景:
    1. 不涉及共享资源,或对共享资源只读,即非互斥操作
    2. 没有时序上的严格关系
    3. 不需要原子操作,或可以通过其他方式控制原子性
    4. 常用于IO操作等耗时操作,因为比较影响客户体验和使用性能
    5. 不影响主线程逻辑
    异步的好处:
    1. 异步流程可以立即给调用方返回初步的结果。
    2. 异步流程可以延迟给调用方最终的结果数据,在此期间可以做更多额外的工作,例如结果记录等等。
    3. 异步流程在执行的过程中,可以释放占用的线程等资源,避免阻塞,等到结果产生再重新获取线程处理。
    4. 异步流程可以等多次调用的结果出来后,再统一返回一次结果集合,提高响应效率。

    异步的使用场景及好处参考链接:同步、异步的使用场景及好处

    在JAVA中异步的实现方式

    一:实现异步工厂

    项目中有看到某位大佬对异步、线程池进行了封装,简化了调用的操作,所以这里记录一下实现方式。

    需要依赖的工具类

    线程相关工具类,直接放进项目即可

    /**
     * 线程相关工具类
     *
     * @author LiWT
     */
    @Slf4j
    public class ThreadUtils {
    
        /**
         * sleep等待,单位为毫秒
         */
        public static void sleep(long milliseconds) {
            try {
                Thread.sleep(milliseconds);
            } catch (InterruptedException e) {
                log.error("sleep error:", e);
            }
        }
    
        /**
         * 停止线程池
         * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
         * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
         * 如果仍然超时,则强制退出.
         * 另对在shutdown时线程本身被调用中断做了处理.
         */
        public static void shutdownAndAwaitTermination(ExecutorService pool) {
            if (pool != null && !pool.isShutdown()) {
                pool.shutdown();
                try {
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        pool.shutdownNow();
                        if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                            log.info("Pool did not terminate");
                        }
                    }
                } catch (InterruptedException ie) {
                    pool.shutdownNow();
                    Thread.currentThread().interrupt();
                }
            }
        }
    
        /**
         * 打印线程异常信息
         */
        public static void printException(Runnable r, Throwable t) {
            if (t == null && r instanceof Future<?>) {
                try {
                    Future<?> future = (Future<?>) r;
                    if (future.isDone()) {
                        future.get();
                    }
                } catch (CancellationException ce) {
                    t = ce;
                } catch (ExecutionException ee) {
                    t = ee.getCause();
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                }
            }
            if (t != null) {
                log.error(t.getMessage(), t);
            }
        }
    }
    

    Spring工具类 方便在非Spring管理环境中获取Bean

    /**
     * spring工具类 方便在非spring管理环境中获取bean
     *
     * @author LiWT
     */
    @Component
    public final class SpringUtils implements BeanFactoryPostProcessor {
        /**
         * Spring应用上下文环境
         */
        private static ConfigurableListableBeanFactory beanFactory;
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            SpringUtils.beanFactory = beanFactory;
        }
    
        /**
         * 获取对象
         *
         * @param name
         * @return Object 一个以所给名字注册的bean的实例
         * @throws BeansException
         */
        @SuppressWarnings("unchecked")
        public static <T> T getBean(String name) throws BeansException {
            return (T) beanFactory.getBean(name);
        }
    
        /**
         * 获取类型为requiredType的对象
         *
         * @param clz
         * @return
         * @throws BeansException
         */
        public static <T> T getBean(Class<T> clz) throws BeansException {
            T result = (T) beanFactory.getBean(clz);
            return result;
        }
    
        /**
         * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
         *
         * @param name
         * @return boolean
         */
        public static boolean containsBean(String name) {
            return beanFactory.containsBean(name);
        }
    
        /**
         * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
         *
         * @param name
         * @return boolean
         * @throws NoSuchBeanDefinitionException
         */
        public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
            return beanFactory.isSingleton(name);
        }
    
        /**
         * @param name
         * @return Class 注册对象的类型
         * @throws NoSuchBeanDefinitionException
         */
        public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
            return beanFactory.getType(name);
        }
    
        /**
         * 如果给定的bean名字在bean定义中有别名,则返回这些别名
         *
         * @param name
         * @return
         * @throws NoSuchBeanDefinitionException
         */
        public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
            return beanFactory.getAliases(name);
        }
    
        /**
         * 获取aop代理对象
         *
         * @param invoker
         * @return
         */
        @SuppressWarnings("unchecked")
        public static <T> T getAopProxy(T invoker) {
            return (T) AopContext.currentProxy();
        }
    }
    
    线程池配置
    /**
     * 线程池配置
     *
     * @author LiWT
     **/
    @Configuration
    public class ThreadPoolConfig {
        /**
         * 核心线程池大小
         */
        private final int corePoolSize = 50;
    
        /**
         * 最大可创建的线程数
         */
        private final int maxPoolSize = 200;
    
        /**
         * 队列最大长度
         */
        private final int queueCapacity = 1000;
    
        /**
         * 线程池维护线程所允许的空闲时间
         */
        private final int keepAliveSeconds = 300;
    
        @Bean(name = "threadPoolTaskExecutor")
        public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setMaxPoolSize(maxPoolSize);
            executor.setCorePoolSize(corePoolSize);
            executor.setQueueCapacity(queueCapacity);
            executor.setKeepAliveSeconds(keepAliveSeconds);
            // 线程池对拒绝任务(无线程可用)的处理策略
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            return executor;
        }
    
        /**
         * 执行周期性或定时任务
         */
        @Bean(name = "scheduledExecutorService")
        protected ScheduledExecutorService scheduledExecutorService() {
            return new ScheduledThreadPoolExecutor(corePoolSize,
                    new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
                @Override
                protected void afterExecute(Runnable r, Throwable t) {
                    super.afterExecute(r, t);
                    ThreadUtils.printException(r, t);
                }
            };
        }
    }
    
    异步任务管理器
    /**
     * 异步任务管理器
     *
     * @author LiWT
     */
    public class AsyncManager {
      /**
       * 操作延迟10毫秒
       */
      private final int OPERATE_DELAY_TIME = 10;
    
      /**
       * 异步操作任务调度线程池
       */
      private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
    
      /**
       * 单例模式
       */
      private AsyncManager() {
      }
    
      private static AsyncManager me = new AsyncManager();
    
      public static AsyncManager me() {
        return me;
      }
    
      /**
       * 执行任务
       *
       * @param task 任务
       */
      public void execute(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
      }
    
      /**
       * 停止任务线程池
       */
      public void shutdown() {
        ThreadUtils.shutdownAndAwaitTermination(executor);
      }
    }
    
    关闭线程池实现
    /**
     * 确保应用退出时能关闭后台线程
     *
     * @author LiWT
     */
    @Slf4j
    @Component
    public class ShutdownManager {
    
        @PreDestroy
        public void destroy() {
            shutdownAsyncManager();
        }
    
        /**
         * 停止异步执行任务
         */
        private void shutdownAsyncManager() {
            try {
                log.info("====关闭后台任务任务线程池====");
                AsyncManager.me().shutdown();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }
    
    • 可以看出异步任务管理器核心其实是创建一个10毫秒延迟的定时器,然后来触发创建的定时任务来执行业务逻辑。
    • 使用时通过调用execute()方法来创建定时任务执行,在我们服务终止或关闭时调用shutdown()来停掉任务的线程池。
    异步调用工厂
    /**
     * 异步工厂(产生任务用)
     *
     * @author LiWT
     */
    @Slf4j
    public class AsyncFactory {
    
    
        /**
         * 测试异步工厂
         *
         * @param str
         * @return
         */
        public static TimerTask testAsync(String str) {
            return new TimerTask() {
                @Override
                public void run() {
                    ThreadUtils.sleep(10000);
                    long times = System.currentTimeMillis();
                    System.out.println("testAsync times:" + times + " log : " + str);
                }
            };
        }
    
        /**
         * 记录登陆信息
         *
         * @param username 用户名
         * @param status   状态
         * @param message  消息
         * @param request  request
         * @param args     列表
         * @return 任务task
         */
        public static TimerTask recordLogininfor(final String username, final String status, final String message, HttpServletRequest request,
                                                 final Object... args) {
            return new TimerTask() {
                @Override
                public void run() {
                    //获取登录信息保存数据库
                }
            };
        }
    
        /**
         * 操作日志记录
         * aop保存用户操作日志调用
         *
         * @param operLog 操作日志信息
         * @return 任务task
         */
        public static TimerTask recordOper(final String operLog) {
            return new TimerTask() {
                @Override
                public void run() {
                    //用户操作信息保存数据库
                }
            };
        }
    }
    
    • 异步工厂中定义了testAsync()方法,可以用来进行测试。
    • 下边两个是我们项目中使用的的场景:
      • 比如在用户登录后记录用户登录信息;
      • 或是每次用户操作完毕后保存操作日志;
      • 又或是一些第三方接口回调方法的执行。
    异步工厂测试用例
    /**
     * @Author: LiWT
     * @Date: 2021/8/14 10:08
     */
    @RestController
    @RequestMapping("/async")
    public class AsyncFactoryController {
    
        @GetMapping("/asyncFactoryTest")
        public String asyncFactoryTest() {
            AsyncManager.me().execute(AsyncFactory.testAsync("异步执行......"));
            long successTimes = System.currentTimeMillis();
            return "请求结束,返回 时间:" + successTimes;
        }
    }
    

    我们从浏览器访问测试接口:localhost:port/async/asyncFactoryTest
    为了更直观的体现异步执行的时间差,我在testAsync()方法中执行了ThreadUtils.sleep(10000);使线程睡眠10s后执行。
    请求直接返回响应:
    请求结束,返回 时间:1628834332942

    控制台输出:testAsync times:1628834342973 log : 异步执行......
    

    通过测试我们可以看到异步操作的好处,首先及时的响应了客户端,然后再来起别的线程处理我们的业务,一定程度上优化了我们的程序。

    二:使用JDK1.8中 CompletableFuture
    CompletableFuture 简介

    CompletableFuture是Future的实现类,弥补了Future一些缺陷,比如阻塞、回调等

    CompletableFuture 实现异步

    CompletableFuture提供了四个静态方法来创建一个异步操作:

    public static CompletableFuture<Void> runAsync(Runnable runnable)
    public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)
    

    创建时若没有传入Executor,会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码;若指定了线程池,则使用指定的线程池运行。

    • runAsync 方法不支持返回值
    • supplyAsync 方法支持返回值
    CompletableFuture 测试用例
    /**
     * @Author: LiWT
     * @Date: 2021/8/14 10:08
     */
    @RestController
    @RequestMapping("/async")
    public class AsyncFactoryController {
    
        @Autowired
        @Qualifier("threadPoolTaskExecutor")
        ThreadPoolTaskExecutor executor;
    
        @GetMapping("/completableFutureAsyncTest")
        public void completableFutureAsyncTest() throws ExecutionException, InterruptedException {
            //方式一:
            CompletableFuture.runAsync(() -> {
                System.out.println("runAsync 方式一");
            });
            //方式二:
            CompletableFuture.runAsync(() -> {
                System.out.println("runAsync 方式二");
            }, executor);
            //方式三:
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("supplyAsync 方式三");
                return "方式三 执行完毕。。。";
            });
            System.out.println(future.get());
            //方式四:
            CompletableFuture<String> futureByExecutor = CompletableFuture.supplyAsync(() -> {
                System.out.println("supplyAsync 方式四");
                return "方式四 执行完毕。。。";
            }, executor);
            System.out.println(futureByExecutor.get());
        }
    
    }
    

    控制台输出为:

    runAsync 方式一
    runAsync 方式二
    supplyAsync 方式三
    方式三 执行完毕。。。
    supplyAsync 方式四
    方式四 执行完毕。。。
    

    CompletableFuture使用get()即可获取到返回值。
    CompletableFuture常用的方法还有thenApplyAsync()、whenCompleteAsync()、thenAccept()、thenCombine()、anyOf()、allOf()…
    总的来说JDK1.8中的CompletableFuture还是非常方便的,大家有空可以多学习一下。

    展开全文
  • 同步、异步的使用场景及好处

    万次阅读 2016-06-02 11:02:15
    异步的使用场景: 1、不涉及共享资源,或对共享资源只读,即非互斥操作 2、没有时序上的严格关系 ...3、不需要原子操作,或可以通过其他方式...同步的好处: 1、同步流程对结果处理通常更为简单,可以就近处理。

    异步的使用场景:

    1、不涉及共享资源,或对共享资源只读,即非互斥操作

    2、没有时序上的严格关系

    3、不需要原子操作,或可以通过其他方式控制原子性

    4、常用于IO操作等耗时操作,因为比较影响客户体验和使用性能

    5、不影响主线程逻辑


    同步的使用场景:不使用异步的时候


    同步的好处:

    1、同步流程对结果处理通常更为简单,可以就近处理。

    2、同步流程对结果的处理始终和前文保持在一个上下文内。

    3、同步流程可以很容易捕获、处理异常。

    4、同步流程是最天然的控制过程顺序执行的方式。

     

    异步的好处:

    1、异步流程可以立即给调用方返回初步的结果。

    2、异步流程可以延迟给调用方最终的结果数据,在此期间可以做更多额外的工作,例如结果记录等等。

    3、异步流程在执行的过程中,可以释放占用的线程等资源,避免阻塞,等到结果产生再重新获取线程处理。

    4、异步流程可以等多次调用的结果出来后,再统一返回一次结果集合,提高响应效率。

    展开全文
  • 1. 前端使用异步加载的好处:先布置好页面布局,请求回数据后再加入页面中,如图片的加载。能加快网页加载速度。 2. 实现方法:前端用 jq 中的 ajax请求(ajax请求默认异步加载),django后台创建每个请求的接口。 ...

    前言:
    1. 前端使用异步加载的好处:先布置好页面布局,请求回数据后再加入页面中,如图片的加载。能加快网页加载速度。
    2. 实现方法:前端用 jq 中的 ajax请求(ajax请求默认异步加载),django后台创建每个请求的接口。
    3. 我们这里实现一个前端请求,用户是否登录。


    后端接口设计

    1. 修改views
    #请求只需要返回页面,数据通过ajax异步加载
    def classify(req):
        return render(req,'classify.html')
    from django.http import JsonResponse
    
    #接口:user_session
    #请求链接: ./api/user/
    #请求参数: 无
    #返回参数: status: 200 成功;isLogin: Ture/false 是否登录;username: [username]/'' 用户名
    #
    def user_session(req):
        context = {'status': 200}
        if 'username' in req.session: #判断username是否在session中
            username = req.session['username']
            context['isLogin'] = True
            context['username'] = username
        else:
            context['isLogin'] = False
            context['username'] = ''
        return JsonResponse(context)#返回json数据

    2 . 添加接口到 urls.py

    urlpatterns = [
        url(r'^classify/(\d+)/(\d+)/$',views.classify),
        url(r'^api/user/',views.user_session),
    ]

    前端页面请求

    因为判断用户登录的功能几乎网站每个页面都需要。所以写在templates下 base.html 文件中。记得引入jq。

    <!-- 是否登录显示在下面代码中 的 id = "isLogin" 的<div>中 -->
            <div class="w1240">
                 <div class="list">
                    <a>欢迎来到宝淘</a>
                    <a class="rt" href="/taobao">首页</a>
                 </div>
                 <div class="link" id = "isLogin">
                 </div>
                 <div class="clear"></div>
            </div>

    在 标签前加上js代码

    <!-- 获取用户登录数据,并在id = "isLogin" 的<div>中显示 -->
    <script>
        $(document).ready(function(){
            $.ajax({
                url: 'http://127.0.0.1:8000/api/user/',
                success: function (res) {
                    //接口返回的json 文件 结果在res中
                    console.log(res);
                    //判断用户是否登录。向 <div>中写入html
                    if(res['isLogin'] == true)
                        $(isLogin).html( '<a href="#">' + res['username'] + '</a> <a href="/logout" >退出</a> ');
                    else
                        $(isLogin).html('<a href="/login">登录</a> <a class="rt" href="/register">注册</a>');
                }
            })
        })
    </script>

    结果

    这里写图片描述
    这里写图片描述

    展开全文
  • 一、同步与异步的区别:  1、同步模式:后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的.  2、异步模式:则完全不同,每一个任务有一个或多个回调函数(callback)...
  • 异步WinHTTP

    千次阅读 2010-09-30 09:55:00
    由于分布式编程的发展,大多数基于 Windows®...异步处理需要缓冲大量的请求和响应、身份验证、自动代理服务器检测、持久连接等操作。此外,在 Windows Vista® 和 Windows Server® 2008 中,WinHTTP 支持上载大于 4G
  • 同步or异步

    2019-09-04 09:10:08
    微服务中除了同步,其实有时候会继承在异步的场景下,通过队列和订阅主题,实现消息的发布和订阅, 一个微服务可以是消息的发布者,把消息通过异步的方式,发送到队列和订阅主题下,作为消费者的微服务, 可以从队列或者...
  • 为解决异步函数的回调陷阱,开发社区不断摸索,终于折腾出 Promise/A+。它不增加新的语法,可以适配几乎所有浏览器;以队列的形式组织代码,易读好改;捕获异常方案也基本可用。这套方案在迭代中逐步完善,最终被...
  • httpclient和异步httpclient

    万次阅读 2016-08-11 13:35:41
    但是,让客户端来编写这么一段代码是不是有点过分,当然你愿意写也是可以的,其实apache又为我们提供了一个后面就是异步httpclient(其实这里所知的异步并非真正的异步IO模式),也就是将这部分包装了,对于访问者来...
  • nodejs爬虫抓取异步数据案例

    千次阅读 2017-07-22 00:15:27
    但是,如果数据是前端异步请求获取,再由js构造的节点,那么我们直接分析抓取到的网页是没有用的,即使我们在浏览器的开发者工具中能够看到对应的节点, 我们也无法获取到这部分异步刷新的节点,因为这是js构造的,...
  • MySQL 8 复制(一)——异步复制

    千次阅读 多人点赞 2019-05-10 18:25:10
    一、MySQL异步复制介绍 1. 复制的用途 2. 复制如何工作 3. 两阶段提交 二、复制实验环境 三、安装mysql-8.0.16 四、配置异步复制 1. 空库 2. 脱机 3. 联机 一、MySQL异步复制介绍 简单说,复制就是将...
  • 因为vue是组件级更新,如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以为了性能考虑,vue在本来数据更新后,再去异步更新视图。 第一步:通知watcher进行更新操作 第二步:依次调用...
  • AJAX异步请求 A: 异步Asynchronous J: JavaScript A: And X: XML 同步请求: 客户端请求到服务器,如果服务器没有响应,客户端只能等待,卡死 异步请求: 客户端请求到服务器,如果服务器没有响应,客户可是自由活动 ...
  • 原生Ajax,异步技术

    2020-11-02 16:51:59
    局部刷新的好处: 返回的数据是少了,可以减少带宽,减少网络资源的浪费。 服务处理方便了,也有利于性能。 请求响应的时间更快,利于用户体验。 结合异步刷新技术,在请求的过程中用户可以继续操作页面,有利于用户...
  • 异步提交form表单

    千次阅读 2019-05-23 11:00:00
    1.要使用ajaxSubmit方法,必须要加两个js文件,且顺序是: ...4.使用异步提交form表单的好处: 我觉得非常简便,轻巧,效率更高,可读性更好。 转载于:https://www.cnblogs.com/XueTing/p/10910676.html
  • ### 客户端使用AJAX实现异步访问 `Ajax`即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。 首先,应该引用`jQuery`文件,然后,调用`jQuery`框架中...
  • Angular异步调用 Promise和$q的用法 背景 首先说明一下promise异步调用出现的背景:javascript语言是一种单线程模式,就是说一次只能够执行一个任务,如果有多个任务的话就必须排队,后面的任务要等待前面的...
  • xamarin android异步更新UI线程

    万次阅读 2017-08-30 23:06:03
    android为了线程安全,不允许在UI线程外的子线程操作UI,这个结论不仅仅是说android,这个概念同样适用于其他的客户端系统,它 的好处时提高客户端UI的用户体验和执行效率(稍后解释),防止线程阻塞。在java 原生的...
  • 中,我们简单的讲解了爬虫时遇到登录问题的解决办法,在这篇文章中我们一起来聊一聊爬虫时遇到数据异步加载的问题,这也是爬虫中常见的问题。 现在很多都是前后端分离项目,这会使得数据异步加载问题更加突出,所以...
  • 经常在工作中用到异步请求的方法,最近的项目也用到了promise和fetch的知识,正好五一做下总结。 先说下同步和异步的区别,异步传输一般是面向字符的传输,它的单位是字符; 同步传输是面向比特的传输,它的单位是桢...
  • jQuery中借助deferred来请求及判断AJAX加载的实例讲解ajax请求异步队列加载我们在开发程序的时候通常会碰到使用ajax加载数据显示到列表的情况。ajax默认使用异步加载(async:true)。为什么不使用同步呢,因为ajax同步...
  • Android 使用httpclien异步加载

    千次阅读 2012-05-01 16:53:47
    但是,让客户端来编写这么一段代码是不是有点过分,当然你愿意写也是可以的,其实apache又为我们提供了一个后面就是异步httpclient(其实这里所知的异步并非真正的异步IO模式),也就是将这部分包装了,对于访问者来...
  • 基于mvc模式的jquery ajax异步请求

    千次阅读 2012-12-26 18:21:45
    在这边介绍在,net开发... 在jquery ajax中有好几种异步请求的方式有get 有post 还有发起带所有参数的Ajax请求,  在这边我介绍其中的一种$.ajax(options)方式,相信其他的方式在看完本文之后你也可以会使用。  $.
  • 第13章 异步JavaScript13.1 使用回调进行异步编程13.1.1 定时器13.1.2 事件13.1.3 网络事件13.1.4 Node中的回调和事件13.2 Promise13.2.1 使用PromisePromise处理错误13.2.2 Promise链13.2.3 解决Proimse13.2.4 ...
  • Netty 是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。 JDK 原生 NIO 程序的问题 JDK 原生也有一套网络应用程序 API,但是存在一系列问题,主要如下: NIO 的类库和 API ...
  • 分布式消息队列是是大型分布式系统不可缺少的中间件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。 对于一个架构师来说,在大型系统设计中,会经常需要面对同步和...
  • 如果把我们所做的UI做个简单分类,大致上可以分为列表界面和非列表界面。对于列表类UI,我们可以选择UITableView或者UICollectionView来实现。 ...UICollectionView出现之前,...同步和异步是基础的编程概念,
  • 异步工作流体系结构的选择 发布日期 : 4/1/2004 | 更新日期 : 4/1/2004 使用 Microsoft .NET 构建分布式应用程序 Duncan Mackenzie Microsoft Developer Network 2001 年 12 月 摘要:本文说明了异步...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,080
精华内容 7,632
关键字:

异步登录的好处