springMVC基础知识点

Springmvc3.x-->springmvc4.x
1.SpringMvc是什么?
  SpringMvc是框架,具有类似于SSH框架一些特点(分层理念——MVC设计模式,高内聚低耦合,热插拔(组件化),易于扩展,易于维护,配置文档说明设置不同组件的协同关系
  ),SpringMvc侧重于视图和控制器,和Struts2的用途是一致的,但是,目前有些方面优于Struts2框架,比如:采用注解的方式指定POJO类,作为业务控制器,这些POJO类不需
  要实现任何接口,另外,Struts2中Action中业务处理方法被调用时,Action对象都会被创建,系统消耗要大一点。并且,在数据解析、数据格式化、类型转换、数据绑定等方面
  都有不错的表现。Sturts2在视图数据表达时,效率更高(支持OGNL),SpringMvc采用EL表达式。


2.SpringMvc干什么?
  SpringMvc侧重于视图和控制器(业务调度),实现业务调度和业务实现乃至视图表达的分离,让程序更易于维护和扩展。
  特点:
      1)采用注解的方式指定POJO类,作为业务控制器
 
      2)处理器类中的方法对应不同业务处理:在处理器类中,可以有多个业务处理方法,它们显而易见的是隶属于同一个业务模块。
针对同一个Handler类中的不同业务行为,如何在请求时和它们关联呢?可以在每个方法头部添加@RequestMapping注解,只要客户端请求的URL能够和某个具体处理方法
         的@RequestMapping匹配,那么该方法就会被HandlerAdapter调用。


3.怎么用?
  和Struts2的StrutsPrepareAndExecuteFilter核心控制器类似,SpringMvc中也有其中核心业务调度作用的组件,该组件之所谓核心,原因在于在实现接收请求,处理器映射,视
  图表达等阶段,都是由它和其它的组件协同完成的。SpringMvc的核心处理器实际上是一个Servlet,名字叫做SpringDispatcherServlet(DispatcherServlet)。

  初步了解SpringMvc的运行机制:从接收到请求,到响应这样一个完整的过程。
  
  
4.解决实际问题。
  4-1.采用SpringMvc实现一个HelloWorld
      1)创建WEB项目
      2)准备SpringMvc相关Jar包,向Web项目中添加jar包资源。
      3)创建一个SpringMvc配置文件<servletName>-servlet.xml
位置:定义在src根目录下
名字:可以自定义,类型是xml文件
用途:

1.定义Handler类的范围
 <context:component-scan base-package="com.hd.handler"></context:component-scan>


2.配置视图解析器(说明有谁来解析,解析的结果视图目录结构前缀,解析结果的视图后缀)
 InternalResourceViewResolver:具体的视图解析器类,spring-webmvc-4.0.0.RELEASE.jar


 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 物理视图的目录前缀 -->
<property name="prefix" value="/"></property>
<!-- 物理视图的文件后缀 -->
<property name="suffix" value=".jsp"></property>
 </bean>
3.自定义的类型转换器
4.格式转换器

      4)配置web.xml文件-->配置DispatcherServlet(<init-param>)
<init-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:springmvc.xml</param-value>  
  </init-param>
      5)创建具体的Handler处理器,明确其中的业务处理行为以及返回值。
      6)创建物理视图:
         发出请求的场景视图
相应结果视图。
5.注解
  5-1.@PathVariable:用于被访问的Handler的某个业务处理方法的括号中,用于说明该方法URL中的占位符参数的类别
      Synax:
 @PathVariable("xxx") XXXType xxx
      Eg:
  @RequestMapping("/testantsymbol/testUrlAntSymbolPlaceHolder/{goodId}")
  public String queryGood(@PathVariable("goodId") String goodId) {


return "goodinfor";


  }


  5-2.@Controller:控制器注解,加在被认定为Handler控制器的头上。
  5-3.@RequestMapping:跟请求相关的映射注解,有两种用途:
      1)加载类的头部:类的头部可以没有@RequestMapping注解
@Controller
         @RequestMapping("/helloworld")
      2)加在方法的头部:用于说明映射到该方法时的URI特征
@RequestMapping("/hello")
         <p><a href="helloworld/hello">Test hello buz!</a></p>


         a.通配符:如果@RequestMapping中用到了以下通配符,分别用于比较特别URL构成
  a-1.?  :表示一个字符,比如:??表示两个字符
   Eg: /testantsymbol?
       /testantsymbola或者/testantsymbolb或者testantsymbolc
