spring实战----security4.1.3实现根据请求跳转不同登录页以及登录后根据权限跳转到不同页配置(代码片段)

Herman-Hong Herman-Hong     2022-11-29     209

关键词:

一、背景介绍

上一篇最后总结说了:

1)被认证请求被FilterSecurityInterceptor拦截看有没有对应权限,如果没有抛异常给ExceptionTranslationFilter 2)ExceptionTranslationFilter缓存原请求,利用LoginUrlAuthenticationEntryPoint入口跳转到登录界面 3)用户在登录界面填写登录信息后,提交,经过UsernamePasswordAuthenticationFilter对填写的信息和从数据源中获取的信息进行对比,成功则授权权限,并通过登录成功后入口SavedRequestAwareAuthenticationSuccessHandler跳转回原请求页面(跳转时有从缓存中对请求信息的恢复) 4)登录完成后返回原请求,由FilterSecurityInterceptor进行权限的验证(大部分工作有AbstractSecurityInterceptor来做),根据登录成功后生成的Authentication(Authentication authentication = SecurityContextHolder.getContext().getAuthentication();由SecurityContextHolder持有,而其中的SecurityContext由 SecurityContextPersistentFilter保存到session中从而实现request共享 )中的权限和请求所需的权限对比,如果一致则成功执行,如果权限不正确则返回403错误码 5)以上均是默认情况下,没有经过配置的执行过程,当然可以自定义LoginUrlAuthenticationEntryPoint和SavedRequestAwareAuthenticationSuccessHandler实现根据不同的请求所需权限跳转到不同登录页面及授权成功后根据权限跳转到不同页面,以及返回403错误码时跳转到对应的页面(AccessDeniedHandlerImpl)在下一篇中会对其进行实现


那么这里要实现题目中说的(登录后根据权限跳转到不同页是指直接点击登录的情况,如果是有原请求跳转过来的,登录成功并且认证成功后跳转到原请求页),需要如下操作

1)自定义LoginUrlAuthenticationEntryPoint实现跳转到不同登录页,如用户订单请求跳转到用户登录页,管理中心请求跳转到管理员登录页

2)自定义SavedRequestAwareAuthenticationSuccessHandler实现直接点击登录成功后跳转到指定的页,如用户登录后跳转到首页,管理员登陆后跳转到管理中心

3)此问题涉及了两种权限的用户登录,ROLE_USER及ROLE_MANAGER,还需要配置AccessDeniedHandlerImpl来处理虽然登录成功了确没有权限访问的情况。

4)还需要自定义SimpleUrlAuthenticationFailureHandler来实现登录失败的情况,主要是用户不存在或密码错误问题。这种情况下能够实现从哪个登录页面过来的还是返回原登录页,并携带错误信息

5)还需要配置login-processing-url属性,能够拦截/manager/login和/login提交,从而经过UsernamePasswordAuthenticationFilter时对其进行登录验证(requiresAuthentication(request, response)判断)

下面对其一一说明

二、全部配置如下:

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

