下面我们将实现关于Spring Security3的一系列教程. 
最终的目标是整合Spring Security + Spring3MVC 
完成类似于SpringSide3中mini-web的功能.

Spring Security是什么?

引用

Spring Security,这是一种基于Spring AOP和Servlet过滤器的安全框架。它提供全面的安全性解决方案,同时在Web请求级和方法调用级处理身份确认和授权。在Spring Framework基础上,Spring Security充分利用了依赖注入(DI,Dependency Injection)和面向切面技术。

关于Spring Security学习的资料. 
最重要,最齐全的中文资料当然是family168的中文文档 
Spring Security2参考文档

Spring Security3 参考文档

附件包含了一个很好的初入门的PDF教程. 
最好是花30分钟先照着PDF上的教程一步一步的操作. 
虽然没有实际的应用价值,但对初学者认识SpringSecurity3很有帮助.

我们的项目目录结构最终是:

需要添加的jar包:

我们先实现一个controller:

MainController.java

Java代码  

  1. package org.liukai.tutorial.controller;

  2. import org.apache.log4j.Logger;

  3. import org.springframework.stereotype.Controller;

  4. import org.springframework.web.bind.annotation.RequestMapping;

  5. import org.springframework.web.bind.annotation.RequestMethod;

  6. @Controller

  7. @RequestMapping("/main")

  8. public class MainController {

  9. protected static Logger logger = Logger.getLogger("controller");

  10. /**

  11. * 跳转到commonpage页面

  12. *

  13. * @return

  14. */

  15. @RequestMapping(value = "/common", method = RequestMethod.GET)

  16. public String getCommonPage() {

  17. logger.debug("Received request to show common page");

  18. return "commonpage";

  19. }

  20. /**

  21. * 跳转到adminpage页面

  22. *

  23. * @return

  24. */

  25. @RequestMapping(value = "/admin", method = RequestMethod.GET)

  26. public String getAadminPage() {

  27. logger.debug("Received request to show admin page");

  28. return "adminpage";

  29. }

  30. }

该controller有两个mapping映射:

引用

main/common 
main/admin

现在我们将同过Spring Security3框架实现成功登陆的人都能访问到main/common. 
但只有拥有admin权限的用户才能访问main/admin.

我们先在web.xml中开启Spring3MVC和SpringSecurity3.

web.xml