/testantsymbol??
/testantsymbolaa或者/testantsymbolbb...
   @RequestMapping("/query?")
   public ModelAndView testAntSymbol1() {
ModelAndView mav = new ModelAndView();
mav.setViewName("antdemo");
mav.addObject("testAntSymbol1", "testAntSymbol1_?");
return mav;
   }
  a-2.*  : 任意个字符构成一个目录,在路径表达时,是一个目录的名字
   Handler的某个Biz方法的@RequestMapping的定义如下:
   /testantsymbol/*/good
   Client:
   /testantsymbol/abcd/good
  a-3.** :表示两层目录结构结构
  Handler的某个Biz方法的@RequestMapping的定义如下:
   /testantsymbol/**/good
   Client:
   /testantsymbol/ab/cd/good
b.Holder place symbol:占位符参数绑定到业务处理方法中
  <action name="*" method="{1}">
...
  </action>
  URL中可以出现占位符:使用时,其可以被替代为不同的值,也就是说位置固定,参数可变
  Eg:
  Handler的某个业务方法:


  @RequestMapping("/testantsymbol/testUrlAntSymbolPlaceHolder/{goodId}")
  public String queryGood(@PathVariable("goodId") String goodId) {

// 用接收到的goodId去数据库中检索商品对象
...
return "goodinfor";


  }
  Client:
  .../testantsymbol/testUrlAntSymbolPlaceHolder/Batch4001
c.通过请求路径,请求头,请求方法进行映射
  c-1.请求路径,方式
      HTTP请求报文:
      请求行
      请求头
      
               请求参数


      Eg:
      @RequestMapping(value="/path", method=RequestMethod.POST, params={"goodid","userid"})
      public String query() {





      }
 c-2.请求头:注解写在服务器Handler的相关业务行为注解说明中,从而可以将客户端请求时的请求头信息绑定到业务处理方法中
     @RequestHeader注解来实现之
      Synax:
      @RequestMapping(value="/header")
      public String queryHeader(@RequestHeader("Accept-Language") String acceptLanguage,
@RequestHeader("Cookie") String cookie) {


...


      }
      Eg:
               @RequestMapping(value="/header", method=RequestMethod.GET)
public ModelAndView queryHeader(@RequestHeader("Accept-Language") String acceptLanguage,
@RequestHeader("Cookie") String cookie) {
// 创建ModelAndView对象
ModelAndView mav = new ModelAndView();
// 将客户端请求头信息添加到mav
mav.addObject("language", acceptLanguage);
mav.addObject("cookie", cookie);
// 设定逻辑视图
mav.setViewName("httprequest");
return mav;
      }
 c-3.@CookieValue:使用@CookieValue绑定请求中cookie值到处理器业务方法中
     和@RequestParam类似,也有value,required,defaultValue
     @RequestMapping(value="/cookie")
     public String queryCookie(@CookieValue("JSESSIONID") String sessionId) {


...


     }


  5-4.@RequestParam:映射请求时的参数,可以将请求参数绑定到业务处理方法参数中
      @RequestParam(value="name", required=false, defaultValue="zs") String name
      三个参数:
      1) value:参数名
      2) required:true 或者 false
      3) defaultValue:默认值,在不是必须出现参数时,给予默认值
要想使用默认值,两个要求:
         a.服务器控制器处理方法前:某某参数required取值为false
  @RequestParam(value="userid", required=false, defaultValue="008")
b.在客户端发出请求时,URL中不能提供userid参数
  helloworld/other?goodid=James
  


6.ModelAndView: Handler业务处理之后结果模型对象,其中包含Model数据模型,也包括响应视图(逻辑结果)
  6-1.Constructor:
      ModelAndView mav = new ModelAndView();
  6-2.Methods:
      1)setViewName(viewName):设置ModelAndView的逻辑视图名字
      2)addObject(key, value):向ModelAndView对象集合中添加key-value.

  Synax:
  
  public ModelAndView xxx() {


...
// 创建ModelAndView对象
ModelAndView mav = new ModelAndView();
// 向ModelAndView对象中添加逻辑视图



// 向ModelAndView对象中添加数据模型(某某对象),用到setObject(key,value)


// 返回ModelAndView对象


  }