<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/security
		http://www.springframework.org/schema/security/spring-security.xsd">
		
	<http auto-config="true" use-expressions="true" entry-point-ref="myAuthenticationEntryPoint" >
		<form-login 
			login-page="/login"
            login-processing-url="/**/login"
            authentication-failure-handler-ref="myAuthenticationFailureHandler"
            authentication-success-handler-ref="myAuthenticationSuccessHandler" />   
         <!-- 认证成功用自定义类myAuthenticationSuccessHandler处理 -->
         
         <logout logout-url="/logout" 
				logout-success-url="/" 
				invalidate-session="true"
				delete-cookies="JSESSIONID"/>
		
		<!-- 登录成功后拒绝访问跳转的页面 -->		
		<access-denied-handler error-page="/security/deny" />
		
		<csrf disabled="true" />
		<intercept-url pattern="/order/*" access="hasRole('ROLE_USER')"/>
		<intercept-url pattern="/manager" access="hasRole('ROLE_MANAGER')"/>
	</http>
	
	<!-- 使用自定义类myUserDetailsService从数据库获取用户信息 -->
	<authentication-manager>  
        <authentication-provider user-service-ref="myUserDetailsService">  
        	<!-- 加密 -->
            <password-encoder hash="md5">
            </password-encoder>
        </authentication-provider>
    </authentication-manager>
    
    <!-- 被认证请求根据所需权限跳转到不同的登录界面 -->
    <beans:bean id="myAuthenticationEntryPoint" 
    	class="com.mango.jtt.springSecurity.MyAuthenticationEntryPoint">
    	<beans:property name="authEntryPointMap" ref="loginFormsMap"></beans:property>
    	<beans:constructor-arg name="loginFormUrl" value="/login"></beans:constructor-arg>
    </beans:bean>
    
    <!-- 根据不同请求所需权限跳转到不同的登录界面 -->
	<beans:bean id="loginFormsMap" class="java.util.HashMap">
		<beans:constructor-arg>
			<beans:map>
				<beans:entry key="/user/**" value="/login" />
				<beans:entry key="/manager/**" value="/manager/login" />
				<beans:entry key="/**" value="/login" />
			</beans:map>
		</beans:constructor-arg>
	</beans:bean>
	
	<!-- 登录且授权成功后控制 -->
    <beans:bean id="myAuthenticationSuccessHandler" 
    	class="com.mango.jtt.springSecurity.MyAuthenticationSuccessHandler">
    	<beans:property name="authDispatcherMap" ref="dispatcherMap"></beans:property>
    </beans:bean>
	
	<!-- 根据不同的权限,跳转到不同的页面(直接点击登录页面用) -->
	<beans:bean id="dispatcherMap" class="java.util.HashMap">
	  	<beans:constructor-arg>
		    <beans:map>
				<beans:entry key="ROLE_USER" value="/"/>
				<beans:entry key="ROLE_MANAGER" value="/manager"/>
	      	</beans:map>
	  	</beans:constructor-arg>
	</beans:bean>
	
	<!-- 登录失败后控制 -->
    <beans:bean id="myAuthenticationFailureHandler" 
    	class="com.mango.jtt.springSecurity.MyAuthenticationFailureHandler">
    	<beans:property name="loginEntry" ref="myAuthenticationEntryPoint"></beans:property>
    </beans:bean>
</beans:beans>

三、MyAuthenticationEntryPoint配置

 <!-- 被认证请求根据所需权限跳转到不同的登录界面 -->
    <beans:bean id="myAuthenticationEntryPoint" 
    	class="com.mango.jtt.springSecurity.MyAuthenticationEntryPoint">
    	<beans:property name="authEntryPointMap" ref="loginFormsMap"></beans:property>
    	<beans:constructor-arg name="loginFormUrl" value="/login"></beans:constructor-arg>
    </beans:bean>
    
    <!-- 根据不同请求所需权限跳转到不同的登录界面 -->
	<beans:bean id="loginFormsMap" class="java.util.HashMap">
		<beans:constructor-arg>
			<beans:map>
				<beans:entry key="/user/**" value="/login" />
				<beans:entry key="/manager/**" value="/manager/login" />
				<beans:entry key="/**" value="/login" />
			</beans:map>
		</beans:constructor-arg>
	</beans:bean>


根据请求路径跳转到不同的登录页面(其他实现方式也可),其中key是匹配的路径,value是要跳转的登录页,关键代码如下:

/**
 * 被认证请求向登录页面跳转的控制 根据被请求所需权限向不同登录页面跳转
 * 
 * @author HHL
 * 
 * @date 2016年12月20日
 */
public class MyAuthenticationEntryPoint extends
		LoginUrlAuthenticationEntryPoint 

	public MyAuthenticationEntryPoint(String loginFormUrl) 
		super(loginFormUrl);
	

	private Map<String, String> authEntryPointMap;
	private PathMatcher pathMatcher = new AntPathMatcher();

	@Override
	protected String determineUrlToUseForThisRequest(
			HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) 
		String requestURI = request.getRequestURI().replace(
				request.getContextPath(), "");
		for (String url : this.authEntryPointMap.keySet()) 
			if (this.pathMatcher.match(url, requestURI)) 
				return this.authEntryPointMap.get(url);
			
		
		return super.determineUrlToUseForThisRequest(request, response,
				exception);
	


	public PathMatcher getPathMatcher() 
		return pathMatcher;
	

	public void setPathMatcher(PathMatcher pathMatcher) 
		this.pathMatcher = pathMatcher;
	


	public Map<String, String> getAuthEntryPointMap() 
		return authEntryPointMap;
	

	public void setAuthEntryPointMap(Map<String, String> authEntryPointMap) 
		this.authEntryPointMap = authEntryPointMap;
	