Xml代码  

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <web-app id="WebApp_ID" version="2.4"

  3. xmlns="http://java.sun.com/xml/ns/j2ee"

  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  5. xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

  6. http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  7. <!-- SpringSecurity必须的filter -->

  8. <filter>

  9. <filter-name>springSecurityFilterChain</filter-name>

  10. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

  11. </filter>

  12. <filter-mapping>

  13. <filter-name>springSecurityFilterChain</filter-name>

  14. <url-pattern>/*</url-pattern>

  15. </filter-mapping>

  16. <context-param>

  17. <param-name>contextConfigLocation</param-name>

  18. <param-value>

  19. /WEB-INF/spring-security.xml

  20. /WEB-INF/applicationContext.xml

  21. </param-value>

  22. </context-param>

  23. <servlet>

  24. <servlet-name>spring</servlet-name>

  25. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

  26. <load-on-startup>1</load-on-startup>

  27. </servlet>

  28. <servlet-mapping>

  29. <servlet-name>spring</servlet-name>

  30. <url-pattern>/</url-pattern>

  31. </servlet-mapping>

  32. <listener>

  33. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

  34. </listener>

  35. </web-app>

要启用SpringSecurity3,我们需要完成以下两步: 
1.在web.xml中声明DelegatingFilterProxy.

Xml代码  

  1. <filter-mapping>

  2. <filter-name>springSecurityFilterChain</filter-name>

  3. <url-pattern>/*</url-pattern>

  4. </filter-mapping>

表示项目中所有路径的资源都要经过SpringSecurity.

2.导入指定的SpringSecurity配置 :spring-security.xml

关于spring-security.xml的配置. 
我们把这个放到后面配置.以便更详细的讲解.

注意一点.最好是将DelegatingFilterProxy写在DispatcherServlet之前.否则 
SpringSecurity可能不会正常工作.

在web.xml中我们定义servlet:spring. 
按照惯例,我们必须声明一个spring-servle.xml 
spring-servle.xml 

Xml代码  

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans xmlns="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

  4. xsi:schemaLocation="http://www.springframework.org/schema/beans

  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  6. <!-- 定义一个视图解析器 -->

  7. <bean id="viewResolver"

  8. class="org.springframework.web.servlet.view.InternalResourceViewResolver"

  9. p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />

  10. </beans>

这个XML配置声明一个视图解析器.在控制器中会根据JSP名映射到/ WEB-INF/jsp中相应的位置.

然后创建一个applicationContext.xml.

applicationContext.xml. 

Xml代码  

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans xmlns="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xmlns:context="http://www.springframework.org/schema/context"

  5. xmlns:mvc="http://www.springframework.org/schema/mvc"

  6. xsi:schemaLocation="http://www.springframework.org/schema/beans

  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  8. http://www.springframework.org/schema/context

  9. http://www.springframework.org/schema/context/spring-context-3.0.xsd

  10. http://www.springframework.org/schema/mvc

  11. http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

  12. <!-- 激活spring的注解. -->

  13. <context:annotation-config />

  14. <!-- 扫描注解组件并且自动的注入spring beans中.

  15. 例如,他会扫描@Controller 和@Service下的文件.所以确保此base-package设置正确. -->

  16. <context:component-scan base-package="org.liukai.tutorial" />

  17. <!-- 配置注解驱动的Spring MVC Controller 的编程模型.注:次标签只在 Servlet MVC工作! -->

  18. <mvc:annotation-driven />

  19. </beans>

接着是创建JSP页面

commonpage.jsp

Jsp代码  

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  4. <html>

  5. <head>

  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

  7. <title>Insert title here</title>

  8. </head>

  9. <body>

  10. <h1>Common Page</h1>

  11. <p>每个人都能访问的页面.</p>

  12. <a href="/spring3-security-integration/main/admin"> Go AdminPage </a>

  13. <br />

  14. <a href="/spring3-security-integration/auth/login">退出登录</a>

  15. </body>

  16. </html>

adminpage.jsp

Jsp代码  

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  4. <html>

  5. <head>

  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

  7. <title>Insert title here</title>

  8. </head>

  9. <body>

  10. <h1>Admin Page</h1>

  11. <p>管理员页面</p>

  12. <a href="/spring3-security-integration/auth/login">退出登录</a>

  13. </body>

  14. </html>

这两个JSP对应着

当然还有登陆页面和拒绝访问页面

loginpage.jsp

Jsp代码  

  1. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

  2. <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>

  3. <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>

  4. <%@ page language="java" contentType="text/html; charset=UTF-8"

  5. pageEncoding="UTF-8"%>

  6. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  7. <html>

  8. <head>

  9. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

  10. <title>Insert title here</title>

  11. </head>

  12. <body>

  13. <h1>Login</h1>

  14. <div id="login-error">${error}</div>

  15. <form action="../j_spring_security_check" method="post">

  16. <p>

  17. <label for="j_username">Username</label> <input id="j_username"

  18. name="j_username" type="text" />

  19. </p>

  20. <p>

  21. <label for="j_password">Password</label> <input id="j_password"

  22. name="j_password" type="password" />

  23. </p>

  24. <input type="submit" value="Login" />

  25. </form>

  26. </body>

  27. </html>

deniedpage.jsp

Jsp代码  

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"

  2. pageEncoding="UTF-8"%>

  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

  4. <html>

  5. <head>

  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

  7. <title>Insert title here</title>

  8. </head>

  9. <body>

  10. <h1>你的权限不够!</h1>

  11. <p>只有拥有Admin权限才能访问!</p>

  12. <a href="/spring3-security-integration/auth/login">退出登录</a>

  13. </body>

  14. </html>

还有一个controller用于映射上面两个JSP页面.. 

LoginLogoutController.java

Java代码  

  1. package org.liukai.tutorial.controller;

  2. import org.apache.log4j.Logger;

  3. import org.springframework.stereotype.Controller;

  4. import org.springframework.ui.ModelMap;

  5. import org.springframework.web.bind.annotation.RequestMapping;

  6. import org.springframework.web.bind.annotation.RequestMethod;

  7. import org.springframework.web.bind.annotation.RequestParam;

  8. @Controller

  9. @RequestMapping("auth")

  10. public class LoginLogoutController {

  11. protected static Logger logger = Logger.getLogger("controller");

  12. /**

  13. * 指向登录页面

  14. */

  15. @RequestMapping(value = "/login", method = RequestMethod.GET)

  16. public String getLoginPage(

  17. @RequestParam(value = "error", required = false) boolean error,

  18. ModelMap model) {

  19. logger.debug("Received request to show login page");

  20. if (error == true) {

  21. // Assign an error message

  22. model.put("error",

  23. "You have entered an invalid username or password!");

  24. } else {

  25. model.put("error", "");

  26. }

  27. return "loginpage";

  28. }

  29. /**

  30. * 指定无访问额权限页面

  31. *

  32. * @return

  33. */

  34. @RequestMapping(value = "/denied", method = RequestMethod.GET)

  35. public String getDeniedPage() {

  36. logger.debug("Received request to show denied page");

  37. return "deniedpage";

  38. }

  39. }

