MVC 设计概述

在早期 Java Web 的开发中,统一把显示层、控制层、数据层的操作全部交给 JSP 或者 JavaBean 来进行处理,我们称之为 Model1:

  • 出现的弊端:
  • JSP 和 Java Bean 之间严重耦合,Java 代码和 HTML 代码也耦合在了一起
  • 要求开发者不仅要掌握 Java ,还要有高超的前端水平
  • 前端和后端相互依赖,前端需要等待后端完成,后端也依赖前端完成,才能进行有效的测试
  • 代码难以复用

正因为上面的种种弊端,所以很快这种方式就被 Servlet + JSP + Java Bean 所替代了,早期的 MVC 模型(Model2)就像下图这样:

首先用户的请求会到达 Servlet,然后根据请求调用相应的 Java Bean,并把所有的显示结果交给 JSP 去完成,这样的模式我们就称为 MVC 模式。

  • M 代表 模型(Model)
    模型是什么呢? 模型就是数据,就是 dao,bean
  • V 代表 视图(View)
    视图是什么呢? 就是网页, JSP,用来展示模型中的数据
  • C 代表 控制器(controller)
    控制器是什么? 控制器的作用就是把不同的数据(Model),显示在不同的视图(View)上,Servlet 扮演的就是这样的角色。

扩展阅读:Web开发模式

Spring MVC 的架构

为解决持久层中一直未处理好的数据库事务的编程,又为了迎合 NoSQL 的强势崛起,Spring MVC 给出了方案:

传统的模型层被拆分为了业务层(Service)和数据访问层(DAO,Data Access Object)。在 Service 下可以通过 Spring 的声明式事务操作数据访问层,而在业务层上还允许我们访问 NoSQL ,这样就能够满足异军突起的 NoSQL 的使用了,它可以大大提高互联网系统的性能。

特点:

  • 结构松散,几乎可以在 Spring MVC 中使用各类视图
  • 松耦合,各个模块分离
  • 与 Spring 无缝集成

Hello Spring MVC

第一步:新建 Spring MVC 项目并且取名为 【HelloSpringMVC】

第二步:修改 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 配置SpringMVC前端控制器DispatcherServlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 指定SpringMVC配置文件spring-config.xml,用来将拦截的对应请求分发给对应的Controller-->
<param-value>/WEB-INF/springmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <!-- 指定该springmvc的Servlet可以拦截的请求为所有请求("/"),
之后可以分发给对应的Controller-->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

第三步:编辑 dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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"> <bean id="simpleUrlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- /hello 路径的请求交给 id 为 helloController 的控制器处理-->
<prop key="/hello">helloController</prop>
</props>
</property>
</bean>

这个文件名的开头 dispatcher 与上面 web.xml 中的 <servlet-name> 元素配置的 dispatcher 对应,这是 Spring MVC 的映射配置文件(xxx-servlet.xml),我们编辑如下:

第四步:编写 HelloController

在 Package【controller】下创建 【HelloController】类,并实现 org.springframework.web.servlet.mvc.Controller 接口:

package controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller{
@Override
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
return null;
}
}

Spring MVC 通过 ModelAndView 对象把模型和视图结合在一起

ModelAndView mav = new ModelAndView("index.jsp");
mav.addObject("message", "Hello Spring MVC");

这里表示视图的是index.jsp,模型数据的是 message,内容是 “Hello Spring MVC”

package controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller; public class HelloController implements Controller { public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mav = new ModelAndView("index.jsp");
mav.addObject("message", "Hello Spring MVC");
return mav;
}
}

第五步:准备 index.jsp

将 index.jsp 的内容修改为:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%> <h1>${message}</h1>

第六步:启动服务器,输入地址:localhost/hello

跟踪 Spring MVC 的请求

每当用户在 Web 浏览器中点击链接或者提交表单的时候,请求就开始工作了,像是邮递员一样,从离开浏览器开始到获取响应返回,它会经历很多站点,在每一个站点都会留下一些信息同时也会带上其他信息,下图为 Spring MVC 的请求流程:

第一站:DispatcherServlet

从请求离开浏览器以后,第一站到达的就是 DispatcherServlet,看名字这是一个 Servlet,通过 J2EE 的学习,我们知道 Servlet 可以拦截并处理 HTTP 请求,DispatcherServlet 会拦截所有的请求,并且将这些请求发送给 Spring MVC 控制器。

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<!-- 拦截所有的请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>