7.将ModelAndView甚至web相关内置对象(pageScope,requestScope,sessionScope,applicationScope)作用域中的数据渲染到视图中,采用EL表达式
  Synax:
${elexpression }
  Eg:
        helloWorld2:${helloWorld2 } <br/>
helloWorld2_status:${helloWorld2_status }<br/>
helloWorld2_score:${helloWorld2_score+1 } <br/>

8.将客户端请求信息封装到处理器业务方法的参数对象
  要求:客户端的请求参数名要和生成的对象属性相同
  注意:客户端的请求参数可以少于绑定对象类型的属性,而且,要求客户端参数一定要在处理器业务参数对象的相关属性一致。
        如果服务端绑定信息对象的某个属性是个自定义类型(而非基本数据类型以及String),客户端控件表达时,采用链式表达式(xxxattribute.subclassattribute....)
        对应到控件的name属性。
        
  Eg:模拟注册客户应用
  1)定义客户实体类,明确客户相关信息:Customer.java
  2)创建一个客户端程序:register.jsp
     通过表单控件名字和Customer类属性相关
  3)定义一个客户管理处理器类,明确注册业务:指定URL要求
     @RequestMapping(value="/register", method=RequestMethod.POST)
public ModelAndView registerCustomer(Customer customer) {
// 创建ModelAndView对象
ModelAndView mav = new ModelAndView();
// 将customer添加到ModelAndView对象
mav.addObject("customer", customer);
// 明确逻辑视图
mav.setViewName("customerinfor");

// 返回ModelAndView
return mav;
}
  4)定义一个显示注册客户对象信息的视图:customerinfor.jsp
     采用EL表达式,取出映射请求时,绑定到注册业务参数对象的信息
  5)装载运行register.jsp,触发提交按钮


9.乱码问题解决方案汇总
  1)查看页面头部是否符合要求:否则修改
     <%@ page language="java" contentType="text/html; charset=UTF-8"%>
  2)查看WEB容器(Tomcat/conf/server.xml)
     <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8" redirectPort="8443"/>
  3)SpringMvc中乱码:在web.xml文件中,添加一个用于对请求信息编码的过滤器CharacterEncodingFilter
     <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>
  Class Task:模拟一个商品管理模块,其中有添加商品业务。
10.SpringMvc访问Servlet API
   实现机制:很多工作都是有SpringMvc框架实现的,对于那些Servlet Api对象来说,通过非常简单的方式就可以获得它们引用。
    在Handler处理器类以及对应业务处理行为中实现内置对象的引用。
   @Controller
   @RequestMapping("/handlermapping")
   public class Handler {


...
@RequestMapping("/controllermapping")
public ModelAndView controller() {






}


   }
   ServletAPI:
   10-1.HttpServletRequest: request
WebUtils类,辅助类,其中的findParameterValue方法,可以获得请求对象中的请求参数。


@RequestMapping("/controllermapping")
public ModelAndView controller(HttpServletRequest request) {


Object obj = WebUtils.findParameterValue(request, "paramName");


}
@RequestMapping(value="/controllermapping", method=RequestMethod.GET)
public ModelAndView controller(HttpServletRequest request) {
String userId = request.getParameter("userid");
String pwd = request.getParameter("pwd");
ModelAndView mav = new ModelAndView();
mav.addObject("userId", userId);
mav.addObject("pwd", pwd);
mav.setViewName("servletapiresult");
return mav;


}
   10-2.HttpServletResponse:
@RequestMapping("/controllerresponse")
public ModelAndView controllerResponse(HttpServletResponse response) {


}
        @RequestMapping("/controllerresponse")
public ModelAndView controllerResponse(HttpServletResponse response) {
PrintWriter printWriter = null;
try {
printWriter = response.getWriter();
printWriter.write("I love springmvc!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (printWriter != null) {
printWriter.close();
}
}
return null;
}
@RequestMapping("/controllerresponse")
public void controllerResponse(HttpServletResponse response) {
PrintWriter printWriter = null;
try {
printWriter = response.getWriter();
printWriter.write("I love springmvc!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (printWriter != null) {
printWriter.close();
}
}

}
   10-3.HttpSession:
@RequestMapping("/controllersession")
public ModelAndView controllerSession(HttpSession session) {


}
@RequestMapping("/controllersession")
public ModelAndView controllerSession(HttpSession session) {
Address home = new Address("Henan", "Zhengzhou");
Customer customer = new Customer("James", "Man", 31, home);
session.setAttribute("cus", customer);
ModelAndView mav = new ModelAndView();
mav.addObject("customer", customer);
mav.setViewName("servletapiresult");
return mav;
}


        @RequestMapping("/controllerall")
public ModelAndView controllerAll(HttpServletRequest request, HttpServletResponse response,
HttpSession session) {
System.out.println(request);
System.out.println(response);
System.out.println(session);
return null;
}
11.RequestMethod四个常量:POST,GET,PUT.DELETE,代表不同的请求
   Springmvc实现REST中的GET、POST、PUT和DELETE
   GET、POST、PUT和DELETE四种请求方法分别代表了数据库CRUD中的
   select、insert、update、delete
   11-1.Client:
   1)GET请求,通过表单或超链接
   <p><a href="restmethod/restget?cid=1">Send Get(select)</a></p>
   2)POST,PUT,DELETE请求,都要用表单,而且表单method的取值都是post
     对于PUT,DELETE请求,表单中都要加一个hidden隐藏域,而且name的取值必须是_method,value 取值为PUT或DELETE
     a.post
       <form action="restmethod/restpost" method="post">
<input type="text" name="cid" value="2"/>
<input type="submit" value="Insert"/>
       </form>
     b.put
       <form action="restmethod/restput" method="post">
       <input type="hidden" name="_method" value="PUT"/>
<input type="text" name="cid" value="3"/>
<input type="submit" value="Update"/>
       </form>
     c.delete
       <form action="restmethod/restdelete" method="post">
<input type="hidden" name="_method" value="DELETE"/>
<input type="text" name="cid" value="4"/>
<input type="submit" value="Delete"/>
       </form>
   11-2.在web.xml文件中,添加对于hidden隐藏域的过滤器,用于区分不同的请求
org.springframework.web.filter.HiddenHttpMethodFilter
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>


<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


   11-3.Handler:
@RequestMapping(value="/restget", method=RequestMethod.GET)
public ModelAndView get(@RequestParam("cid") Integer cid) {
ModelAndView mav = new ModelAndView();
mav.addObject("selectinfor", "Prepare select custNo=" + cid);
mav.setViewName("restresult");
return mav;
}
@RequestMapping(value="/restpost", method=RequestMethod.POST)
public ModelAndView post(@RequestParam("cid") Integer cid) {
ModelAndView mav = new ModelAndView();
mav.addObject("insertinfor", "Prepare insert custNo=" + cid);
mav.setViewName("restresult");
return mav;
}
@RequestMapping(value="/restput", method=RequestMethod.PUT)
public void put(@RequestParam("cid") Integer cid, HttpServletResponse response) {
/*ModelAndView mav = new ModelAndView();
mav.addObject("updateinfor", "Prepare update custNo=" + cid);*/
// mav.setViewName("restresult");

try {
response.getWriter().write("Prepare update custNo=" + cid);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@RequestMapping(value="/restdelete", method=RequestMethod.DELETE)
public void delete(@RequestParam("cid") Integer cid, HttpServletResponse response) {
try {
response.getWriter().write("Prepare delete custNo=" + cid);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


12.Dao类如何结合Handler处理器,来协同完成业务?
   MVC体系中,一直都是需要分层,Dao类就是Model层,主要负责业务实现,调度是Controller(Handler)
   12-1.@Repository:添加在相关业务实现类的头部,这是一种Dao类的注解
   12-2.@Autowired:添加在Handler中的可以驱使的那些Dao属性变量的头部。注意:在Handler类中对应相关的Dao属性,不需要给它们添加GET和SET方法,只需要写@Autowried
@Autowired
private CustomerDao customerDao;


13.SpringMvc静态资源的访问
   SpringMVC访问静态资源的三种方式
   13-1.解决方法:在web.xml里添加如下的配置——利用default servlet,把静态资源的映射业务承担过去


<servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>*.css</url-pattern>
</servlet-mapping>
 
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.gif</url-pattern>


  </servlet-mapping>
    
  <servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>*.jpg</url-pattern>
  </servlet-mapping>
    
  <servlet-mapping>
      <servlet-name>default</servlet-name>
      <url-pattern>*.js</url-pattern>
  </servlet-mapping>
  13-2.解决方法2:在spring的配置文件中添加如下一行:


       <mvc:default-servlet-handler/>
  13-3. <mvc:resources mapping="/resources/**" location="/resources/" /> 


14.内部跳转:forward
15.重定向:redirect
   @RequestMapping(value="/login", method=RequestMethod.POST)
public String loginValidate(@ModelAttribute("customer") Customer customer) {

// 调度CustomerDao类对象来处理登录业务
boolean flag = customerDao.login(customer);
// 如果是合法用户,转到index.jsp
if (flag) {
return "forward:/index.jsp";
} else {
// 否则,是非法用户,转到login.jsp
return "redirect:/login.jsp";
}

}
   
16.国际化资源:为了让程序具有更好的适应性,视图文字自动适应所在的语言环境,提高用户感受,界面友好自适应。
   16-1.准备国际化资源文件:文件是properties,文件内容是key=value这样的键值对,不同的文件,key是一样的,值不一样书写格式:
开发时,将若干资源文件存储在src根目录下。

key1=value1
key2=value2
...

        1)源文件:message.properties
  
        2)某种语言文件(文件名前缀和源文件一致):fileName_语言缩写标识_国家的标识.properties
  Eg:中文的资源文件
           message_zh_CN.properties
  message_en_US.properties
Eg:
  message.properties
  custName=CustomerName
custPwd=CustomerPwd
  message_zh_CN.properties
  custName=用户名
custPwd=密码
  message_en_US.properties
custName=CustomerName
custPwd=CustomerPwd
   16-2.在视图文件中,将那些key添加到视图相应位置。
1)现在在视图页面的指令区域,导入相关的标签库:
  <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
2)在视图中指定位置,通过<spring:message code="xxxkey" />


  <spring:message code="custName" ></spring:message>
   16-3.自定义一个spring-context.xml文件中添加bean标签,用于说明资源文件是谁
        <!-- 明确本项目中资源文件是谁 -->
