【书籍篇】Spring实战第4版 第2部分 Web中的Spring

Spring实战第4版 第2部分 Web中的Spring

  • 五. 构建Spring Web应用程序
    • 5.1 SpirngMVC请求流程
    • 5.2 搭建Spring MVC
      • 5.2.1 配置DispatcherServlet
      • 5.2.2 配置WebConfig
      • 5.2.3 配置RootConfig
    • 5.3 编写基本的控制器
    • 5.4 Spittr首页
    • 5.6 复杂的控制器
      • 5.6.1 定义类级别的请求处理
      • 5.6.2 传递模型数据到视图中
      • 5.6.3 接受请求的输入
      • 5.6.4 处理表单
      • 5.6.5 校验表单
  • 六. 渲染Web视图
    • 6.1 视图解析器
    • 6.2 创建JSP视图
      • 6.2.1 配置InternalResourceViewResolver
      • 6.2.2 使用Spring的JSP库
      • 6.2.3 Spring通用标签库
      • 6.2.4 展示国际化信息
      • 6.2.5 创建URL
      • 6.2.6 转义
    • 6.3 使用Apache Tiles视图定义布局
      • 6.3.1 配置Tile视图解析器
      • 6.3.2 定义Tiles
      • 6.3.3 主布局模板
    • 6.4 使用Thymeleaf模板
      • 6.4.1 配置Thymeleaf视图解析器
      • 6.4.2 定义Thymeleaf模板
      • 6.4.3 借助Thymeleaf实现表单绑定
  • 七. Spring MVC的高级技术
    • 7.1 Spring MVC配置的替代方案
      • 7.1.1 自定义DispacherServlet配置
      • 7.1.2 添加其他Servlet和Filter
      • 7.1.3 web.xml中声明DispatcherServlet
      • 7.1.4 web.xml中使用基于java的配置
    • 7.2 处理Multipart形式的数据
      • 7.2.1 配置multipart解析器
      • 7.2.2 StandardServletMultipartResolver
      • 7.2.3 CommonsMultipartResolver
    • 7.3 处理Multipart请求
    • 7.4 处理异常
      • 7.4.1 异常映射HTTP状态码
      • 7.4.2 异常处理方法
      • 7.4.3 为控制器添加通知
    • 7.5 跨重定向请求传递数据
      • 7.5.1 使用URL传递
      • 7.5.2 使用flash传递
  • 八. 使用Spring Web Flow
    • 8.1 在Spring中配置Web Flow(xml配置)
      • 8.1.1 装配流程执行器
      • 8.1.2 配置流程注册表
      • 8.1.3 处理流程请求
    • 8.2 流程组件
      • 8.2.1 状态
        • 8.2.1.1 行为状态
        • 8.2.1.2 决策状态
        • 8.2.1.3 结束状态
        • 8.2.1.4 子流程状态
        • 8.2.1.5 视图状态
      • 8.2.2 转移
      • 8.2.3 流程数据
        • 8.2.3.1 声明变量
        • 8.2.3.2 作用域
    • 8.3 流程实例

五. 构建Spring Web应用程序

5.1 SpirngMVC请求流程

web浏览器发送请求
第一站:前端控制器(DispatcherServlet),其作用是将从处理器映射(handler mapping)获取请求的下一站是哪里(哪个控制器)。
第二站:将请求数据交由控制器处理(controller)或者是控制器将业务逻辑委托给一个或多个服务对象处理,
	   处理完的数据称为模型(model),再进行友好的方式进行格式化,最后发送给视图(view)
第三站:视图渲染数据响应给web浏览器。

5.2 搭建Spring MVC

5.2.1 配置DispatcherServlet

public class SpittrWebAppInitializer
	extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected String[] getServletMappings() {
        return new String[] {"/"};	// 将DispatcherServlet映射到"/"
    }
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] {RootConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] {WebConfig.class};
    }
}

5.2.2 配置WebConfig

@Configuration
@EnableWebMvc
public class WebConfig {
    
}

5.2.3 配置RootConfig

@Configuration
@ComponentScan(basePackages={"spittr"}, 
    excludeFilters={
        @Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)
})
public class RootConfig {
    
}

5.3 编写基本的控制器

@Controller		// 声明为一个控制器
public class DemoController {
    @RequestMapping(value="/", method=GET)	// 处理对"/"的Get请求
    public String demo() {
       return "demo";		// 发送给视图“demo”
    }
}

5.4 Spittr首页

略。。。详细可从书中p144获知

5.6 复杂的控制器

5.6.1 定义类级别的请求处理

@Controller
@RequestMapping("/")
public class DemoController {
	...
}

5.6.2 传递模型数据到视图中

略。。。详细可从书中p147获知