DispatcherServlet 的任务就是拦截请求发送给 Spring MVC 控制器。

第二站:处理器映射(HandlerMapping)

问题:典型的应用程序中可能会有多个控制器,这些请求到底应该发给哪一个控制器呢?

所以 DispatcherServlet 会查询一个或多个处理器映射来确定请求的下一站在哪里,处理器映射会根据请求所携带的 URL 信息来进行决策

例如上面的例子中,我们通过配置 simpleUrlHandlerMapping 来将 /hello 地址交给 helloController 处理:

bean id="simpleUrlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- /hello 路径的请求交给 id 为 helloController 的控制器处理-->
<prop key="/hello">helloController</prop>
</props>
</property>
</bean>
<bean id="helloController" class="controller.HelloController"></bean>

第三站:控制器

一旦选择了合适的控制器, DispatcherServlet 会将请求发送给选中的控制器,到了控制器,请求会卸下其负载(用户提交的请求)等待控制器处理完这些信息:

public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
// 处理逻辑
....
}

第四站:返回 DispatcherServlet

当控制器在完成逻辑处理后,通常会产生一些信息,这些信息就是需要返回给用户并在浏览器上显示的信息,它们被称为模型(Model)。仅仅返回原始的信息时不够的——这些信息需要以用户友好的方式进行格式化,一般会是 HTML,所以,信息需要发送给一个视图(view),通常会是 JSP。

控制器所做的最后一件事就是将模型数据打包,并且表示出用于渲染输出的视图名(逻辑视图名)。它接下来会将请求连同模型和视图名发送回 DispatcherServlet。

public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
// 处理逻辑
....
// 返回给 DispatcherServlet
return mav;
}

第五站:视图解析器

这样以来,控制器就不会和特定的视图相耦合,传递给 DispatcherServlet 的视图名并不直接表示某个特定的 JSP。(实际上,它甚至不能确定视图就是 JSP)相反,它传递的仅仅是一个逻辑名称,这个名称将会用来查找产生结果的真正视图。

DispatcherServlet 将会使用视图解析器(view resolver)来将逻辑视图名匹配为一个特定的视图实现,它可能是也可能不是 JSP

上面的例子是直接绑定到了 index.jsp 视图

第六站:视图

既然 DispatcherServlet 已经知道由哪个视图渲染结果了,那请求的任务基本上也就完成了。

它的最后一站是视图的实现,在这里它交付模型数据,请求的任务也就完成了。视图使用模型数据渲染出结果,这个输出结果会通过响应对象传递给客户端。

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%> <h1>${message}</h1>

使用注解配置 Spring MVC

上面我们已经对 Spring MVC 有了一定的了解,并且通过 XML 配置的方式创建了第一个 Spring MVC 程序,我们来看看基于注解应该怎么完成上述程序的配置:

第一步:为 HelloController 添加注解

package controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; @Controller
public class HelloController{ @RequestMapping("/hello")
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mav = new ModelAndView("index.jsp");
mav.addObject("message", "Hello Spring MVC");
return mav;
}
}

把实现的接口也给去掉。

简单解释一下:

  • @Controller 注解:
    很明显,这个注解是用来声明控制器的,但实际上这个注解对 Spring MVC 本身的影响并不大。(Spring 实战说它仅仅是辅助实现组件扫描,可以用 @Component 注解代替,但我自己尝试了一下并不行,因为上述例子没有配置 JSP 视图解析器我还自己配了一个仍没有成功...)
  • @RequestMapping 注解:
    很显然,这就表示路径 /hello 会映射到该方法上

第二步:取消之前的 XML 注释

在 dispatcher-servlet.xml 文件中,注释掉之前的配置,然后增加一句组件扫描:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--<bean id="simpleUrlHandlerMapping"-->
<!--class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">-->
<!--<property name="mappings">-->
<!--<props>-->
<!--<!– /hello 路径的请求交给 id 为 helloController 的控制器处理–>-->
<!--<prop key="/hello">helloController</prop>-->
<!--</props>-->
<!--</property>-->
<!--</bean>-->
<!--<bean id="helloController" class="controller.HelloController"></bean>--> <!-- 扫描controller下的组件 -->
<context:component-scan base-package="controller"/>
</beans>

第三步:当配置完成,重新启动服务器,输入 localhost/hello 地址仍然能看到效果

@RequestMapping 注解细节

