由于急需这方面的知识,所以暂时先囫囵吞枣,记下来,有时间再来分享自己的感想,这里先转载下:
关于spring mvc 浅解!
刚接触spring mvc!看了看内部流程。浅浅的记一下。
当url为“person.do?do=toEditPage”时程序的走向:
1,程序会根据后面的person.do后面的do转入spring的控制器
<servlet>
<servlet-name> appfuse</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name> appfuse</servlet-name>
<url-pattern>*.do</url-pattern> //处理以什么方式结尾的动作
</servlet-mapping>
2,根据appfuse 找到 appfuse-servlel.xml 。这个是spring mvc非常重要的配置文件。注明了每一次跳转动作进入的控制器,注入相应的dao层,业务层,以及commond层
程序会根据/person.do 找到相应的控制器:com.nbw.test.web.action.PersonController。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/> //这个是跳转页面的路径
<property name="suffix" value=".jsp"/> //指定跳转路径下以什么结尾的文件
</bean>
<bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver" id="paramResolver">
<property name="paramName" value="do"/> //这个在指定当控制器有多方法的时候,使用什么样的参数名来获得方法 例如:person.do?do=toEditPage
</bean>
//下面当url为person.do的时候请求进入PersonController控制器。
<bean class="com.nbw.test.web.action.PersonController" name="/person.do">
<property name="methodNameResolver">
<ref bean="paramResolver"/> //这是当控制器需要实现多个方法的时候,指定使用哪个方法名,引用上面
</property>
<property name="sessionForm"> //是否把form放入session,如果选true,会将form存入session,当再次实例form的时候会根据名字从session取,如果选false则会重新新建一个
<value>false</value>
</property>
<property name="commandClass"> //使用哪个command存储页面传过来的参数
<value>com.nbw.test.domain.Person</value>
</property>
</bean>
3,进入com.nbw.test.web.action.PersonController控制器。PersonController
extends AbstractMultiActionFormController extends
AbstractFormController extends BaseCommandController
这几个类是spring的核心类,他们会根据appfuse-servlel.xml 里面的配置信息,处理相应的参数,验证以及返回到哪个页面!
程序会进入AbstractFormController类的handleRequestInternal方法。
/**
* Handles two cases: form submissions and showing a new form.
* Delegates the decision between the two to {@link
#isFormSubmission},
* always treating requests without existing form session attribute
* as new form when using session form mode.
* @see #isFormSubmission
* @see #showNewForm
* @see #processFormSubmission
*/
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// Form submission or new form to show?
//这里会判断是不是post请求如果是就进行判断,如果不是就新建一个
if (isFormSubmission(request)) {
// Fetch form object from HTTP session, bind, validate, process submission.
try {
//
开始绑定参数,程序会根据appfuse-servlel.xml 指定的
sessionform为ture或者false来决定是从session里面去还是新建一个实例,如果为false进入
formBackingObject
方法,然后程序会调用createCommand方法,在createCommand方法spring会使用
BeanUtils.instantiateClass(this.commandClass)来将参数注入form
Object command = getCommand(request);
ServletRequestDataBinder binder = bindAndValidate(request, command);
BindException errors = new BindException(binder.getBindingResult());
//因为spring不支持 属性为日期型的转换 需要改写这个方法
//this.convertStringToDate(request, command);
//在这个方法里程序会根据?do=toEditPage的toEditPage,方法使用反射调用这个方法
return processFormSubmission(request, response, command, errors);
}
catch (HttpSessionRequiredException ex) {
// Cannot submit a session form if no form object is in the session.
if (logger.isDebugEnabled()) {
logger.debug("Invalid submit detected: " + ex.getMessage());
}
return handleInvalidSubmit(request, response);
}
}
else {
// New form to show: render form view.
return showNewForm(request, response);
}
}
/**
* Return the form object for the given request.
* <p>Calls {@link
#formBackingObject} if not in session form mode.
* Else, retrieves the form object from the session. Note that the form object
* gets removed from the session, but it will be re-added when showing the
* form for resubmission.
* @param request current HTTP request
* @return object form to bind onto
* @throws org.springframework.web.HttpSessionRequiredException
* if a session was expected but no active session (or session form object) found
* @throws Exception in case of invalid state or arguments
* @see #formBackingObject
*/
protected final Object getCommand(HttpServletRequest request) throws Exception {
// If not in session-form mode, create a new form-backing object.
//假如不从session里取
if (!isSessionForm()) {
return formBackingObject(request);
}
// Session-form mode: retrieve form object from HTTP session attribute.
HttpSession session = request.getSession(false);
if (session == null) {
throw new HttpSessionRequiredException("Must have session when trying to bind (in session-form mode)");
}
String formAttrName = getFormSessionAttributeName(request);
Object sessionFormObject = session.getAttribute(formAttrName);
if (sessionFormObject == null) {
throw new HttpSessionRequiredException("Form object not found in session (in session-form mode)");
}
// Remove form object from HTTP session: we might finish the form workflow
// in this request. If it turns out that we need to show the form view again,
// we'll re-bind the form object to the HTTP session.
if (logger.isDebugEnabled()) {
logger.debug("Removing form session attribute [" + formAttrName + "]");
}
session.removeAttribute(formAttrName);
return currentFormObject(request, sessionFormObject);
}
protected final Object createCommand() throws Exception {
if (this.commandClass == null) {
throw new IllegalStateException( "Cannot create command without commandClass being set - " +
"either set commandClass or (in a form controller) override formBackingObject ");
}
if (logger.isDebugEnabled()) {
logger.debug( "Creating new command of class [ " + this.commandClass.getName() + "] ");
}
return BeanUtils.instantiateClass(this.commandClass);//就这里!!!
}
//利用反射机制调用控制器里的方法
protected ModelAndView processFormSubmission(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception
{
if (errors.hasErrors()) {
if (logger.isDebugEnabled()) {
logger.debug("Data binding errors: " + errors.getErrorCount());
}
return showForm(request, response, errors);
} else {
String methodName = methodNameResolver.getHandlerMethodName(request);
Method method = null;
Method[] methods = this.getClass().getMethods();
for(int i = 0; i <methods.length ; i++){
if(methods[i].getName().equals(methodName)){
method = methods[i];
}
}
//java
//Class dd= (Class<T>)((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
//method = getClass().getMethod(methodName,new
Class[]{HttpServletRequest.class, HttpServletResponse.class,
(Class<T>)((ParameterizedType)
getClass().getGenericSuperclass()).getActualTypeArguments()[0],
BindException.class});
// method = getClass().getMethod(methodName,new
Class[]{HttpServletRequest.class, HttpServletResponse.class,
getCommandClass(), BindException.class});
List params = new ArrayList(4);
params.add(request);
params.add(response);
//Java 5.0
params.add(getCommandClass().cast(command));
//Java 1.4
//params.add(command);
params.add(errors);
try{
return (ModelAndView) method.invoke(this, params.toArray(new Object[params.size()]));
}
catch (InvocationTargetException e){
//找到实际的异常,并抛出
throw (Exception)e.getTargetException();
}
catch(Exception e){
throw e;
}
}
}
//然后调用 PersonController类的toEditPage方法command已经设置好
//new ModelAndView("test/personEdit","person",command);这个会根据在appfuse-servlel.xml 文件里面的
//<property name="prefix" value="/WEB-INF/jsp/"/>获得路径 /web-inf/jsp/text/
//再根据<property name="suffix" value=".jsp"/>得到返回文件后缀名personEdit.jsp
//所以总的路径是/web-inf/jsp/text/personEdit.jsp
//将command放到person里。person是model名字,command是object。实际是map。在页面根据person取。
/**
* 转向编辑页面
*
* @param request
* @param response
* @param command
* @param errors
* @return
*
* @throws ServletException, IOException
*/
public ModelAndView toEditPage(HttpServletRequest request,
HttpServletResponse response, Person command, BindException errors)
throws ServletException, IOException {
String id = request.getParameter("objectId");
command = this.personmanager.findById(id);
return new ModelAndView("test/personEdit","person",command);
}
分享到:
相关推荐
本书由浅入深地介绍了当今流行的Java Web框架Spring MVC的方方面面,从基础的环境搭建到微服务设计与架构,再到持久化、REST API构建、认证与测试……涵盖了Spring MVC诸多重要且常用的特性。值得一提的是,本书针对...
Spring MVC 配置详解 Spring MVC 是一个基于 DispatcherServlet 的 MVC 框架,它是当前主流的 Web 框架之一。要想灵活运用 Spring MVC 来应对大多数的 Web 开发,就必须要掌握它的配置及原理。 一、Spring MVC ...
第3篇是Spring MVC技术入门,包括Spring MVC的背景介绍、架构整体剖析、环境搭建、处理器与映射器的讲解、前端控制器的源码分析、多种视图解析器的介绍、请求映射与参数绑定的介绍、Validation校验与异常处理和拦截...
《深入解析Spring MVCgn Web Flow》是Spring MVC 和Web Flow 两个框架的权威指南,书中包括的技巧和提示可以让你从这个灵活的框架中汲取尽可能多的信息。书中包含了一些开发良好设计和解耦的Web 应用程序的最佳实践...
深入解析Spring MVC与Web Flow.7z.002
Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):...
灵活性:Spring MVC 提供了多种视图解析器,使得视图的选择变得简单和灵活。开发者可以根据项目的需求选择不同的视图解析器,如 JSP、Thymeleaf、FreeMarker 等。 可配置性:Spring MVC 提供了强大的配置功能,包括...
Spring MVC源码深度剖析开源架构源码2021.pdf
详细的Spring MVC教程,内容包括控制器 重定向 保存并获取属性参数 拦截器 表单标签和验证表单 视图和视图解析器 上传文件 数据转换和格式化
本地化:Spring MVC的本地化解析器 本地化:Spring MVC的本地化解析器 LocaleChangeInterceptor:通过URL参数指定 静态资源处理 静态资源处理:使REST风格的URL成为实现 静态资源处理:原理 静态资源处理:如何配置? ...
Spring源代码解析4:Spring MVC ;Spring源代码解析5:Spring AOP获取Proxy;Spring源代码解析6:Spring声明式事务处理 ; Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动...
Spring源代码解析4:Spring MVC .doc Spring源代码解析5:Spring AOP获取Proxy .doc Spring源代码解析6:Spring声明式事务处理 .doc Spring源代码解析7:Spring AOP中对拦截器调用的实现 .doc Spring源代码解析8:...
thymeleaf,我个人认为是个比较好的模板,性能也比一般的,比如freemaker的要...由于thymeleaf在内存缓存解析后的模板,解析后的模板是基于tree的dom节点树,因此thymeleaf适用于一般的web页面,不适合基于数据的xml。
此中包含了大量的SpringMVC demo, 以及spring mvc 部分源码解析。
深入解析Spring MVC与Web Flow
_第一课:spring mvc 原理深度解析1
Spring MVC--5.视图和视图解析器
奉上学习Spring MVC 3.0的技术资料PPT资料,我花了两天写成,该资料根据最新拙作的《Spring 3.x 企业应用开发实战 》写成,仅需要1个小时左右的时间,就可以让你学习到Spring MVC 3.0的所有知识点和新功能,强烈推荐...
Spring MVC是Spring框架中的一部分,全称是Spring Web MVC,主要用于实现MVC设计模式的Web框架。它分离了控制器、模型对象、过滤器以及处理程序...此外,Spring MVC还支持本地化/国际化(Locale)解析及文件上传等。
spring mvc web_flow xml版