该类重写了父类的determineUrlToUseForThisRequest,实现了根据请求路径返回不同的登录页路径,从而在父类的commence方法中跳转到根据请求路径返回的登录页。其中spring的AntPathMatcher类及AntPathRequestMatcher可以实现路径的匹配工作。

这里实现了"/user/**"相关的路径跳转到用户登录页面"/login","/manager/**"相关的页面跳转到管理员登录页面"/manager/login",上面两者没有匹配的"/**",均跳转到用户登录页面"/login"。当然上述的前提条件是请求路径需要权限,也就是有如下配置:

<intercept-url pattern="/order/**" access="hasRole('ROLE_USER')"/>
		<intercept-url pattern="/manager" access="hasRole('ROLE_MANAGER')"/>
否则,不需要权限的请求,也不需要跳转到登录页


四、myAuthenticationSuccessHandler配置

主要配置

<!-- 授权成功后控制 -->
    <beans:bean id="myAuthenticationSuccessHandler" 
    	class="com.mango.jtt.springSecurity.MyAuthenticationSuccessHandler">
    	<beans:property name="authDispatcherMap" ref="dispatcherMap"></beans:property>
    </beans:bean>
	
	<!-- 根据不同的权限,跳转到不同的页面(直接点击登录页面用) -->
	<beans:bean id="dispatcherMap" class="java.util.HashMap">
	  	<beans:constructor-arg>
		    <beans:map>
				<beans:entry key="ROLE_USER" value="/"/>
				<beans:entry key="ROLE_MANAGER" value="/manager"/>
	      	</beans:map>
	  	</beans:constructor-arg>
	</beans:bean>

其中map中的key为登录后的用户权限,value代表要直接点击登录的情况下登录成功后要跳转的页面,关键代码处理

/**
 * 登录授权成功后操作控制,如果是直接点击登录的情况下,根据授权权限跳转不同页面; 否则跳转到原请求页面
 * 
 * @author HHL
 * @date
 * 
 */
public class MyAuthenticationSuccessHandler extends
		SavedRequestAwareAuthenticationSuccessHandler 
	private Map<String, String> authDispatcherMap;
	private RequestCache requestCache = new HttpSessionRequestCache();

	@Autowired
	private IUserService userService;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException 
		// 获取用户权限
		Collection<? extends GrantedAuthority> authCollection = authentication
				.getAuthorities();
		if (authCollection.isEmpty()) 
			return;
		

		// 认证成功后,获取用户信息并添加到session中
		UserDetails userDetails = (UserDetails) authentication.getPrincipal();
		MangoUser user = userService.getUserByName(userDetails.getUsername());
		request.getSession().setAttribute("user", user);
		
		String url = null;
		// 从别的请求页面跳转过来的情况,savedRequest不为空
		SavedRequest savedRequest = requestCache.getRequest(request, response);
		if (savedRequest != null) 
			url = savedRequest.getRedirectUrl();
		

		// 直接点击登录页面,根据登录用户的权限跳转到不同的页面
		if (url == null) 
			for (GrantedAuthority auth : authCollection) 
				url = authDispatcherMap.get(auth.getAuthority());
			
			getRedirectStrategy().sendRedirect(request, response, url);
		

		super.onAuthenticationSuccess(request, response, authentication);
	
	


	public RequestCache getRequestCache() 
		return requestCache;
	

	public void setRequestCache(RequestCache requestCache) 
		this.requestCache = requestCache;
	


	public Map<String, String> getAuthDispatcherMap() 
		return authDispatcherMap;
	

	public void setAuthDispatcherMap(Map<String, String> authDispatcherMap) 
		this.authDispatcherMap = authDispatcherMap;
	

其中用从requestCache中获取到的savedRequest来判断是否是直接点击登录还是从其他页面跳转过来的,上一篇也说过从savedRequest获取实质上是从session中获取,因此这里的requestCache实例可以为任一实例。

这里就实现了如果是直接点击登录的成功后,用户登录的跳转到首页"/",管理员登录的就跳转到管理中心“/manager”;如果是从其他请求页过来的还是返回原请求页面。