如果 @RequestMapping 作用在类上,那么就相当于是给该类所有配置的映射地址前加上了一个地址,例如:

@Controller
@RequestMapping("/wmyskxz")
public class HelloController {
@RequestMapping("/hello")
public ModelAndView handleRequest(....) throws Exception {
....
}
}
  • 则访问地址: localhost/wmyskxz/hello

配置视图解析器

还记得我们 Spring MVC 的请求流程吗,视图解析器负责定位视图,它接受一个由 DispaterServlet 传递过来的逻辑视图名来匹配一个特定的视图。

  • 需求: 有一些页面我们不希望用户用户直接访问到,例如有重要数据的页面,例如有模型数据支撑的页面。
  • 造成的问题:
    我们可以在【web】根目录下放置一个【test.jsp】模拟一个重要数据的页面,我们什么都不用做,重新启动服务器,网页中输入 localhost/test.jsp 就能够直接访问到了,这会造成数据泄露...
    另外我们可以直接输入 localhost/index.jsp 试试,根据我们上面的程序,这会是一个空白的页面,因为并没有获取到 ${message} 参数就直接访问了,这会影响用户体验

解决方案

我们将我们的 JSP 文件配置在【WEB-INF】文件夹中的【page】文件夹下,【WEB-INF】是 Java Web 中默认的安全目录,是不允许用户直接访问的(也就是你说你通过 localhost/WEB-INF/ 这样的方式是永远访问不到的)

但是我们需要将这告诉给视图解析器,我们在 dispatcher-servlet.xml 文件中做如下配置:

<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/" />
<property name="suffix" value=".jsp" />
</bean>

这里配置了一个 Spring MVC 内置的一个视图解析器,该解析器是遵循着一种约定:会在视图名上添加前缀和后缀,进而确定一个 Web 应用中视图资源的物理路径的。让我们实际来看看效果:

第一步:修改 HelloController

我们将代码修改一下:

第二步:配置视图解析器:

按照上述的配置,完成:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--<bean id="simpleUrlHandlerMapping"-->
<!--class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">-->
<!--<property name="mappings">-->
<!--<props>-->
<!--<!– /hello 路径的请求交给 id 为 helloController 的控制器处理–>-->
<!--<prop key="/hello">helloController</prop>-->
<!--</props>-->
<!--</property>-->
<!--</bean>-->
<!--<bean id="helloController" class="controller.HelloController"></bean>--> <!-- 扫描controller下的组件 -->
<context:component-scan base-package="controller"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

第三步:剪贴 index.jsp 文件

在【WEB-INF】文件夹下新建一个【page】文件夹,并将【index.jsp】文件剪贴到里面:

第四步:更新资源重启服务器,访问 localhost/hello 路径,看到正确效果。

原理:

我们传入的逻辑视图名为 index ,再加上 “/WEB-INF/page/” 前缀和 “.jsp” 后缀,就能确定物理视图的路径了,这样我们以后就可以将所有的视图放入【page】文件夹下了!

注意:此时的配置仅是 dispatcher-servlet.xml 下的


控制器接收请求数据

使用控制器接收参数往往是 Spring MVC 开发业务逻辑的第一步,为探索 Spring MVC 的传参方式,为此我们先来创建一个简单的表单用于提交数据:

<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
<html>
<head>
<meta charset="utf-8">
<title>Spring MVC 传参方式</title>
</head>
<body>
<form action="/param" role="form">
用户名:<input type="text" name="userName"><br/>
密码:<input type="text" name="password"><br/>
<input type="submit" value="提 交">
</form>
</body>
</html>

  

使用 Servlet 原生 API 实现:

我们很容易知道,表单会提交到 /param 这个目录,我们先来使用 Servlet 原生的 API 来看看能不能获取到数据:

@RequestMapping("/param")
public ModelAndView getParam(HttpServletRequest request,
HttpServletResponse response) {
String userName = request.getParameter("userName");
String password = request.getParameter("password"); System.out.println(userName);
System.out.println(password);
return null;
}

  

测试成功:

使用同名匹配规则

我们可以把方法定义的形参名字设置成和前台传入参数名一样的方法,来获取到数据(同名匹配规则):

@RequestMapping("/param")
public ModelAndView getParam(String userName,
String password) {
System.out.println(userName);
System.out.println(password);
return null;
}

测试成功:

问题: 这样又会和前台产生很强的耦合,这是我们不希望的

解决: 使用 @RequestParam("前台参数名") 来注入:

@RequestParam 注解细节:
该注解有三个变量:valuerequireddefaultvalue

  • value :指定 name 属性的名称是什么,value 属性都可以默认不写
  • required :是否必须要有该参数,可以设置为【true】或者【false】
  • defaultvalue :设置默认值

使用模型传参

要求: 前台参数名字必须和模型中的字段名一样

让我们先来为我们的表单创建一个 User 模型:

package pojo;

public class User {

    String userName;
String password; /* getter and setter */
}

然后测试仍然成功:

中文乱码问题

注意: 跟 Servlet 中的一样,该方法只对 POST 方法有效(因为是直接处理的 request)

我们可以通过配置 Spring MVC 字符编码过滤器来完成,在 web.xml 中添加:

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<!-- 设置编码格式 -->
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

控制器回显数据

通过上面,我们知道了怎么接受请求数据,并能解决 POST 乱码的问题,那么我们怎么回显数据呢?为此我们在【page】下创建一个【test2.jsp】:

<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" isELIgnored="false" %>
<html>
<head>
<title>Spring MVC 数据回显</title>
</head>
<body>
<h1>回显数据:${message}</h1>
</body>
</html>

使用 Servlet 原生 API 来实现

我们先来测试一下 Servlet 原生的 API 是否能完成这个任务:

@RequestMapping("/value")
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
request.setAttribute("message","成功!");
return new ModelAndView("test1");
}

在浏览器地址栏中输入:localhost/value 测试

使用 Spring MVC 所提供的 ModelAndView 对象

使用 Model 对象

在 Spring MVC 中,我们通常都是使用这样的方式来绑定数据,

使用 @ModelAttribute 注解:

@ModelAttribute
public void model(Model model) {
model.addAttribute("message", "注解成功");
} @RequestMapping("/value")
public String handleRequest() {
return "test1";
}

这样写就会在访问控制器方法 handleRequest() 时,会首先调用 model() 方法将 message 添加进页面参数中去,在视图中可以直接调用,但是这样写会导致该控制器所有的方法都会首先调用 model() 方法,但同样的也很方便,因为可以加入各种各样的数据。

客户端跳转

前面不管是地址 /hello 跳转到 index.jsp 还是 /test 跳转到 test.jsp,这些都是服务端的跳转,也就是 request.getRequestDispatcher("地址").forward(request, response);

那我们如何进行客户端跳转呢?我们继续在 HelloController 中编写:

@RequestMapping("/hello")
public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mav = new ModelAndView("index");
mav.addObject("message", "Hello Spring MVC");
return mav;
} @RequestMapping("/jump")
public ModelAndView jump() {
ModelAndView mav = new ModelAndView("redirect:/hello");
return mav;
}

我们使用 redirect:/hello 就表示我们要跳转到 /hello 这个路径,我们重启服务器,在地址栏中输入:localhost/jump ,会自动跳转到 /hello 路径下:

也可以这样用:

@RequestMapping("/jump")
public String jump() {
return "redirect: ./hello";
}

文件上传

我们再来看一下在 Spring MVC 中如何实现文件的上传和下载

注意: 需要先导入 commons-io-1.3.2.jar 和 commons-fileupload-1.2.1.jar 两个包

第一步:配置上传解析器

在 dispatcher-servlet.xml 中新增一句,开启对上传功能的支持

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

第二步:编写 JSP

文件名为 upload.jsp,仍创建在【page】下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试文件上传</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="picture">
<input type="submit" value="上 传">
</form>
</body>
</html>

第三步:编写控制器

在 Package【controller】下新建【UploadController】类:

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; @Controller
public class UploadController { @RequestMapping("/upload")
public void upload(@RequestParam("picture") MultipartFile picture) throws Exception {
System.out.println(picture.getOriginalFilename());
} @RequestMapping("/test2")
public ModelAndView upload() {
return new ModelAndView("upload");
} }

第四步:测试

在浏览器地址栏中输入:localhost/test2 ,选择文件点击上传,测试成功。

参考资料:

  • 《Java EE 互联网轻量级框架整合开发》
  • 《Spring 实战》

