一、Spring MVC 验证

JSR 303 是ajvaEE6 中的一项子规范 ,叫 Bean Validation 用于对javaBean中的字段进行校验。

官方的参考实现是: Hibernate Validator ,此实现和 Hibernate ORM 没有任何关系  //http://hibernate.org/validator

Spring 3.x 也大力支持     JSR 303,使用的是  Hibernate Validator

1) 导包

4.3.1.Final 版本为例

// jboss-logging-3.1.0.CR2.jar

hibernate-validator-4.3.1.Final.jar

jboss-logging-3.1.0.jar、

validation-api-1.0.0.GA.jar

2) 配置文件

<mvc:annotation-driven validator="validator" />

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<property name="validationMessageSource" ref="validatemessageSource"/> //不设置则默认为classpath下的 ValidationMessages.properties
</bean> <bean id="validatemessageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:validatemessages"/> //配置验证信息资源文件的路径
<property name="fileEncodings" value="utf-8"/>
<property name="cacheSeconds" value="120"/> //缓存时间
</bean>

3) 创建校验信息用的资源文件,本例在类路径(src或config)下直接创建即可

validatemessages.properties 内容

name.not.empty=名字不能为空

age.not.inrange=年龄要在合适的范围内

email.not.correct=邮箱格式不正确

email.not.empty=邮箱不能为空

4) 在实体类上,添加校验

 public class UserInfo {
private int id; @NotNull(message="用户名不能为 null")
@NotEmpty(message="{name.not.empty}")
@Pattern(regexp="13\\d{9}",message="用户名是按手机验证的格式不对")
private String userName; @Size(min=3,max=6,message="{password.not.inrange}")
private String password; @NotEmpty(message="{email.not.empty}")
@Email(message="{email.not.correct}")
private String note;
private String aihao; //也可以将规则添在get 方法上

5) 控制器

//在添加用户这个请求提交上来的时候
@RequestMapping(value="/addUser" ,method=RequestMethod.POST)
public String addUser(Model model, @Valid UserInfo user,BindingResult bResult){
if(bResult.hasErrors()){
List<ObjectError> errorList= bResult.getAllErrors();
for(ObjectError e:errorList){
System.out.println(e.getDefaultMessage());
} model.addAttribute("errorList",errorList); //把错误信息传到前台
return "user_add";
} else{
return "success";
}
}

说明: BindingResult 是Errors的子类

@Valid  和  BindingResult 的位置不要写反

@Valid  写成了 @Validated 实测也可以

6) 前端页面

<c:forEach var="e" items="${errorList }">
${e.defaultMessage}
</c:forEach> <form action="${pageContext.request.contextPath }/addUser" method="post">
账号: <input type="text" name="userName" />
密码: <input type="text" name="password" />
备注: <input type="text" name="note" />
<input type=submit value="提交" />
</form>

例子 如何详细的显示出错信息

新建页面 user_add_validate.jsp

 <%@ taglib uri="http://www.springframework.org/tags/form" prefix="x" %>
<x:form method="post" action="${pageContext.request.contextPath }/addUser">
账号:<x:input path="userName" /> <x:errors path="userName" /><br>
密码:<x:input path="password" /> <x:errors path="password" /> <br>
备注:<x:input path="note" /><x:errors path="note" /> <br>
<input type=submit value="提交" />
</x:form>

问题:

1) 如果直接访问  user_add_validate.jsp 出现错误

//java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?

原因是Spring环境没初始化

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

2) 需要指定  modelAttribute="user" 这个属性

<x:form method="post" action="${pageContext.request.contextPath }/addUser" modelAttribute="user"  >
//上面也可以写成 commandName="user"

3) 不能直接访问 user_add_validate.jsp 要这样:

@RequestMapping(value="/addUser",method=RequestMethod.GET)
public String addUser(@ModelAttribute("user") UserInfo user){ //@ModelAttribute("user") 必加
return "user_add_validate";
}

4) 添加用户的方法要如下

@RequestMapping(value="/addUser" ,method=RequestMethod.POST)
public String addUser( @ModelAttribute("user") @Valid UserInfo user,BindingResult bResult){
if(bResult.hasErrors()){
return "user_add_validate";
}
else{
return "success";
}
}

附加:

分组校验

问题: 当一个pojo类被多个业务方法使用,但它的验证规则不同,如何处理?

可以采用分组校验