该controller实现了两个映射

引用

auth/login     --显示Login页面 
auth/denied    --显示拒绝访问页面

最后,让我们看看spring-security.xml的配置

spring-security.xml

Xml代码  

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans xmlns="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xmlns:security="http://www.springframework.org/schema/security"

  5. xsi:schemaLocation="http://www.springframework.org/schema/beans

  6. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  7. http://www.springframework.org/schema/security

  8. http://www.springframework.org/schema/security/spring-security-3.0.xsd">

  9. <!--  Spring-Security 的配置 -->

  10. <!-- 注意开启use-expressions.表示开启表达式.

  11. see:http://www.family168.com/tutorial/springsecurity3/html/el-access.html

  12. -->

  13. <security:http auto-config="true" use-expressions="true" access-denied-page="/auth/denied" >

  14. <security:intercept-url pattern="/auth/login" access="permitAll"/>

  15. <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/>

  16. <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>

  17. <security:form-login

  18. login-page="/auth/login"

  19. authentication-failure-url="/auth/login?error=true"

  20. default-target-url="/main/common"/>

  21. <security:logout

  22. invalidate-session="true"

  23. logout-success-url="/auth/login"

  24. logout-url="/auth/logout"/>

  25. </security:http>

  26. <!-- 指定一个自定义的authentication-manager :customUserDetailsService -->

  27. <security:authentication-manager>

  28. <security:authentication-provider user-service-ref="customUserDetailsService">

  29. <security:password-encoder ref="passwordEncoder"/>

  30. </security:authentication-provider>

  31. </security:authentication-manager>

  32. <!-- 对密码进行MD5编码 -->

  33. <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

  34. <!--

  35. 通过 customUserDetailsService,Spring会自动的用户的访问级别.

  36. 也可以理解成:以后我们和数据库操作就是通过customUserDetailsService来进行关联.

  37. -->

  38. <bean id="customUserDetailsService" class="org.liukai.tutorial.service.CustomUserDetailsService"/>

  39. </beans>

在配置中我们可以看到三个URL对应的三个权限

Xml代码  

  1. <security:intercept-url pattern="/auth/login" access="permitAll"/>

  2. <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/>

  3. <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>

需要注意的是我们使用了SpringEL表达式来指定角色的访问. 
以下是表达式对应的用法.

引用