Spring MVC实践的更多相关文章

  1. Spring MVC 实践 - Component

    Spring MVC 实践 标签 : Java与Web Converter Spring MVC的数据绑定并非没有任何限制, 有案例表明: Spring在如何正确绑定数据方面是杂乱无章的. 比如: S ...

  2. Spring MVC 实践 - Base

    Spring MVC 实践 标签 : Java与Web Spring Web MVC Spring-Web-MVC是一种基于请求驱动的轻量级Web-MVC设计模式框架, Spring MVC使用MVC ...

  3. Spring MVC 实践笔记

    1.了解 Maven 的用法:http://spring.io/guides/gs/maven/ .这篇英文非常详细的演示了 Maven 的用法,在命令行下执行.注意,运行Maven的时候,Maven ...

  4. IntelliJ IDEA:Getting Started with Spring MVC, Hibernate and JSON实践

    原文:IntelliJ IDEA:Getting Started with Spring MVC, Hibernate and JSON实践 最近把编辑器换成IntelliJ IDEA,主要是Ecli ...

  5. JSR-303 Bean Validation 介绍及 Spring MVC 服务端参数验证最佳实践

    任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用很多时候同样的数据验证逻辑会出现在不同的层,这样 ...

  6. 搭建Spring4+Spring MVC web工程的最佳实践

    Spring是个非常非常非常优秀的java框架,主要是用它的IOC容器帮我们依赖注入和管理一些程序中的Bean组件,实现低耦合关联,最终提高系统可扩展性和可维护性,用它来辅助我们构建web工程将会感觉 ...

  7. JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践

    任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用在很多时候,同样的数据验证逻辑会出现在不同的层, ...

  8. 基于 Spring MVC 的开源测试用例管理系统以及开发自测的实践

    早前公司领导提出让开发自测,测试么也做做开发.当然了,为了保证自测质量,测试用例仍需测试提供,所以为了提高开发自测的效率和质量,我们开发了捉虫记.捉虫记是一个完整的Spring MVC项目,现已开源, ...

  9. Spring MVC基本配置和实践(一)

    一.Spring MVC介绍 1. Spring MVC是什么? The Spring Web MVC framework和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从S ...

随机推荐

  1. HDU3394 点双连通分量

    Railway Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  2. POJ2431_Expedition_KEY

    题目传送门 由题目可得,在一条路上有N个加油站,在距离终点a[i](细节)的位置上,你需要通过长度为L的路,油箱的容量是无限的,但是初始只有P点油,经过每个加油站时可以选择加b[i]的油,问最少加油几 ...

  3. Java:IDEA设置虚拟机运行时参数

    第一步:打开“Run->Edit Configurations”菜单 第二步:选择“VM Options”选项,输入你要设置的VM参数 第三步:点击“OK”.“Apply”后设置完成

  4. Android Stadio配置了gralde的本地路径,但是windos 命令行还是会下载gradle

    如下图: 已经在stadio 里面设置了gradle 的路径,但是在cmd 命令行里面不会去用这个路径. 解决方案:需要在环境变量里面设置一个gradle home GRADLE_USER_HOME ...

  5. js实现无限级分类

    let arr = [ {id:1,name:"php",pid:0}, {id:2,name:"php基础",pid:1}, {id:3,name:" ...

  6. 使用Google Cloud Messaging (GCM),PHP 开发Android Push Notifications (安卓推送通知)

    什么是GCM? Google Cloud  Messaging (GCM) 是Google提供的一个服务,用来从服务端向安卓设备发送推送通知. GCM分为客户端和服务端开发. 这里我们只介绍服务端开发 ...

  7. DSP5509项目之用FFT识别钢琴音调(1)

    1. 其实这个项目难点在于,能不能采集到高质量的钢琴音调.先看一下FFT相关程序. FFT 并不是一种新的变换,它是离散傅立叶变换(DFT)的一种快速算法.由于我们在计算 DFT 时一次复数乘法需用四 ...

  8. Sql Server Profiler使用

            在使用Entity Framework的过程当中,有时候需要看Entity Framework自动生成的Sql语句,在客户端可以使用跟踪的方法看到每次查询时的Sql语句,其实通过数据库 ...

  9. android 学习十四 探索安全性和权限

    1.部署安全性:应用程序必须使用数字证书才能安装到设备上. 2.执行期间的安全性:    2.1 使用独立进程    2.2 使用固定唯一用户ID    2.3  申明性权限模型   3数字证书   ...

  10. Objective-C 点语法 成员变量的作用域 @property和@synthesize关键字 id类型

    点语法 1.利用点语法替换set方法和get方法 方法调用 Student *stu = [Student new]; [stu setAge : 18]; int age = [stu age]; ...