快速学习使用springmvc、strust2、strust1以及它们的对比
1、如何快速学习springmvc
<servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.json</url-pattern> </servlet-mapping>然后再在application.xml里面配置下面代码,
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <!-- 自动扫描的包名 --> <context:component-scan base-package="com.shishuo.studio"></context:component-scan> <mvc:annotation-driven /> <task:annotation-driven /> <tx:annotation-driven /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <!-- 在XML配置文件中加入外部属性文件,当然也可以指定外部文件的编码 --> <bean id="propertyConfigurer" class="com.shishuo.studio.util.PropertyUtils"> <property name="locations"> <list> <value>classpath:shishuo.studio.properties</value> <!-- 指定外部文件的编码 --> </list> </property> </bean> <!-- FreeMarker的配置 --> <bean id="freeMarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/ftl" /><!-- 指定路径 --> <property name="defaultEncoding" value="UTF-8" /><!-- 指定编码格式 --> <property name="freemarkerSettings"> <props> <prop key="template_update_delay">10</prop> <prop key="defaultEncoding">UTF-8</prop> <prop key="url_escaping_charset">UTF-8</prop> <prop key="locale">zh_CN</prop> <prop key="boolean_format">true,false</prop> <prop key="time_format">HH:mm:ss</prop> <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop> <prop key="date_format">yyyy-MM-dd</prop> <prop key="number_format">#.##</prop> <prop key="whitespace_stripping">true</prop> <prop key="classic_compatible">true</prop> </props> </property> </bean> <!-- 配置 FreeMarker视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"></property> <property name="cache" value="false" /> <property name="prefix" value="/" /> <property name="suffix" value=".ftl" /><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑 --> <property name="contentType" value="text/html;charset=utf-8" /> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <property name="exposeSpringMacroHelpers" value="true" /> </bean>我们试图模板用的是freemarker,所以后缀名是以.ftl结束,如果是用的jsp,那这个配置文件里面的
<property name="suffix" value=".ftl" />valeu改为.jsp然后我再给出类给大家看见
package com.shishuo.studio.action;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import com.shishuo.studio.constant.SystemConstant;import com.shishuo.studio.entity.Category;import com.shishuo.studio.entity.vo.CourseVo;import com.shishuo.studio.entity.vo.PageVo;import com.shishuo.studio.exception.CategoryNotFoundException;import com.shishuo.studio.exception.notfound.StorageNotFoundException;import com.shishuo.studio.service.CategoryService;import com.shishuo.studio.service.UserService;/** * @author Herbert * */@Controller@RequestMapping("/category")public class CategoryAction extends BaseAction { protected final Logger logger = Logger.getLogger(this.getClass()); @Autowired protected CategoryService categoryService; @Autowired protected UserService userService; /** * 首页 * * @param modelMap * @return */ @RequestMapping(value = "/{categoryId}.htm", method = RequestMethod.GET) public String category(@PathVariable long categoryId, ModelMap modelMap, @RequestParam(value = "p", defaultValue = "1") int p) { try { // 获得数据 Category category = categoryService.getCategoryById(categoryId); // 获取当前目录下的所有课程 PageVo<CourseVo> coursePageVo = courseService .getCoursePageByIdForUser(categoryId, p, 24); // 增加属性 modelMap.addAttribute("category", category); modelMap.put("coursePageVo", coursePageVo); return "category"; } catch (CategoryNotFoundException e) { return SystemConstant.PAGE_404; } catch (StorageNotFoundException e) { // TODO Auto-generated catch block return SystemConstant.PAGE_404; } }}
package com.shishuo.studio.action;import javax.servlet.http.HttpServletRequest;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import com.shishuo.studio.action.auth.AuthBaseAction;@Controller@RequestMapping("/about")public class AboutAction extends AuthBaseAction { /** * 跳转到关于我们页面 * * @param modelMap * @param request * @return */ @RequestMapping(value = "/about.htm", method = RequestMethod.GET) public String about(ModelMap modelMap, HttpServletRequest request) { return "/about/about"; } /** * 跳转到服务协议页面 * * @param modelMap * @param request * @return */ @RequestMapping(value = "/service.htm", method = RequestMethod.GET) public String service(ModelMap modelMap, HttpServletRequest request) { return "/about/service"; } /** * 跳转到投诉举报页面 * * @param modelMap * @param request * @return */ @RequestMapping(value = "/complain.htm", method = RequestMethod.GET) public String complain(ModelMap modelMap, HttpServletRequest request) { return "/about/complain"; } /** * 跳转到版权声明页面 * * @param modelMap * @param request * @return */ @RequestMapping(value = "/copyright.htm", method = RequestMethod.GET) public String copyright(ModelMap modelMap, HttpServletRequest request) { return "/about/copyright"; } /** * 跳转到联系我们页面 * * @param modelMap * @param request * @return */ @RequestMapping(value = "/connect.htm", method = RequestMethod.GET) public String connect(ModelMap modelMap, HttpServletRequest request) { return "/about/connect"; }}
下面是使用springmvc的经验:
return "system/comment/comment";后面不需要东西
return "redirect:/admin/comment/page.htm";一般当我改变一个状态的时候 我需要还是显示在当前页面 就需要再进入Action 相当于再到数据库访问一次把 我改变的数据同个pageVo 显示到页面
spring的注解学习
@RequestParam("description") String description,
@PathVariable
请求路径上有个id的变量值,[email protected] @RequestMapping(value = "/page/{id}", method = RequestMethod.GET)
@autowired 自动配置 不需要写getter() setter()方法
@Deprecated 过时
@Repository 用在接口前面的类 比如ibits接口类的最前面
@ResponseBody当控制器返回页面不是字符串的时候 比如返回一个json对象用这个注解
@Controller控制器 加在控制器类的最前面
@RequestMapping("/admin/file")
放在类前面是这个路径下
@RequestMapping(value = "/index.htm", method = RequestMethod.GET)如果这个注解放在方法的前面 表示上面那个路径的基础下然后再是这个路劲
@RequestParam(value = "fileId", defaultValue = "1")当url传入参数的时候就可以拿到值
[email protected](value = "/update.htm", method = RequestMethod.GET)
public String update(
@RequestParam(value = "fileId", defaultValue = "1") long fileId,
ModelMap modelMap) throws Exception {}
简单原理:
spring mvc请所有的请求都提交给在web.xml中配置的DispatcherServlet,由它查询一个或多个HandlerMapping,找到处理请求的Controller,并且将请求提交给这个类。
Controller进行业务逻辑处理后,会返回一个ModelAndView
Dispathcher查询一个或多个 ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 ,视图对象负责渲染返回给客户端。
2、如何快速学习strust2
2 在项目的src目录下新建struts.properties或struts.xml
struts.properties和struts.xml具有相同的配置作用,配置项目相关
3 web.xml加入:
<filter> <filter-name>ActionContextCleanUp</filter-name> <filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class> </filter> <!-- 若有其他相关的filter 需要加在这个地方--> <!--配置struts2过滤器--> <filter> <filter-name>webwork</filter-name> <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>ActionContextCleanUp</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>webwork</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>编写action请求处理类.可以继承struts2的 ActionSupport也可以不继承,(不过一般为了方便获取 request,response以及session 最好自己编写一个类继承ActionSupport,并在类中获取request等,让请求处理类继承这个类),然后根据页面和struts.xml配置决定请求的处理方法.
例1:
<s:form action="login.action" method="post"> <s:textfield key="username" name="user.username"/> <s:password key="password" name="user.password" /> <s:submit key="submit" /> </s:form>strust.xml中
<action name="login" class="cc.dynasoft.action.LoginAction"> <result name="success">/welcome.jspresult> <result name="error">/login.jspresult> </action>这时请求会交由LoginAction的默认方法execute来处理,在LoginAaction中有user对象及其set方法,页面属性会自动注入到此user对象中,返回字符串[success],匹配struts.xml此action内的result值确定调转的展示页面
例2:
-----页面
<s:form action="submit.action"> <s:textfield name="msg"label="输入内容"/> <s:submit name="save"value="保存"align="left"method="save"/> <s:submit name="print"value="打印"align="left"method="print"/> </s:form>
struts.xml
-----struts.xml: <action name="submit" class="action.MoreSubmitAction"> <result name="save">/result.jsp</result> <result name="print">/result.jsp</result> </action>由页面submit的method方法来指定对应的处理方法,方法返回字符串.继而确定调转展示页面
例3:
-----设置自定义的url后缀,有struts2处理例如struts.action.extension=php.默认为action,即处理所有*.action的请求
-----页面
<form method="post" action="Kinder_add.php" <input type="text" name="kinder.name"> <input type="text"name="kinder.zip"> <input type="submit" value="提交"> </form>
<action name="*_*" method="{2}" class="ostar.lg.action.{1}Action"> <result name="success">/default.jsp</result> </action>
这样的意思是:所有由'_'间隔的请求都会有'_'前面的字符串同名的action类处理,并交给这个类的和'_'后面字符串同名的方法处理[简化了配置],方法返回字符串继而确定调转展示的页面.(*_*只是一种自定义格式,可任意配置)
B 流程:
1、客户端初始化一个对服务器的请求(tomcat);
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于 Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin);
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个 Action;
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;
5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类;
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。
C特性分析:
1 线程模式,每一次请求都会产生一个新的实例处理请求. 多线程环境没有数据同步问题.
2 引入数据的依赖注入
[页面表单数据到action的注入,实例对象的注入,都是通过set注入,需要提供set方法]
3 基于AOP的拦截器,可以在每次请求前后灵活控制
4 配置文件支持表达式,基于约定优于配置的话可简化配置文件
4 内置以插件形式支持ajax如dojo,支持多种模板展示jsp、freemarker,Velocity等
3、如何快速学习strust1
2 在web-inf目录下新建struts-config.xml文件,配置struts相关内容
3 web.xml配置加入:
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>3</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>3</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
4 编写action控制类,继承Action[复杂情况继承DispactureAction],同时在struts-config.xml中配置这个控制类action.例如:
<action path="/stock" parameter="method" name="stocklogForm" type="com.xuanmu.struts.action.stock.StockAction" scope="request"> <forward name="LIST" path="/productsList.jsp" /> </action>当截取到请求为stock时就由StockAaction处理.[继承DispactureAction的话分发到parameter值对应的方法中去], 该方法返回由字符串封装[LIST]的ActionForward对象,然后再struts-config.xml中的匹配 ,决定返回呈现的页面
B流程:
1预备工作:服务器启动,Web应用启动时就会加载web.xml初始化actionServlet和记载struts配置文件(struts-config.xml),读配置信息到内存中,供以后action调用
2(由请求定位action控制类)
用户通过客户端向服务器发出一个请求,http://localhost:8080/struts_login/login.do
我们已经在web.xml配置了所有符合某特定格式的请求都将由struts指定的Servlet来处理。比如:只要是以.do结尾的请求(*.do)都由 org.apache.struts.action.ActionServlet来对其进行处理.ActionServlet会拿到用户的请求,并且去分析这个URL,它会截下 /login. 截下来之后,它是为了去struts-config.xml这个配置文件里面找<action>标签path属性的值等于所截部分的那个 Action.
3(页面数据注入)
找到对应的action之后,ActionServlet会把表单提交的数据给存放(生成对应调用 set/get方法)到struts-config中相应的action标签的name属性值指定的actionform类中(若有, [actionform的子类,并且在form-bean标签中配置了,若要进行数据验证可以在actionform中覆盖validate方法,推荐使用js,减轻服务器负担]).同时把actionform和当前HttpServletrequest 对象注入到代调用的action方法中.
4(调用action的处理方法)
[默认是execute方法可以通过dispactureAction分发请求给自定义的方法]可以在方法中取得请求附属的数据(若需要),编写业务逻辑代码处理请求.
5(返回到view层的页面)
Action的业务逻辑方法会返回一个ActionForward对象 ,ActionForward对象根据此action配置的<forward>匹配name进而调转到对应path的jsp页面上.
表现层常见框架的对比
springmvc和strust2比较
神 —— SpringMVC总是沿着一条固定的逻辑主线运行
形 —— SpringMVC却拥有多种不同的行为模式
SpringMVC是一个基于组件的开发框架,组件的不同实现体系构成了“形”;组件的逻辑串联构成了“神”。因此,“形散神不散”: SpringMVC的逻辑主线始终不变,而行为模式却可以多种多样。
strust2和strust1对比
2、 线程模式方面的对比:Struts 1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts 1 Action能做的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的;Struts 2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。
3、Servlet依赖方面的对比:Struts 1 Action依赖于Servlet API,因为Struts 1 Action的execute方法中有HttpServletRequest和HttpServletResponse方法。Struts 2 Action不再依赖于Servlet API,从而允许Action脱离Web容器运行,从而降低了测试Action的难度。 当然,如果Action需要直接访问HttpServletRequest和HttpServletResponse参数,Struts 2 Action仍然可以访问它们。但是,大部分时候,Action都无需直接访问HttpServetRequest和HttpServletResponse,从而给开发者更多灵活的选择。
4、可测性方面的对比:测试Struts 1 Action的一个主要问题是execute方法依赖于Servlet API,这使得Action的测试要依赖于Web容器。为了脱离Web容器测试Struts 1的Action,必须借助于第三方扩展:Struts TestCase,该扩展下包含了系列的Mock对象(模拟了HttpServetRequest和HttpServletResponse对象),从而可以脱离Web容器测试Struts 1的Action类。Struts 2 Action可以通过初始化、设置属性、调用方法来测试。
5、 封装请求参数的对比:Struts 1使用ActionForm对象封装用户的请求参数,所有的ActionForm必须继承一个基类:ActionForm。普通的JavaBean不能用作ActionForm,因此,开发者必须创建大量的ActionForm类封装用户请求参数。虽然Struts 1提供了动态ActionForm来简化ActionForm的开发,但依然需要在配置文件中定义ActionForm;Struts 2直接使用Action属性来封装用户请求属性,避免了开发者需要大量开发ActionForm类的烦琐,实际上,这些属性还可以是包含子属性的Rich对象类型。如果开发者依然怀念Struts 1 ActionForm的模式,Struts 2提供了ModelDriven模式,可以让开发者使用单独的Model对象来封装用户请求参数,但该Model对象无需继承任何Struts 2基类,是一个POJO,从而降低了代码污染。
6、表达式语言方面的对比:Struts 1整合了JSTL,因此可以使用JSTL表达式语言。这种表达式语言有基本对象图遍历,但在对集合和索引属性的支持上则功能不强;Struts 2可以使用JSTL,但它整合了一种更强大和灵活的表达式语言:OGNL(Object Graph Notation Language),因此,Struts 2下的表达式语言功能更加强大。
7、 — 绑定值到视图的对比:Struts 1使用标准JSP机制把对象绑定到视图页面;Struts 2使用“ValueStack”技术,使标签库能够访问值,而不需要把对象和视图页面绑定在一起。
8、类型转换的对比:Struts 1 ActionForm 属性通常都是String类型。Struts 1使用Commons-Beanutils进行类型转换,每个类一个转换器,转换器是不可配置的;Struts 2使用OGNL进行类型转换,支持基本数据类型和常用对象之间的转换。
9、 数据校验的对比:Struts 1支持在ActionForm重写validate方法中手动校验,或者通过整合Commons alidator框架来完成数据校验。Struts 2支持通过重写validate方法进行校验,也支持整合XWork校验框架进行校验。
10、 Action执行控制的对比:Struts 1支持每一个模块对应一个请求处理(即生命周期的概念),但是模块中的所有Action必须共享相同的生命周期。Struts 2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。开发者可以根据需要创建相应堆栈,从而和不同的Action一起使用。
11、捕获输入:Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有冗余的javabean)。Struts 2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。
版权声明:本文为博主原创文章,未经博主允许不得转载。