表达式 说明 
hasRole([role]) 返回 true 如果当前主体拥有特定角色。 
hasAnyRole([role1,role2]) 返回 true 如果当前主体拥有任何一个提供的角色 (使用逗号分隔的字符串队列) 
principal 允许直接访问主体对象,表示当前用户 
authentication 允许直接访问当前 Authentication对象 从SecurityContext中获得 
permitAll 一直返回true 
denyAll 一直返回false 
isAnonymous() 如果用户是一个匿名登录的用户 就会返回 true 
isRememberMe() 如果用户是通过remember-me 登录的用户 就会返回 true 
isAuthenticated() 如果用户不是匿名用户就会返回true 
isFullyAuthenticated() 如果用户不是通过匿名也不是通过remember-me登录的用户时, 就会返回true。

所以

Xml代码  

  1. <security:intercept-url pattern="/auth/login" access="permitAll"/>

表示所有的人都可以访问/auth/login.

Xml代码  

  1. <security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/>

  2. <security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>

则表示只有拥有对应的角色才能访问.

Xml代码  

  1. <security:form-login

  2. login-page="/auth/login"

  3. authentication-failure-url="/auth/login?error=true"

  4. default-target-url="/main/common"/>

表示通过 /auth/login这个映射进行登录. 
如果验证失败则返回一个URL:/auth/login?error=true 
如果登录成功则默认指向:/main/common

Xml代码  

  1. security:logout

  2. invalidate-session="true"

  3. logout-success-url="/auth/login"

  4. logout-url="/auth/logout"/>

很简单.我们开启了session失效功能. 
注销URL为:/auth/logout 
注销成功后转向:/auth/login

Xml代码  

  1. <!-- 指定一个自定义的authentication-manager :customUserDetailsService -->

  2. <security:authentication-manager>

  3. <security:authentication-provider user-service-ref="customUserDetailsService">

  4. <security:password-encoder ref="passwordEncoder"/>

  5. </security:authentication-provider>

  6. </security:authentication-manager>

  7. <!-- 对密码进行MD5编码 -->

  8. <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

  9. <!--

  10. 通过 customUserDetailsService,Spring会自动的用户的访问级别.

  11. 也可以理解成:以后我们和数据库操作就是通过customUserDetailsService来进行关联.

  12. -->

  13. <bean id="customUserDetailsService" class="org.liukai.tutorial.service.CustomUserDetailsService"/>

一个自定义的CustomUserDetailsService,是实现SpringSecurity的UserDetailsService接口,但我们重写了他即便于我们进行数据库操作.

DbUser.java

Java代码  

  1. package org.liukai.tutorial.domain;

  2. public class DbUser {

  3. private String username;

  4. private String password;

  5. private Integer access;

  6. //getter/setter

  7. }

通过一个初始化的List来模拟数据库操作.

UserDao.java

Java代码  

  1. package org.liukai.tutorial.dao;

  2. import java.util.ArrayList;

  3. import java.util.List;

  4. import org.apache.log4j.Logger;

  5. import org.liukai.tutorial.domain.DbUser;

  6. public class UserDao {

  7. protected static Logger logger = Logger.getLogger("dao");

  8. public DbUser getDatabase(String username) {

  9. List<DbUser> users = internalDatabase();

  10. for (DbUser dbUser : users) {

  11. if (dbUser.getUsername().equals(username) == true) {

  12. logger.debug("User found");

  13. return dbUser;

  14. }

  15. }

  16. logger.error("User does not exist!");

  17. throw new RuntimeException("User does not exist!");

  18. }

  19. /**

  20. * 初始化数据

  21. */

  22. private List<DbUser> internalDatabase() {

  23. List<DbUser> users = new ArrayList<DbUser>();

  24. DbUser user = null;

  25. user = new DbUser();

  26. user.setUsername("admin");

  27. // "admin"经过MD5加密后

  28. user.setPassword("21232f297a57a5a743894a0e4a801fc3");

  29. );

  30. users.add(user);

  31. user = new DbUser();

  32. user.setUsername("user");

  33. // "user"经过MD5加密后

  34. user.setPassword("ee11cbb19052e40b07aac0ca060c23ee");

  35. );

  36. users.add(user);

  37. return users;

  38. }

  39. }

自定义UserDetailsService .可以通过继承UserDetailsService 
来达到灵活的自定义UserDetailsService