5.6.3 接受请求的输入

@Controller
@RequestMapping("/")
public class DemoController {
    
    @Autowired
    private DemoService demoService;
    
	@RequestMapping(value="/getList", method=GET)
    public List<String> getList(@RequestParam("conut") long count) {  
       return demoService.selectByCount(count);
    }
    
    @RequestMapping(value="/{id}", method=GET)
    public List<String> getObj(@PathVariable("id") long id) {  
       return demoService.selectById(id);
    }
}

5.6.4 处理表单

略。。。详细可从书中p158获知

5.6.5 校验表单

在Spring MVC中提供了对java校验API的支持,详细可从书中p164获知或百度

public class Demo {
    @NotNull
    @Size(min=5, max=16)
    private Long id;
    ...
}

@Controller
@RequestMapping("/")
public class DemoController {
    @RequestMapping(value="/valid", method=POST)
	public Boolean valid(@Valid Demo demo, Errors errors) {
        if (errors.hasErrors()) {
            return false;
        }
        return true;
    }
}

六. 渲染Web视图

6.1 视图解析器

Spring自带了13个视图解析器

视图解析器 描述
BeanNameViewResolver 将视图解析为Spring应用上下文中的bean,其中bean的ID与视图的名字相同
ContentNegotiatingViewResolver 通过考虑客户端的内容类型来解析视图,委托给另一个能够产生对应内容类型的视图解析器
FreeMarkerViewResolver 将视图解析为FreeMarker模板
InternalResourceViewResolver 将视图解析为Web应用的内部资源(一般为JSP)
JasperReportsViewResolver 将视图解析为JasperReports定义
ResourceBundleViewResolver 将视图解析为资源bundle(一般为属性文件)
TilesViewResolver 将视图解析为Apache Tiles定义,其中tile ID与视图名称相同(注意有两个不同的TilesViewResolver实现,分别对应Tiles 2.0 和 Tiles 3.0)
UrlBasedViewResolver 直接更具视图的名称解析视图,视图的名称会匹配一个物理视图的定义
VelocityLayoutViewResolver 将视图解析为Velocity布局,从不同的Velocity模板中组合页面
VelocityViewResolver 将视图解析为Velocity模板
XmlViewResolver 将视图解析为XML文件中bean的定义(类似于BeanNameViewResolver)
XsltViewReslover 将视图解析为XSLT转换后的结果
ThymeleafViewResolver 将逻辑视图名称解析为Thymeleaf模板视图

6.2 创建JSP视图

6.2.1 配置InternalResourceViewResolver

@bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INFO/views/");
    resolver.setSuffix(".jsp");
    // 解析JSTL标签
    resolver.setViewClass("org.springframework.web.servlet.view.JstlView.class");
    return resolver;
}
<bean id="viewResolver"  class= "org.springframework.web.servlet.view.InternalResourceViewResolver" 
      p:prefix="/WEB-INFO/views/" p:suffix=".jsp" 
      p:viewClass="org.springframework.web.servlet.view.JstlView" />

6.2.2 使用Spring的JSP库


<%@ tagblib uri="http://wwww.springframwork.org/tags/form" prefix="sf" %>

6.2.3 Spring通用标签库

<%@ tagblib uri="http://wwww.springframwork.org/tags" prefix="s" %>

6.2.4 展示国际化信息

@Bean
public MessageSource messageSource() {
	ResourceBunleMessageSource messageSource = new ResourceBunleMessageSource();
    messageSource.setBeanname("message");
    return messageSource;
}

@Bean
public MessageSource messageSource() {
    ReloadableResourceBunleMessageSource messageSource = new ReloadableResourceBunleMessageSource();
    messageSource.setBasename("file://etc/spittr/messages");	// 类路径以 classpath: 为前缀
    messageSource.setCacheSeconds(10);
    return messageSource;
}

// en.properties
spittr.welcome=Welcome to Spittr!
    
// zh.properties
spittr.welcome=欢迎来到Spittr!

6.2.5 创建URL

。。。详细可从书中p182获知

6.2.6 转义

。。。详细可从书中p184获知

6.3 使用Apache Tiles视图定义布局

6.3.1 配置Tile视图解析器

@Bean
public TilesConfigurer tilesConfigurer() {
    TilesConfigurer tiles = new TilesConfigurer();
    // 指定Tile的定义的位置	"/WEB-INFO/**/tiles.xml"	
    tiles.setDefinitions(new String[] {
        "/WEB-INFO/layout/tiles.xml"	
    });
    // 启用刷新功能
    tiles.setCheckRefresh(true);
    return tiles;
}