属性:<property name="basename" value="就是资源文件的前缀"/>
<context:component-scan base-package="com.hd.netstore"></context:component-scan>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="message"></property>
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
   16-4.在web.xml文件中,通过<context-param>标签将spring-context.xml包含进来,为了将资源文件中涉及到的键值对装在到Map集合中
<!-- 加载国际化配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


17.表单验证:采用验证注解,已非常简单的方式实现数据验证。
   明确:表单验证消息需要利用表单发出请求时那个request对象。
   SpringMvc表单验证步骤:
   1)添加jar包:利用的是Hibernate的jar包。
      classmate-0.8.0.jar
      commons-logging-1.1.1.jar
      hibernate-validator-5.0.0.CR2.jar
      hibernate-validator-annotation-processor-5.0.0.CR2.jar
      jboss-logging-3.1.1.GA.jar


   2)表单页面:login.jsp (表单信息可以绑定到业务处理器行为的参数对象——>表单控件名字要和实体类的属性一致!!!)
      要用form标签,导入标签库:
      <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
      <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
      <!-- 添加request必须一个用于回显验证信息的属性对象(目标类型) -->
      <jsp:useBean id="customer" class="com.hd.netstore.entity.Customer" scope="request"></jsp:useBean>
      <form:errors path="*"></form:errors> path的取值如果为"*",表示取出所有的验证消息。


      <form:form action="" method="" modelAttribute="customer">

      error information :   Neither BindingResult nor plain target object for bean name 'customer' available as request attribute
      Attributes:
      a.action:服务器处理器URI
      b.取值就是你要转化的参数对象名字(就是所在类的类名,但是首字母小写)
modelAttribute:customer
        commandName:
      SubTag:
      a.<form:input path="xxxattributeName"/>:相当于表单控件<input type="text" name="xxxattributeName"/>