五、myAuthenticationFailureHandler

登录失败后,没有用户或者密码错误的情况下,主要配置

<!-- 登录失败后控制 -->
    <beans:bean id="myAuthenticationFailureHandler" 
    	class="com.mango.jtt.springSecurity.MyAuthenticationFailureHandler">
    	<beans:property name="loginEntry" ref="myAuthenticationEntryPoint"></beans:property>
    </beans:bean>


其中依赖了myAuthenticationEntryPoint,就是要根据登录路径,返回到原登录页面,并携带错误信息,这里就需要管理登录的form action设置不同

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<%@ include file="../../includes/taglibs.jsp"%>
<!DOCTYPE html>
<html>
<head>
    <title>Mango-managerLogin</title>
	<meta name="menu" content="home" />    
</head>

<body>

<h1>请管理员登录!</h1>

<div style="text-align:center">
	<form action="<c:url value='/manager/login' />" method="post">
		<c:if test="$not empty error">
			<p style="color:red">$error</p>
		</c:if>
      <table>
         <tr>
            <td>用户名:</td>
            <td><input type="text" name="username"/></td>
         </tr>
         <tr>
            <td>密码:</td>
            <td><input type="password" name="password"/></td>
         </tr>
         <tr>
            <td colspan="2" align="center">
                <input type="submit" value="登录"/>
                <input type="reset" value="重置"/>
            </td>
         </tr>
      </table>
   </form>
</div>

</body>
</html>


其中action是/manager/login,和用户登录页中的/login是区分开的,这样利用myAuthenticationEntryPoint就可以根据路径返回到对应的登录界面,关键代码:

/**
 * 登录失败控制
 * 
 * @author HHL
 * 
 * @date 2016年12月20日
 */
public class MyAuthenticationFailureHandler extends
		SimpleUrlAuthenticationFailureHandler 
	private MyAuthenticationEntryPoint loginEntry;

	public MyAuthenticationEntryPoint getLoginEntry() 
		return loginEntry;
	

	public void setLoginEntry(MyAuthenticationEntryPoint loginEntry) 
		this.loginEntry = loginEntry;
	

	@Override
	public void onAuthenticationFailure(HttpServletRequest request,
			HttpServletResponse response, AuthenticationException exception)
			throws IOException, ServletException 
		// 从loginEntry中获取登录失败要跳转的url,并加上错误信息error
		String authenfailureUrl = this.loginEntry
				.determineUrlToUseForThisRequest(request, response, exception);
		authenfailureUrl = authenfailureUrl + "?error";
		super.setDefaultFailureUrl(authenfailureUrl);
		super.onAuthenticationFailure(request, response, exception);

	

该类覆盖了父类的onAuthenticationFailure,根据请求路径,如果是“/manager/login”就和MyAuthenticationEntryPoint中的“/manager/**”相匹配,返回路径为“/manager/login”‘;“/login”的情况也类似,返回到“/login”;然后添加上?error,并设置到父类的setDefaultFailureUrl,由父类的onAuthenticationFailure执行跳转。

当然contoller中要如下配置:

/**
 * @author HHL
 * 
 * 
 *         管理员控制类
 */
@Controller
public class ManagerController 

	/**
	 * 管理中心首页
	 * 
	 * @param model
	 * @return
	 */
	@RequestMapping("/manager")
	public String login(Model model) 
		return "manager/index";
	
	
	/**
	 * 显示登录页面用,主要是显示错误信息
	 * 
	 * @param model
	 * @param error
	 * @return
	 */
	@RequestMapping("/manager/login")
	public String login(Model model,
			@RequestParam(value = "error", required = false) String error) 
		if (error != null) 
			model.addAttribute("error", "用户名或密码错误");
		
		return "manager/login";
	

如果登录失败则error为"",满足不为null的条件


六、login-processing-url配置

既然两个登录页中的form action不同,那么login-processing-url配置对两者均要进行拦截:

login-processing-url="/**/login"

这里的"/**/login"对"/manager/login"和"/login"均能实现拦截,由UsernamePasswordAuthenticationFilter进行拦截,match部分是由Spring中的AntPathRequestMatcher实现的。

工作在父类AbstractAuthenticationProcessingFilter的requiresAuthentication方法