1)定义分组 (其实就是定义接口,空接口就可以,一个接口就是一个分组)

public interface IVG1, IVG2

2)在pojo类上指定校验属于哪个分组

public class UserInfo(
@NotEmpty(message="用户名不能为 null",groups={IVG1.class}) @Size(min=3,max=6,message="{password.not.inrange}",groups={IVG1.class,IVG2.class})
private String password;
...
}

3)在业务方法上指定验证的时候使用哪个分组

@RequestMapping(value="/addUser" ,method=RequestMethod.POST)
public String addUser( @ModelAttribute("user") @Validated(value=IVG1.class) UserInfo user,BindingResult bResult){
if(bResult.hasErrors()){
return "user_add_validate";
}
else{
return "success";
}
}
//注意,用的是 @Validated 注解 不是 @Valid

二、Spring MVC 数据的回显

(其实上例就是带数据回显的)

pojo类型的数据回显

@RequestMapping(value="/addUser" ,method=RequestMethod.POST)
public String addUser( @ModelAttribute("user") UserInfo user){
....
}

页面的 from上也要加 modelAttribute 或 commondName

<x:form action="${pageContext.request.contextPath }/test" method="post" modelAttribute="user">
<x:input path="userName" /> //注意,要回显示的数据必须用 这样的标签
<x:input path="password" />
</x:form>

对于简单类型

用 model.addAttribute(...)  即可

三、Spring MVC 异常处理

SpringMVC 提供全局异常处理器进行统一的异常处理

1) 在controller(Action)内部处理异常

-- login.jsp

 <form action="user/login" method="post" >
账号:<input type="text" name="userName" />
密码:<input type="text" name="password" />
<input type="submit" />

-- 自定义异常类 //不定义也可以

public class MyException extends Exception{
private String msg;
public MyException(String msg){
super(msg);
this.msg=msg;
} public void writeLog(){
System.out.println("---异常信息"+this.msg+"已经记录-");
} }

-- action 中的处理

@RequestMapping(value="/login")
public String login(HttpSession session,String userName,String password) throws MyException {
UserInfo user=new UserDao().getLoginUser(userName, password);
if(user==null){
throw new MyException("用户登录失败"); //如果登录失败,抛出异常
}
session.setAttribute("user", user);
return "success";
} @ExceptionHandler(value={MyException.class}) //这里是进行异常处理的地方
public String exectionProcessAAA(MyException e,HttpServletRequest request){
request.setAttribute("e_msg", e.getMessage());
e.writeLog();
return "error" ; //全局的一个异常处理页面
}

2) 全局异常处理

--在配置文件中加入配置

<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="cat.beans.MyException">error_process_1</prop> //可以看到,可以为每种异常指定一个result视图
<prop key="java.lang.Exception">error_process_2</prop>
<prop key="java.lang.Throwable">error_process_3</prop>
</props>
</property>
</bean>

在异常处理页面

${exception.message}  //这样即可取出异常信息

四、Spring MVC 文件上传

1) 单文件上传

== 在配置文件中

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
<property name="defaultEncoding" value="UTF-8" /> //这里面的这些属性可以不用,一个都不写也不会出错
<property name="maxUploadSize" value="5400000" />
<property name="uploadTempDir" value="uploadTempDir" />
</bean>

== 页面

<form method="post"  action="${pageContext.request.contextPath }/addUserWithImg"    enctype="multipart/form-data" >
<input name="userName" />
<input name="password"/>
<input name="note"/>
<input type="file" name=upfile /> //注意,这个名字
<input type="submit" >
</form>

== 控制层

@RequestMapping(value="/addUserWithImg",method=RequestMethod.POST)
public String addUserWithImg(UserInfo user,MultipartFile upfile /*注意这个名字要和表单元素同名*/ ,HttpServletRequest request )
throws IllegalStateException, IOException{
System.out.println(upfile);
System.out.println("contentType:"+upfile.getContentType()); //image/pjepg
System.out.println("name:"+upfile.getName()); //photo
System.out.println("getOriginalFilename:"+upfile.getOriginalFilename()); //zhangsan.jpg
System.out.println("getSize:"+upfile.getSize()); new UserDao().addUser(user); String path=request.getServletContext().getRealPath("/upload_files");
File targetFile=new File(path, upfile.getOriginalFilename()); upfile.transferTo(targetFile); return "success";
}

2) 多文件上传