为了能够回显验证消息,在每个控件的旁边添加一个回显信息标签:<form:errors path="xxxattributeName" />
      

   3)实体类(表单信息可以绑定到业务处理器行为的参数对象类型!!!),在实体类的属性上方添加验证注解(采用不同的注解类对应不同的实体类属性)
      Customer.java
      public class Customer {



private String custNo;
@NotEmpty(message="用户名不能为空!")
private String custName;
@Length(min=6,max=10,message="the lenght is between 6 and 10")
private String custPwd;
// @Digits(message="", fraction = 0, integer = 0)
private int custAge;
// @Email(message="ewg")
private String custGender;


      }
   4)业务处理器类(业务处理方法)
      @Controller
      @RequestMapping("/userhandle")
      public class UserHandler {

@Autowired
private UserDao userDao;

@RequestMapping("/validate")
// @Valid:该注解添加在被绑定对象属性的前面,用于说明该类型是一个验证实体类
// Customer customer: 用于接收客户端传来的参数,封装到一个名字叫做customer变量中,变量名可以随意。
// BindingResult: 在接收客户端请求的过程中,很多信息都封装在其中,比如:验证错误信息(格式是键值对--> xxxAttributeName:message)
  方法:
  1)getErrorCount():返回值是一个整数,表示目前在验证信息的过程中,出错的验证消息值对个数,如果大于零,说明验证有问题。
  2)getFieldErrors():返回一个验证错误信息键值对对象集合。
  类型:
  1)FieldError:验证错误信息键值对对象
     方法:
     a.getField():控件的名字
     b.getDefaultMessage():验证消息

      public ModelAndView loginValidate(@Valid Customer customer, BindingResult result) {

ModelAndView modelAndView = new ModelAndView();
boolean flag = userDao.login(customer);
// 判断是否有验证错误消息
if (result.getErrorCount() > 0) {
// 为了让客户端页面显示验证信息,必须保证目前的customer回显到客户端request对象的customer属性,所以采用内部跳转
// 调用业务实现类userDao进行判断

if (!flag) {
modelAndView.setViewName("forward:/login.jsp");
} else {


modelAndView.setViewName("forward:/index.jsp");
}

} else {


modelAndView.setViewName("forward:/index.jsp");


}
      }
      }
   5)springmvc.xml文件中进行配置:说明国家化资源的出处
      前提:在web.xml文件中添加
      <!-- 加载国际化配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
      添加在pringmvc.xml文件中
      <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">   
     
      <!--   其中basename用来指定properties文件的通用名
              如实例中的message_en_US.properties,message_zh_CN.properties通用名都是message
      -->
      <property name="basename" value="message"/>
      <property name="useCodeAsDefaultMessage" value="true" />
      <property name="encoding" value="UTF-8"></property> ???
      </bean> 
      Attributes:
      a.<property name="basename" value="message"/>:basename是关键字,value值是国际化资源文件的名字(message.properties,message_zh_CN.properties,message_en_US.properties)



   6)利用国际化资源文件添加验证信息:
      在国际化资源文件中如何书写验证类型属性的消息?

      <form:input path="xxxattributeName"/>
      Synax:

XXXAnnotationName.验证类名字(首字母小写).path中的名字= value
      Eg:
         NotEmpty.customer.custName=custName!!!
         Length.customer.custPwd=custPwd!!!

         NotEmpty.customer.custName=custName!!!
Length.customer.custPwd=custPwd!!!


NotEmpty.customer.custName=\u7528\u6237\u540D\u4E0D\u80FD\u5C11
Length.customer.custPwd=\u5BC6\u7801\u4E0D\u5BF9\u554A\uFF01


   注意:在实体类属性注解消息和国际化消息并存的情况下,以国际化资源文件消息优先!!!

18.拦截器:Interceptor,拦在处理器之前以及之后执行的一些操作,类似于J2EE中的filter,它可以决定它所拦截的请求是否继续,并且还可以进行一些修改操作。
   SpringMvc拦截器,通过boolean类型的返回值,如果为true,它所拦截的处理器就会收到请求,如果为false,所访问的处理器处理业务就会被拦截。
   18-1.接口:HandlerInterceptor


/**
  * afterCompletion,用于撤销系统资源
  * 通过boolean类型的返回值,如果为true,它所拦截的处理器就会收到请求,如果为false,所访问的处理器处理业务就会被拦截
  */
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {


}
/**
  * postHandle是在被拦截的处理器业务执行之后,执行的业务
  * 通过boolean类型的返回值,如果为true,它所拦截的处理器就会收到请求,如果为false,所访问的处理器处理业务就会被拦截
  */
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {


}

         /**
  * preHandle是在被拦截的处理器执行之前执行的业务
  * 通过boolean类型的返回值,如果为true,它所拦截的处理器就会收到请求,如果为false,所访问的处理器处理业务就会被拦截
  */
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
...
return true;
}
   18-2.自定义拦截器:
public class ExplainInterceptor  implements HandlerInterceptor { 
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("afterCompletion...");

}


public void postHandle(HttpServletRequest request, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
request.setAttribute("SubJames", "subJames");
System.out.println("postHandle...");

}


public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
String custName = request.getParameter("custName");
System.out.println("requst-->custName:" + request.getParameter("custName"));
System.out.println("preHandle...");
if (custName.equals("James")) {
return false;
} else {
return true;
}

}
}
    18-3.拦截器的配置:
         1)在springmvc.xml文件中配置
2)配置时的标签:
   <mvc:interceptors>
<bean class="com.hd.netstore.interceptors.ExplainInterceptor"></bean>
<!-- <bean class="com.hd.netstore.interceptors.FirstInterceptor"></bean> -->
<!-- <mvc:interceptor>
<mvc:mapping path="/**"/> 
<mvc:exclude-mapping path="/customerhandler/login"/>
<bean class="com.hd.netstore.interceptors.SecondInterceptor"></bean>

</mvc:interceptor> -->


   </mvc:interceptors>
            a.<mvc:interceptors>:拦截器栈,里面配置具体的拦截器信息
     如果<mvc:interceptors>标签里面有个裸漏的<bean class="package.xxxInterceptor"/>,那么<bean class="package.xxxInterceptor"/>将拦截所有
     业务处理。
   b.<mvc:interceptor>:具体的拦截规则
     /**的意思是所有文件夹及里面的子文件夹
     /*是所有文件夹,不含子文件夹
     /是web项目的根目录


     <mvc:mapping path="/customerhandler/login"/> mvc:mapping的path属性可以用到*等通配符,也可以在path明确URI
     (1)拦截器拦截指定的业务处理器
              <mvc:interceptor>
<mvc:mapping path="/**"/> 
<bean class="com.hd.netstore.interceptors.SecondInterceptor"></bean>

     </mvc:interceptor>
     (2)拦截器不拦截的业务处理器
     <mvc:interceptor>
<mvc:mapping path="/**"/> 
<mvc:exclude-mapping path="/customerhandler/login"/>
<bean class="com.hd.netstore.interceptors.SecondInterceptor"></bean>
     </mvc:interceptor>
   Class task:对于登录业务,在登录请求传递到登录业务处理之前,先检查用户名和密码,如果合法转到登录业务处理器,并且写登录信息到公共类的属性中,如果不合法,直接
              终止登录请求。

19.异常处理:程序运行过程中的不正常的现场,如果程序未加处理,系统处理,系统的处理方式比较粗暴——关掉程序。
   如果希望程序健壮性,就需要预估异常,解决异常。
   SpringMvc框架体系中的异常处理:专门定义了一个接口HandlerExceptionResolver,该接口中只有一个方法resolveException(request, response, handler, Exception ex)
   HandlerExceptionResolver有四个实现类,分别应对不同异常处理。
   1)DefaultHandlerExceptionResolver: 默认的异常处理,SpringMvc默认安装了DefaultHandlerExceptionResolver,用于解决那些它可以处理异常。
      对于用户来说,只需要了解它所能解决的异常类的类型以及,响应状态码:
      NoSuchRequestHandingMethodException        404
      ...


      在web.xml文件中通过<error-page>标签设置异常处理,往往是有处理结果(视图表达)
      <error-page>
<error-code>404</error-code>
<location>/xxxview</location>
      </error-page>
   2)AnnotationMethodHandlerExceptionResolver:异常处理方法只能处理其所在类的那些异常
      异常发生之后,通过事先定义好的异常处理方法(通过注解说明)实现处理
      @ExceptionHandler({NullPointerException.class, ArithMeticException.class...})
      // Exception ex参数用于引用系统捕获的异常对象
      public ModelAndView exceptionResolver(Exception ex) {
System.out.println("异常:" + ex.getMessage());
ModelAndView mav = new ModelAndView();
mav.addObject("exception", ex.getMessage());
mav.setViewName("errorinfor");
return mav;
      } 
      在一个类的内部,定义异常处理方法步骤:
      a.在方法的头部,添加注解( @ExceptionHandler),并且明确该异常处理方法可以捕获的异常类型。
@ExceptionHandler(异常类的运行时类列表)
有两种异常类的运行时类列表表达方式:
a-1.如果要捕获的异常种类有多个:
            @ExceptionHandler({NullPointerException.class, ArithmeticException.class})
a-2.如果要捕获的异常种类有一个:
            @ExceptionHandler(NullPointerException.class)




      b.定义一个有视图返回以及数据模型信息的异常处理方法,该方法要准备一个接收一场对象的参数(异常类的父类)。
@ExceptionHandler({NullPointerException.class, ArithmeticException.class})
public ModelAndView xxxResolver(Exception ex) {


// 异常处理语句;
ModelAndView mav = new ModelAndView();
mav.addObject("exception", ex);
// 决定异常处理的视图页面(显示异常信息)
mav.setViewName("exceptioninfor");
return mav;
}


      c.异常信息视图
xxx.jsp----> exceptioninfor.jsp
Content:采用EL表达式,展示异常信息
   3)通过一个类(专门用于异常处理的类)来实现异常处理:在定义的类的头部添加注解——@ControllerAdvice
      
      
      a.定义异常处理类:
@ControllerAdvice
public class PersernalExceptionHandler {

@ExceptionHandler({NullPointerException.class, ArithmeticException.class})
public ModelAndView exceptionResolver(Exception ex) {
System.out.println("异常:" + ex.getMessage());
ModelAndView mav = new ModelAndView();
mav.addObject("exception", ex.getMessage());
mav.setViewName("errorinfor");
return mav;
}
}
      b.在类的内部定义异常处理方法:


@ExceptionHandler({NullPointerException.class, ArithmeticException.class})
public ModelAndView exceptionResolver(Exception ex) {
System.out.println("异常:" + ex.getMessage());
ModelAndView mav = new ModelAndView();
mav.addObject("exception", ex.getMessage());
mav.setViewName("errorinfor");
return mav;
}
   4)通过springmvc.xml文件配置异常处理类对象:


      a.在springmvc.xml中配置,设定异常处理策略:


      <!-- 异常统一处理配置 -->
<bean id="handleExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">

<property name="exceptionMappings">
<props>
<!-- prop的设置用于明确什么异常对应什么视图 -->
<prop key="java.lang.ArithmeticException">errorinfor</prop>
<prop key="java.lang.NullPointerException">errorinfor</prop>
...
</props>
</property>
</bean>
      b.异常处理视图页面如何显示异常信息?
        采用EL表达式显示异常信息: ${exception }




20.上传:采用SpringMvc中的方式上传
   20-1.添加jar包:来自于Struts2
commons-fileupload-1.3.jar
        commons-io-2.0.1.jar
   20-2.配置web项目的springmvc.xml文件:
添加一个用于上传文件的Reslover对象:spring-web-4.0.0.RELEASE.jar-->org.springframework.web.multipart.commons
<!-- upload settings -->
<bean id="multipartResolver"  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="102400000"></property>
</bean>
   20-3.编写客户端页面(负责获得客户端的上传文件)
<form action="" method="" enctype="multipart/form-data" >
  <input type="file" name="file"><br> 
  <input type="submit" value="submit">
</form>
   20-4.编写上传业务处理器
@Controller
@RequestMapping("/mvc")
public class UploadHandler {

@RequestMapping("/upload")
public String upload(HttpServletRequest req) {
// 采用SpringMvc中新增的一个请求对象(对req进行转化)
MultipartHttpServletRequest mreq = (MultipartHttpServletRequest) req;
// 获得客户端上传文件对象
MultipartFile file = mreq.getFile("来自于客户端file控件");
// 获得上传文件的文件名(为了获得文件名后缀)
String fileName = file.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf("."));
// 准备一个写文件的输出流对象(获得web站点存放上传文件的路径)
String webRoot = req.getSession().getServletContext().getRealPath("/");
String uploadRoot = webRoot + "/upload/";
SimpleDateForamt sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String newFileName = sdf.format(new Date()) + suffix;
FileOutputStream fos = new FileOutputStream(uploadRoot + );
// 用输出流对象,调用write方法,将file文件的字节流写到上传文件(文件命名采用日期字符串+文件后缀)的路径
fos.write(file.getBytes());
// 关闭流
fos.flush();
fos.close();
// 返回逻辑
return "uploadstatus";


}




}




   
  



猜你喜欢

转载自blog.csdn.net/aa15237104245/article/details/80468943
今日推荐