/**
	 * Indicates whether this filter should attempt to process a login request for the
	 * current invocation.
	 * <p>
	 * It strips any parameters from the "path" section of the request URL (such as the
	 * jsessionid parameter in <em>http://host/myapp/index.html;jsessionid=blah</em>)
	 * before matching against the <code>filterProcessesUrl</code> property.
	 * <p>
	 * Subclasses may override for special requirements, such as Tapestry integration.
	 *
	 * @return <code>true</code> if the filter should attempt authentication,
	 * <code>false</code> otherwise.
	 */
	protected boolean requiresAuthentication(HttpServletRequest request,
			HttpServletResponse response) 
		return requiresAuthenticationRequestMatcher.matches(request);
	

可见UsernamePasswordAuthenticationFilter完成了用户的登录工作(用户是否存在,密码是否正确,和数据源只能的用户信息对比)


七、access-denied-handler

访问拒绝,该配置中有两种用户权限'ROLE_USER'和'ROLE_MANAGER',当用户登录时具有'ROLE_USER'权限,当管理员登录时具有'ROLE_MANAGER'权限;因此当用户登录的情况下访问管理中心,这个时候权限就不充分,Security系统会抛403错误,拒绝访问,那么这里就需要配置错误页,根据access-denied-handler标签就可以配置

<!-- 登录成功后拒绝访问跳转的页面 -->		
		<access-denied-handler error-page="/security/deny" />


路径为"/security/deny"

/**
 * security控制类
 * 
 * @author HHL
 * 
 * @date 2016年12月20日
 */