@Bean
public ViewResolver viewResolver() {
    return new TilesViewResolver();
}
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
	<property name="definitions">
    	<list>
        	<value>/WEB-INFO/layout/tiles.xmlvalue>
            <value>/WEB-INFO/**/tiles.xmlvalue>
        list>
    property>
bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.tiles3.ViewResolver" />

6.3.2 定义Tiles

<xml version="1.0" encoding="UTF-8">
<DOCTYPE tiles-definitions PUBLIC
	"...">
<tiles-definitions>
    
	<definition name="base" template="/WEB-INF/layout/page.jsp">
        
    	<put-attribute name="body" value="/WEB-INF/layout/header.jsp" />
        <put-attribute name="footer" value="/WEB-INF/layout/footer.jsp" />
    definition>

	
	<definition name="home" template="/WEB-INF/layout/home.jsp">
        
    	<put-attribute name="body" value="/WEB-INF/layout/home.jsp" />
    definition>
tiles-definitions>

6.3.3 主布局模板

<%@ tagblib uri="http://wwww.springframwork.org/tags" prefix="s" %>
<%@ tagblib uri="tiles.apache.org/tags-tiles" prefix="t" %>


    
        ...
    
    
        
        

6.4 使用Thymeleaf模板

略。。。详细可从书中p190~196获知

6.4.1 配置Thymeleaf视图解析器

6.4.2 定义Thymeleaf模板

6.4.3 借助Thymeleaf实现表单绑定

七. Spring MVC的高级技术

7.1 Spring MVC配置的替代方案

略。。。详细可从书中p200~205获知

7.1.1 自定义DispacherServlet配置

7.1.2 添加其他Servlet和Filter

7.1.3 web.xml中声明DispatcherServlet

7.1.4 web.xml中使用基于java的配置

7.2 处理Multipart形式的数据

7.2.1 配置multipart解析器

从Spring3.1开始,Spring内置了两个MultipartResolver的实现供我们选择

multipart解析器 描述
CommonsMultipartResolver 使用Jakarta Commons FileUpload解析multipart请求
StandardServletMultipartResolver 依赖于servlet3.0对multipart请求的支持

7.2.2 StandardServletMultipartResolver

@bean
public MultipartResolver multipartResolver() throws IOException {
    return new StandardServletMultipartResolver();
}
// java配置
@Override
protected void custiomizeRegistration(Dynamic registration) {
    // 临时路径,文件大小不超过2MB,整个请求不超过4MB,所有文件都写入磁盘
    registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads"2096000, 4192000, 0));
}

<servlet>
	<servlet-name>appServletservlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    <load-on-startup>1load-on-startup>
    <multipart-config>
    	<location>/tmp/spittr/uploadslocation>
        <max-file-size>2096000max-file-size>
        <max-request-size>4192000max-request-size>
    multipart-config>
servlet>

7.2.3 CommonsMultipartResolver

@bean
public MultipartResolver multipartResolver() throws IOException {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));	// 临时路径
    resolver.setMaxUploadSize(2096000);		// 最大的文件容量
    resolver.setMaxInMemorySize(0);		// 最大的内存大小
    return resolver;
}

7.3 处理Multipart请求

... ...
// 方式一:无法获取文件信息
@RequestMapping(value="/register", method=POST)
public String processRegistration(
	@RequestPart("profilePicture") btye[] profilePicture,
    @Valid Spitter spitter,
    Errors errors) {
    ...
}

// 方式二:使用part,能获取文件信息
@RequestMapping(value="/register", method=POST)
public String processRegistration(
	@RequestPart("profilePicture") Part profilePicture,
    @Valid Spitter spitter,
    Errors errors) {
    ...
}

7.4 处理异常

7.4.1 异常映射HTTP状态码

@ResponseStatus(value=HttpStatus.NOT_FOUND, reson="Spittle Not Found")
public class SpitterNotFoundException extends RuntimeException {
    ...
}

7.4.2 异常处理方法

// 方式一
@RequestMapping(method=POST)
public String saveSpitter(SpittleForm form, Model model) {
    try {
        spittleRepository.save(new Spittle(null, form.getName()));
    	return "redirect:/spittles";
    } catch (DuplicateSpittleException e) {
        return "error/duplicate";
    }
}


// 方式二
// 该控制器里的方法抛出DuplicateSpittleException异常就会调用handleDuplicateSpittle()方法来处理异常
@RequestMapping(method=POST)
public String saveSpitter(SpittleForm form, Model model) {
    spittleRepository.save(new Spittle(null, form.getName()));
    return "redirect:/spittles";
}
	
@ExceptionHandler(DuplicateSpittleException.class)
public String handleDuplicateSpittle() {
    return "error/duplicate";
}

7.4.3 为控制器添加通知