<form method="post"  action="${pageContext.request.contextPath }/addUserWithMultImg"    enctype="multipart/form-data" >
<input name="userName" />
<input name="password"/>
<input name="note"/> <input type="file" name=upfiles />
<input type="file" name=upfiles />
<input type="file" name=upfiles />
<input type="file" name=upfiles /> <input type="submit" >
</form>
//注意要加上  @RequestParam
public String ddUserWithMultImg(UserInfo user,@RequestParam("upfiles") MultipartFile [] upfiles ,HttpServletRequest request )
throws IllegalStateException, IOException{
new UserDao().addUser(user);
String path=request.getServletContext().getRealPath("/upload_files"); for(MultipartFile f:upfiles){
if(!f.isEmpty()){
File targetFile=new File(path, f.getOriginalFilename());
f.transferTo(targetFile);
}
} return "success";
}

五、Spring MVC 资源文件的引入

在配置文件中:

<mvc:resources location="/images/" mapping="/images/**" />
<mvc:resources location="/css/" mapping="css/**" />
//也可以放在一个文件夹中,统一的引入,如
<mvc:resources location="/resource/" mapping="resource/**" />

六、Spring MVC 关于json数据处理

1) 传统方式的 ajax访问和响应

//请求发起页面  ajax_test.jsp
$(function(){
$("#btn1").click(function(){
$.ajax({
url:"testAjax",
type:"post",
data:{userName:'admin',password:'123'},
async:false,
cache:false,
dataType:"json",
success:function(data){
//alert(data);
alert(data.id);
alert(data.note);
}
});
});
}); @RequestMapping("/testAjax")
public void testAjax(HttpServletRequest request,HttpServletResponse response) throws IOException{
String userName=request.getParameter("userName");
String password=request.getParameter("password");
System.out.println(userName+":"+password); response.setContentType("text/html;charset=utf-8");
//response.getWriter().print("这是普通数据"); String jsonStr="{\"note\":\"这是备注\",\"id\":\"90\"}";
response.getWriter().print(jsonStr);
}

附注:

@RequestBody 用来处理application/json 类型的请求内容

使用 @ResponseBody 的方式返回json 格式的数据

要导入包 spring mvc 4.1.4

jackson-annotations-2.4.4.jar、

jackson-core-2.4.4.jar、

jackson-databind-2.4.4.jar。

附 3.1 用的是

jackson-core-asl-1.9.11.jar

jackson-mapper-asl-1.9.11.jar

//例一 从服务端查询出一个userInfo对象返回
//服务端
@RequestMapping("/testAjax2") @ResponseBody //这里用 @ResponseBody 注解声明返回json数据
public UserInfo testAjax2(UserInfo u) {
UserInfo user=new UserDao().getLoginUser(u.getUserName(), u.getPassword());
return user;
}
//客户端
$.ajax({
url:"testAjax2",
type:"post",
data:{userName:'aaa',password:'aaa'}, //在服务端,用的是pojo类型的对象接收的参数
async:false,
cache:false,
dataType:"json",
success:function(data){
alert(data.id);
alert(data.note);
}
});
//例二 从服务端查询一组对象返回
@RequestMapping("/testAjax3") @ResponseBody
public List<UserInfo> testAjax2() {
List<UserInfo> userList=new UserDao().getAllUser();
return userList;
} $("#btn3").click(function(){
$.ajax({
url:"testAjax3",
type:"post", async:false,
cache:false,
dataType:"json",
success:function(userList){ //从服务端返回的是一组对象
$.each(userList,function(key,user){
$("#div1").append(user.id +"-"+user.userName+"-"+user.password+"<br />");
});
}
});
});

七、Spring MVC中 RESTful 风格

REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的,HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。长期以来,软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构

REST,即Representational State Transfer的缩写。我们对这个词组的翻译是"表现层状态转化"。

如果一个架构符合REST原则,就称它为RESTful架构。关于 Representational State Transfer (表现层状态转化) 的理解。

1)REST的名称"表现层状态转化"中,省略了主语。"表现层"其实指的是"资源"(Resources)的"表现层"。

网络上的一个具体信息,可以用一个URI(统一资源定位符)指向它

2) Representation 表现层

"资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。

比如,文本可以用txt格式表现,也可以用HTML格式、XML格式

URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的 因为这个后缀名表示格式,属于 "表现层" 范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。

3) State Transfer 状态转化

HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:

GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

综合上面的解释,我们总结一下什么是RESTful架构:

(1)每一个URI代表一种资源;

(2)客户端和服务器之间,传递这种资源的某种表现层;

(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。

http://localhost:8080/myweb/userAction_show.action?id=5

rest 风格

http://www.douban.com/photos/album/49432287/   这是豆瓣上的url rest风格

查询用户

http://localhost:8080/myweb/user/5

删除用户

http://localhost:8080/myweb/user/5/delete

//例子

@RequestMapping("/get_user/{id}/{flag}")
public String getUser(@PathVariable("id") int idAAA, @PathVariable("flag") String flagAAA){
System.out.println(idAAA +":"+flagAAA);
return "success";
}

请求的url

http://localhost:8080/springmvc-03/get_user/10/search

如果不传  PathVariable 指定的参数,会报404

八、Spring MVC 拦截器

SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间。

方式一: 用实现 HandlerInterceptor  接口的方式

方式二: 继承抽象类HandlerInterceptorAdapter  (Spring 提供的类,它实现了 HandlerInterceptor)

方式三: 实现WebRequestInterceptor 接口或继承实现了该接口的类

例子:

1) 拦截器声明

public class MyInterceptor implements HandlerInterceptor {
/*==在Controller 方法被调用之前执行,一般用来进行身份验证,授权等
== SpringMVC中的Interceptor 拦截器是链式的,可以同时存在多个Interceptor,并根据声明的前后顺序依次执行
== 而且所有的Interceptor中的 preHandle 方法都会在 Controller方法调用之前调用
== SpringMVC的这种Interceptor链式结构也是可以进行中断的,preHandle的返回值为false的时候整个请求就结束了 */
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
System.out.println("preHandle");
return true;
} /* 一般在处理公用的模型数据,统一指定视图等操作的时候用
== 在preHandle方法返回值为true的时候才会执行。
== 它的执行时间是在是在Controller的方法调用之后,DispatcherServlet进行视图的渲染之前执行
== 可以对ModelAndView进行操作。
== 这个方法的链式结构跟正常访问的方向是相反的,也就是说先声明的Interceptor拦截器该方法反而会后调用,这跟Struts2里面的拦截器的执行过程有点像
*/
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
} /*
== 在preHandle方法返回值为true的时候才会执行。
== 该方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行,
== 这个方法的主要作用是用于清理资源的,统一的日志及异常处理等 */
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("afterCompletion");
}
}

2) 在配置文件中加入配置

<mvc:interceptors>
//如果有 多个拦截器,顺序执行
<mvc:interceptor>
// 如果不配置或/*,将拦截所有的Controller
<mvc:mapping path="/searchall_forupdate" /> path 配置拦的是请求的url
//<mvc:mapping path="/**" /> 所有的url包扩子url
<bean class="cat.interceptor.MyInterceptor"></bean>
</mvc:interceptor> </mvc:interceptors>
//例子,验证用户是否登录
public class MySessionInterceptor implements HandlerInterceptor {
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception { } public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object handler, ModelAndView arg3) throws Exception {} public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object obj) throws Exception {
String url=request.getRequestURI();
System.out.println(url);
if(url.contains("login")){ //如果用户发的是登录的请求,则直接放行
return true;
}
else{
UserInfo user=(UserInfo)request.getSession().getAttribute("user");
if(user!=null){
return true;
}
else{
request.setAttribute("msg", "请登录");
request.getRequestDispatcher("login.jsp").forward(request, response);
return false;
}
}
}

上面的拦截器的配置文件

<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cat.interceptor.MyInterceptor"></bean>
</mvc:interceptor> <mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cat.interceptor.MySessionInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors> 