@Controller
public class SecurityController 

	/**
	 * 拒绝访问时跳转页面
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping("/security/deny")
	public String deny(HttpServletRequest request,HttpServletResponse response)
		return "security_deny";
	

页面为security_deny.jsp

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<%@ include file="../includes/taglibs.jsp"%>
<!DOCTYPE html>
<html>
<head>
    <title>Mango-deny</title>
	<meta name="menu" content="home" />    
</head>
<body>
<h1>对不起,您没有权限访问该页面!</h1>
       
<div style="text-align:center">
	<img src="<c:url value='/resources/images/nonono.jpg'/>"/>
	<p>
		<a href="<c:url value='/'/>">首页</a>
		<a href="<c:url value='/manager'/>">管理中心</a>
		<a href="<c:url value='/logout'/>" >退出登录</a>
	</p>
</div>
</body>
</html>


效果如下:




完整代码如下:https://github.com/honghailiang/SpringMango



 

spring实战----security4.1.3认证的过程以及原请求信息的缓存及恢复(requestcache)(代码片段)

一、先看下认证过程认证过程分为7步:1.用户访问网站,打开了一个链接(originurl)。2.请求发送给服务器,服务器判断用户请求了受保护的资源。3.由于用户没有登录,服务器重定向到登录页面4.填写表单,点击登录5... 查看详情

spring实战----security4.1.3实现根据请求跳转不同登录页以及登录后根据权限跳转到不同页配置(代码片段)

一、背景介绍上一篇最后总结说了:1)被认证请求被FilterSecurityInterceptor拦截看有没有对应权限,如果没有抛异常给ExceptionTranslationFilter2)ExceptionTranslationFilter缓存原请求,利用LoginUrlAuthenticationEntryPoint入口跳 查看详情

spring实战----开篇(包含系列目录链接)

终于还是要对Spring进行解剖,接下来Spring实战篇系列会以应用了Spring技术的JavaWeb的应用mango为例,来分析Spring各个模块的技术,包括源码解析等,谨以此记!!! 【Spring实战】----开发环境配置【Spring... 查看详情

spring实战笔记:spring核心

springcore一.简介: 1.依赖注入(DI)   优点:解耦   Spring通过应用上下文(ApplicationContext)装载bean的定义,并把它们组装起来。   Spring应用上下文负责对象的创建和组装。    &n... 查看详情

spring实战

Spring的两个核心特性:依赖注入(DI)和面向切面编程(AOP) 为了降低Java开发的复杂性,Spring采取了以下4种关键策略:  基于POJO的轻量级和最小侵入性编程  通过依赖注入和面向接口实现松耦合  基于切面和惯例进行声明... 查看详情

spring4.1.8扩展实战之四:感知spring容器变化(smartlifecycle接口)(代码片段)

欢迎访问我的GitHub本篇概览本章是《spring4.1.8扩展实战》的第四篇,如果业务上需要在spring容器启动和关闭的时候做一些操作,可以自定义SmartLifecycle接口的实现类来扩展,本章我们通过先分析再实战的方法,来掌握这种扩展方... 查看详情

spring实战笔记:spring集成

...是客户端应用和服务端之间的会话。    1.Spring通过多种远程调用技术支持RPC(remoteprocedurecall,远程过程调用)RPC模型使用场景RMI不考虑网络限制时(例如防火墙),访问/发布基于Java的服务Hessian或Burlap考虑网络限... 查看详情

[dubbo实战]dubbo+zookeeper+spring实战(转)

     这里最熟悉的就是spring了,项目中应用很多。dubbo是一个实现分布式的框架,zookeeper是注册中心。给我的感觉就像多对多关系的两者表,zookeeper相当于第三张表维护关系。下面通过一个小程序加深认识。一... 查看详情

《spring实战(第三版)》之旅

...糊。  反正经过这五大框架的学习,感觉最重要的还是Spring框架,于是乎,开学时期偶得一书《Spring实战》,在网上口碑还是蛮高的,于是继续深入学习(复习)下Spring这个框架。  到目前为止已经读到了第8章使用SpringWebFl... 查看详情

spring实战入门,带你轻松掌握spring框架

Spring框架是什么?Spring是于2003年兴起的一个轻量级的Java开发框架,它是为了解决企业应用开发的复杂性而创建的。Spring的核心是控制反转(IoC)和面向切面编程(AOP)。Spring是可以在JavaSE/EE中使用的轻量级开源框架。Spring的主... 查看详情

spring4实战学习笔记

《Spring4实战第4版》2016年4月新出版的,之前的第三版看起来还是不错的,所以看到新版就直接买下来。英文版源码地址:SpringinAction,FourthEditionCoversSpring4 1.IOC装配Bean参考【Spring实战4 2.2】,作者提倡无XML配置化... 查看详情

spring实战笔记二

一、Spring配置的方式    spring容器用来创建应用程序中的bean,并通过DI来协调这些对象间的关系。    在bean进行装配时,spring提供了三种主要的装配机制。      ①在XML中进行显式配置      ②在Java中进... 查看详情

spring实战-手动创建spring项目结构

环境:MacOS+IntelliJIDEA2019.3.1(UltimateEdition)1、创建存放项目的文件夹2、创建pom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:x 查看详情

spring实战--1spring的核心

  最近面试总会涉及Spring的优点,SpringMVC与Struts2的比较,生活慢慢稳定下来,这些面试还是应了那句话“只顾盲目拉车,不会低头看路”,回过头来还是要好好研究一下Spring,如果仅仅是停留在粘贴拷贝像从前一样机械... 查看详情

spring07_纯注解实战及spring整合junit

本教程源码请访问:tutorial_demo在《Spring04_IOC和DI实战》当中,我们使用XML配置的方式结合ApacheCommonsDbUtils实现单表的CRUD操作,这篇教程我们使用纯注解方式结合ApacheCommonsDbUtils实现单表的CRUD操作。一、需求和技术要求1.1、需求实... 查看详情

spring实战笔记:web中的spring

一.构建SpringWeb应用1.SpringMVC中用户请求处理  上图展示了请求使用SpringMVC所经历的所有站点。  1:在请求离开浏览器时,会带有所有请求内容的信息,至少会包含请求的URL。     请求通过Spring的Di... 查看详情

spring实战-第二章-装配bean

Bean是Spring对象的声明(装配wiring),要使用Spring,必须先装配需要使用的对象,有3种装配的方式自动化装配Bean通过Java代码装配通过XML装配自动化装配Bean自动化装配Bean很简单1.声明接口packagesoundsystem;publicinterfaceCompactDisc{voidplay(... 查看详情

spring实战spring注解配置工作原理源码解析(代码片段)

一、背景知识在【Spring实战】Spring容器初始化完成后执行初始化数据方法一文中说要分析其实现原理,于是就从源码中寻找答案,看源码容易跑偏,因此应当有个主线,或者带着问题、目标去看,这样才能最... 查看详情