// 任意控制器抛出DuplicateSpittleException异常都会调用handleDuplicateSpittle()方法来处理异常
@ControllerAdvice
public class AppWideExceptionHandller {
    @ExceptionHandler(DuplicateSpittleException.class)
    public String handleDuplicateSpittle() {
        return "error/duplicate";
    }
}

7.5 跨重定向请求传递数据

跨重定向请求传递数据
使用URL模板以路径变量或查询参数的形式传递数据
通过flash属性发送数据

7.5.1 使用URL传递

@RequestMapping(value="/register", method=POST)
public String processRegistration(Spitter spitter, Model model) {
    spittleRepository.save(Spitter);
    model.adddAttribute("name", Spitter.getName());
    return "redirect:/spittles/{name}";
}

7.5.2 使用flash传递

@RequestMapping(value="/register", method=POST)
public String processRegistration(Spitter spitter, Model model) {
    spittleRepository.save(spitter);
    model.adddAttribute("name", spitter.getName());
    model.adddFlashAttribute("spitter", spitter);
    return "redirect:/spittles/{name}";
}

@RequestMapping(value="/{name}", method=GET)
public String showSpitterProfile(@PathVariable String name, Model model) {
    if (!model.contaionsAttribute("spitter")) {
        model.adAttribute(spittleRepository.findByName(name));
    }
    return "profile";
}

八. 使用Spring Web Flow

8.1 在Spring中配置Web Flow(xml配置)

8.1.1 装配流程执行器


<flow:flow-executor id="flowExecutor" />

8.1.2 配置流程注册表



<flow:flow-registry id="flowRegistry" base-path="/WEB-INF/flows">
    <flow:flow-location-pattern value="*-flow.xml" />
flow:flow-registry>

<flow:flow-registry id="flowRegistry">
    <flow:flow-location value="/WEB-INF/flows/springpizza.xml" />
flow:flow-registry>


<flow:flow-registry id="flowRegistry">
    <flow:flow-location id="pizza" value="/WEB-INF/flows/springpizza.xml" />
flow:flow-registry>

8.1.3 处理流程请求


<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
	<propertry name="flowRegistry" ref="flowRegistry" />
bean>


<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
	<propertry name="flowExecutor" ref="flowExecutor" />
bean>

8.2 流程组件

8.2.1 状态

类型 作用
行为(Action) 流程逻辑发生的地方
决策(Decision) 将流程基于流程数据确定分成两个方向
结束(End) 流程最后一站,一旦进入流程终止
子流程(Subflow) 会在当前正在运行大队流程上下文中启动一个新的流程
视图(View) 暂停流程并邀请用户参与流程
8.2.1.1 行为状态

<action-state id="saveOrder">
	<evaluate expression="pizzaFlowActions.saveOrder(order)" />
    <transition to="thankYou" />
action-state>
8.2.1.2 决策状态

<decision-state id="checkDeiveryArea">
	<if test="pizzaFlowAtions.checkDeliveryArea(customer.zipCode)"
        then="addCustomer"
        else="deliveryWarning" />
decision-state>
8.2.1.3 结束状态

<end-state id="customerReady" />
8.2.1.4 子流程状态

<subflow-state id="order" subflow="pizza/order">
	<input name="order" value="order" />
    <transition on="orderCreated" to="payment" />
subflow-state>
8.2.1.5 视图状态

<view-state id = "welcome" />

<view-state id = "welcome" view="greeting"/>

<view-state id = "welcome" modedl="flowScope.paymentDetails"/>

8.2.2 转移


<transition to="customerReady" />

<transition on="phoneEntered" to="customerReady" />

<transition on-exception="com.springinaction.pizza.service.CustomerNotFoundException" to="customerReady" />

<global-transitions>
	<transition on="cancel" to="endstate" />
global-transitions>

8.2.3 流程数据

8.2.3.1 声明变量

<var name="customer" class="com.springinaction.pizza.domain.Customer" />

<evaluate result="viewScope.toppingsList" expression="T(com.springinaction.pizza.ddomain.Topping).asList()" />

<set name="flowScope.pizza" value="new com.springinaction.pizza.domain.Pizza()" />
8.2.3.2 作用域
范围 作用域和可见性
Conversation 最高层级的的流程开始时创建,最高层级的流程结束时销毁。被最高层级的流程和其所有的子流程所共享
Flow 当流程开始时创建,在流程结束时销毁。只有在创建它的流程中是可见的
Request 当一个请求进入流程时创建,在流程返回时销毁
Flash 当流程开始时创建,在流程结束时销毁。在视图状态渲染后,它会被清除
View 当进入视图状态时创建,当这个状态退出时销毁。只在视图状态内是可见的

8.3 流程实例

略。。。详细可从书中p234~248获知

你可能感兴趣的:(Spring实战第4版,Spring实战)