关于UserDetailsService更多信息. 可以查看SpringSecurity3文档

CustomUserDetailsService.java

Java代码  

  1. package org.liukai.tutorial.service;

  2. import java.util.ArrayList;

  3. import java.util.Collection;

  4. import java.util.List;

  5. import org.apache.log4j.Logger;

  6. import org.liukai.tutorial.dao.UserDao;

  7. import org.liukai.tutorial.domain.DbUser;

  8. import org.springframework.dao.DataAccessException;

  9. import org.springframework.security.core.GrantedAuthority;

  10. import org.springframework.security.core.authority.GrantedAuthorityImpl;

  11. import org.springframework.security.core.userdetails.User;

  12. import org.springframework.security.core.userdetails.UserDetails;

  13. import org.springframework.security.core.userdetails.UserDetailsService;

  14. import org.springframework.security.core.userdetails.UsernameNotFoundException;

  15. /**

  16. * 一个自定义的service用来和数据库进行操作. 即以后我们要通过数据库保存权限.则需要我们继承UserDetailsService

  17. *

  18. * @author liukai

  19. *

  20. */

  21. public class CustomUserDetailsService implements UserDetailsService {

  22. protected static Logger logger = Logger.getLogger("service");

  23. private UserDao userDAO = new UserDao();

  24. public UserDetails loadUserByUsername(String username)

  25. throws UsernameNotFoundException, DataAccessException {

  26. UserDetails user = null;

  27. try {

  28. // 搜索数据库以匹配用户登录名.

  29. // 我们可以通过dao使用JDBC来访问数据库

  30. DbUser dbUser = userDAO.getDatabase(username);

  31. // Populate the Spring User object with details from the dbUser

  32. // Here we just pass the username, password, and access level

  33. // getAuthorities() will translate the access level to the correct

  34. // role type

  35. user = new User(dbUser.getUsername(), dbUser.getPassword()

  36. .toLowerCase(), true, true, true, true,

  37. getAuthorities(dbUser.getAccess()));

  38. } catch (Exception e) {

  39. logger.error("Error in retrieving user");

  40. throw new UsernameNotFoundException("Error in retrieving user");

  41. }

  42. return user;

  43. }

  44. /**

  45. * 获得访问角色权限

  46. *

  47. * @param access

  48. * @return

  49. */

  50. public Collection<GrantedAuthority> getAuthorities(Integer access) {

  51. );

  52. // 所有的用户默认拥有ROLE_USER权限

  53. logger.debug("Grant ROLE_USER to this user");

  54. authList.add(new GrantedAuthorityImpl("ROLE_USER"));

  55. // 如果参数access为1.则拥有ROLE_ADMIN权限

  56. ) == 0) {

  57. logger.debug("Grant ROLE_ADMIN to this user");

  58. authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));

  59. }

  60. return authList;

  61. }

  62. }

最后启动服务器输入: 
http://localhost:8080/spring3-security-integration/auth/login

总结 
通过本教程.我们对SpringSecurity3有了进一步的认识. 
主要是了解了UserDetailsService的重要作用. 
以及实现了模拟自定义数据的登录.(这点很重要,很多人学习了SpringSecurity却不知道 
如何自定义权限)

这次教程因为内容很多,显得比较粗糙.很多地方并没有详细的阐明. 
后面的教程还是SpringSecurity. 
但我们将对SpringSecurity3新推出的一些特性进行详细的说明和理解. 

BTW:附件为本次教程源码.你可以下载后直接在tomcat或其他web服务器启动.也可以自行添加 
maven插件启动.