Java框架之Spring MVC(二)的更多相关文章

  1. Java框架之Spring MVC(一)

    一.Spring简介 Spring MVC是当前最优秀的 MVC 框架,自从Spring 2.5 版本发布后,由于支持注解配置,易用性有了大幅度的提高.Spring 3.0 更加完善,实现了对 Str ...

  2. Java框架之Spring(二)

    前一篇博客讲述了Spring的一些基础概念,下面我们来创建第一个Spring程序吧. 步骤如下: 1) 导包 2) 配置文件 附没有提示的情况 MyEclipse ->File and Edit ...

  3. java企业架构 spring mvc +mybatis + KafKa+Flume+Zookeeper

    声明:该框架面向企业,是大型互联网分布式企业架构,后期会介绍linux上部署高可用集群项目. 项目基础功能截图(自提供了最小部分)      平台简介        Jeesz是一个分布式的框架,提供 ...

  4. 第63节:Java中的Spring MVC简介笔记

    前言 感谢! 承蒙关照~ Java中的Spring MVC简介笔记 MVC简介 Spring MVC 基本概念 Spring MVC 项目搭建 maven 使用Spring MVC进行开发 实现数据绑 ...

  5. Java方式配置Spring MVC

    概述 使用Java方式配置Spring MVC,以及回顾一下Spring MVC的各种用法. Spring MVC简述 关于Spring MVC的介绍网上有很多,这里就不再赘述了,只是要说一下,Spr ...

  6. 二十一、MVC的WEB框架(Spring MVC)

    一.基于注解方式配置 1.首先是修改IndexContoller控制器类 1.1.在类前面加上@Controller:表示这个类是一个控制器 1.2.在方法handleRequest前面加上@Requ ...

  7. 【Java】关于Spring MVC框架的总结

    SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦.基于请求驱动指的就是使用请求-响应模型,框架的 ...

  8. 玩转Spring MVC(二)----MVC框架

    早期程序员在编写代码时是没有一个规范的,系统的业务逻辑和数据库的访问时混合在一起的,不仅增加了大量的重复工作,而且增加了后期维护的难度. 后来,人们逐渐发现某些通用的功能是可以单独的封装起来的,这样就 ...

  9. 二十、MVC的WEB框架(Spring MVC)

    一.Spring MVC 运行原理:客户端请求提交到DispatcherServlet,由DispatcherServlet控制器查询HandlerMapping,找到并分发到指定的Controlle ...

随机推荐

  1. ExtJs 带参数的MVC

    题记:研究使用ext两个星期了,从痛苦中逐渐走向明朗. 展示列表的子列表的数据时需要将当前的数据传给下一个mvc. 比如用户列表,点击一个用户查看该用户的日志列表. 首先是controller,放一个 ...

  2. JaveScript简单数据类型(JS知识点归纳二)

    JS中的简单数据类型有五种 : --> string --> number -->boolean --> null -->undefined 数据类型的检测 :typeo ...

  3. iOS多线程与网络开发之发送接收server信息

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. (1).使用同步方法发送get请求(不经常使用) 2 /** 发送get消息 */ 3 - (void) testGet { 4 NSString *r ...

  4. Amicable numbers -- Javascript 实现

    问题描写叙述: Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide eve ...

  5. leetcode:程序猿面试技巧

    起因 写在开头,脑袋铁定秀逗了,历时20多天,刷完了leetcode上面151道题目(当然非常多是google的),感觉自己对算法和数据结构算是入门了,但仍然还有非常多不清楚的地方,于是有了对于每道题 ...

  6. JAVA入门[12]-JavaBean

    一.什么是JavaBean JavaBean是特殊的Java类,使用Java语言书写,并且遵守规范: 提供一个默认的无参构造函数. 需要被序列化并且实现了Serializable接口. 可能有一系列可 ...

  7. 自学Zabbix3.8.1.3-可视化Visualisation-Graphs特殊图表

    自学Zabbix3.8.1.3-可视化Visualisation-Graphs特殊图表 虽然一个简单的图表和自定义图标很适合访问一个项目的数据,但这两个都不允许在多个项目中快速创建一个比较图表.为了解 ...

  8. Ubuntu安装微信开发者工具

    参考教程:https://ruby-china.org/topics/30339 1.下载nw sdk $ wget -c http://dl.nwjs.io/v0.15.3/nwjs-sdk-v0. ...

  9. (五):C++分布式实时应用框架——支撑复杂的业务通讯关系

    C++分布式实时应用框架--支撑复杂的业务通讯关系 技术交流合作QQ群:436466587 欢迎讨论交流 版权声明:本文版权及所用技术归属smartguys团队所有,对于抄袭,非经同意转载等行为保留法 ...

  10. 深度优先搜索(DFS)——部分和问题

    对于深度优先搜索,这里有篇写的不错的博客:DFS算法介绍 .总得来说是从某个状态开始,不断的转移状态知道无法转移,然后回到前一步的状态.如此不断的重复一直到找到最终的解.根据这个特点,常常会用到递归. ...