spring 的权限控制:security的更多相关文章

  1. spring的权限控制,过滤器

    spring的过滤器可以实现登录状态问题 1.创建一个AccessFilter类,基础代码 package com.ujia.util.access; import javax.servlet.htt ...

  2. 自定义Spring Security权限控制管理(实战篇)

    上篇<话说Spring Security权限管理(源码)>介绍了Spring Security权限控制管理的源码及实现,然而某些情况下,它默认的实现并不能满足我们项目的实际需求,有时候需要 ...

  3. 权限控制框架Spring Security 和Shiro 的总结

    关于权限控制,一开始感觉比较难,后来先是接触了Spring Security 学起来也比较吃力,再是学习了Shiro,感觉简单很多. 总体来说这些框架,主要做了两个事情 Authentication: ...

  4. Spring Security(17)——基于方法的权限控制

    目录 1.1     intercept-methods定义方法权限控制 1.2     使用pointcut定义方法权限控制 1.3     使用注解定义方法权限控制 1.3.1    JSR-25 ...

  5. Spring Security(16)——基于表达式的权限控制

    目录 1.1      通过表达式控制URL权限 1.2      通过表达式控制方法权限 1.2.1     使用@PreAuthorize和@PostAuthorize进行访问控制 1.2.2   ...

  6. 基于spring security 实现前后端分离项目权限控制

    前后端分离的项目,前端有菜单(menu),后端有API(backendApi),一个menu对应的页面有N个API接口来支持,本文介绍如何基于spring security实现前后端的同步权限控制. ...

  7. Spring Security权限控制

    Spring Security官网 : https://projects.spring.io/spring-security/ Spring Security简介: Spring Security是一 ...

  8. spring security 3.1 实现权限控制

    spring security 3.1 实现权限控制 简单介绍:spring security 实现的权限控制,能够分别保护后台方法的管理,url连接訪问的控制,以及页面元素的权限控制等, secur ...

  9. request.getRemoteUser() Spring Security做权限控制后

    一. request.getRemoteUser();//获取当前缓存的用户,比如Spring Security做权限控制后就会将用户登录名缓存到这里 request.getRemoteAddr(); ...

随机推荐

  1. MySQL字符集乱码详解

    对于MySQL数据库中出现乱码经常是新手碰到的一个头痛的问题,不知道为什么经常出现中文乱码. 1.对于所谓的数据库中乱码,其实这中说法是错误的,只是我们不认识服务器给我们的字符.其实还是原来的字符?那 ...

  2. vue回顶部 组件 可以直接使用

    <template> <div id="goTop"> <div class="goTop" v-show="goTop ...

  3. 如何使用JavaScript导入和导出Excel文件

    本文由葡萄城技术团队于原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. JavaScript是一个涵盖多种框架.直译式.可以轻松自定义客户端的脚本 ...

  4. [apue] dup2的正确打开方式

    管道与重定向常常需要使用dup与dup2复制句柄,其中dup2又较为常用,但是使用dup2有几个小坑需要注意. int dup2(int oldfd, int newfd); man手册页上是这样讲的 ...

  5. UESTC 1324:卿学姐与公主(分块)

    http://acm.uestc.edu.cn/#/problem/show/1324 题意:…… 思路:卿学姐的学习分块例题. 分块是在线处理区间问题的类暴力算法,复杂度O(n*sqrt(n)),把 ...

  6. Intent对象(组件间的通信原理)

    Intent对象是一种可以在运行时动态绑定组件的关键技术,通过使用Intent对象,可以告诉系统你想要实现什么样的操作,也就是Intent对象里面包含的请求内容,请求再由Android操作系统接收到, ...

  7. Zimg—轻量级图片服务器搭建利器

    在一个互联网应用中,图片扮演着越来越重要的角色.有稳定的可扩展的图片存储服务器就显得尤为的重要,云厂商们提供了便利的图片存储服务,花钱就可以解决了.这里简单介绍一个开源的一个分布式图片存储服务器--z ...

  8. dubbo webservice 区别

    DUBBO中可以设置采用webservice方式,进行数据交互. 随着交互系统的增多,这种方式对系统的侵入性越来越大,关系更为错综复杂,很容易出错. 较适用与外围系统通信,若是内部系统间则会出现以上较 ...

  9. springboot项目快速搭建

    1. 问题描述 springboot的面世,成为Java开发者的一大福音,大大提升了开发的效率,其实springboot只是在maven的基础上,对已有的maven gav进行了封装而已,今天用最简单 ...

  10. [NOIP2013]华容道 题解(搜索)

    [NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...