SpringMVC
目录
一、 HelloWorld以及前期相关的配置工作... 3
二、 RequestingMapping修饰类... 4
三、 RequestMapping修饰请求头、请求参数等... 4
四、 RequestMapping支持通配符的情况antPAth. 6
五、 使用PathVariable. 6
六、 HiddenHttpMethodFilter. 6
七、 RequestParam.. 8
八、 请求头RequestHeader. 9
九、 Cookie的值... 9
十、 Object 的使用 经常用到表单形式提交对象的参数... 10
十一、 testServletAPI 10
十二、 处理模型数据的几种方式... 11
1.ModelAndView.. 11
2、ModelMap类型的... 12
3、@SessionAttribute. 12
4、ModelAttribute. 13
十三、 对于原码的追踪失败testInternalResourceResolver. 13
十四、 JSTLResolverResourceView(国际化有问题) 14
十五、 mvc:view-controller. 14
十六、 自定义视图解析器... 15
十七、 测试重定向Redirect. 16
十八、 整合... 17
至于表单的提交的方式的设置... 17
至于form标签的使用... 17
至于介于delete(GET)到DELETE. 18
SpringMVC数据绑定... 19
MVC:annotation-driven. 21
@InitBinder. 22
Hibernate validator验证... 22
国际化验证信息输出的配置... 23
Ajax AND Json. 24
十九、 HttpMessageConvert. 25
@RequestBody / @ResponseBody实现文件的上传... 25
HttpEntity<T> / ResponseEntity<T> 实现文件的下载... 26
二十、 国际化I18N.. 26
二十一、 MultipartResolver文件长传... 28
二十二、 自定义拦截器... 29
二十三、 ExceptionHandlerExecptionResolver异常的捕捉和输出显示... 30
二十四、 @ResponseStatus. 32
二十五、 DefaultHandlerExceptionResolver. 33
二十六、 SimpleMappingExceptionResolver. 33
一、 HelloWorld以及前期相关的配置工作
web.xml文件中需要配置启动加载文件 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<!-- The front controller of this Spring Web application, responsible for handling all application requests --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
</web-app> 那么问题就是:如何配置默认的解析文件的位置呢 以及如何命名 配置详情: 1、 初始化参数不需要配置 2、 配置文件的位置更改为WEB-INF/之下 并且命名的方式是:名字-servlet.xml 3、 其余不变就行了 |
实体类
@Controller public class HelloController {
@RequestMapping("/hello") public String HelloWorld(){ System.out.println("helloworld !"); return "success"; }
} |
二、 RequestingMapping修饰类
@Controller @RequestMapping("/hello1") public class DouleHelloWorld { @RequestMapping("hello") public String helloworld1(){ System.out.println("hello world!"); return "success"; } } 相应的跳转的链接的方式就是 <a href=”hello1/hello”>这是一个跳转</a> |
三、 RequestMapping修饰请求头、请求参数等
/** * 测试方法,定义的方法为post的时候使用get的方法 * 无法处理 */ @RequestMapping(value="/hellomethod",method=RequestMethod.POST) public String testMethod(){ System.out.println("测试方法!"); return "success"; } |
Html界面显示代码
<br><br> <form action="hello1/hellomethod" method="post"> 测试post请求提交<br> <input type="submit" value="提交"/> </form> <br><br> <a href="hello1/hellomethod">test method</a> 错误实现的界面提示的错误显示为: |
请求头参数
/** * 设置指定格式的params 或者是headers * 只有在符合设计的格式的时候才可以实现跳转 * 否则出现报错的现象 * @return */ @RequestMapping(value="/testparam", params = {"username","age!=10"}, headers={"Accept-Language=zh-CN,zh;q=0.8"}) public String testParam(){ System.out.println("testparam"); return "success"; } |
四、 RequestMapping支持通配符的情况antPAth
/** * 使用通配符也可以实现地址实现的跳转 * * 中间可以用任意字符进行填充 * ?匹配一个字符 * *任意字符 * **匹配多层路径 * @return */ @RequestMapping(value="/*/testAntPath") public String testAntPath(){ System.out.println("testAntPath"); return "success"; }
|
五、 使用PathVariable
/** * pathVariable的作用是可以将url中的参数映射到 * 方法中的实际参数 * @param id * @return */ @RequestMapping(value="/testPathVariable/{id}") public String testPathVariable(@PathVariable(value="id") Integer id){ System.out.println("testPathVariable" + id); return "success"; } |
六、 HiddenHttpMethodFilter
首先需要在web.xml文件中进行配置
<!-- 配置 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> |
/** * 测试的是增删改查的实现 * * order/ post 提交 新增一个对象 * order/1 put 更新一个对象 * order/2 get 得到一个对象 * order/3 delete 删除一个对象 * 其中的put delete并不是自身携带的 * 因此查看源代码的时候的值 其中的主要是依靠其中的_method中值 * 来判断是区分于get post 之外的另外两个方法 * @param id * @return */ @RequestMapping(value="/testDelete/{id}",method=RequestMethod.DELETE) public String testDelete(@PathVariable(value="id") Integer id){ System.out.println("testDelete:" + id); return "success"; } @RequestMapping(value="/testPut/{id}",method=RequestMethod.PUT) public String testPut(@PathVariable(value="id") Integer id){ System.out.println("testPut:" + id); return "success"; } @RequestMapping(value="/testPost",method=RequestMethod.POST) public String testPost(){ System.out.println("testPost:"); return "success"; } @RequestMapping(value="/testGet/{id}",method=RequestMethod.GET) public String testGet(@PathVariable(value="id") Integer id){ System.out.println("testGet:" + id); return "success"; }
详细实现的源代码: String paramValue = request.getParameter(this.methodParam); if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) { String method = paramValue.toUpperCase(Locale.ENGLISH); HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method); filterChain.doFilter(wrapper, response); } else { filterChain.doFilter(request, response); } } |
前端有关方法的注释
<br><br> <form action="hello1/testDelete/1" method="POST"> <input type="hidden" name="_method" value="DELETE"/> <input type="submit" value="testDelete"/> </form> <br><br> <form action="hello1/testPut/1" method="POST"> <input type="hidden" name="_method" value="PUT"/> <input type="submit" value="testPut"/> </form> <br><br> <form action="hello1/testPost/" method="post"> <input type="submit" value="testPost"/> </form> <br><br> <a href="hello1/testGet/1">test testGet</a> |
七、 RequestParam
/** * 测试的是 testRequestParam * value : 传入的参数的名字 必须和URL传入的参数的名字一致 但是后面括号中的参数可以不一致 * required:该参数是不是必须携带 默认的true 可以设置成为false * defaultValue:参数在没有携带的时候 使用此设置的默认参数 * @param un * @param age * @return */ @RequestMapping(value="/testRequestParam",method=RequestMethod.GET) public String testRequestParam(@RequestParam(value="username") String un, @RequestParam(value="age",required=false,defaultValue="0") int age){ System.out.println("testRequestParam: username " + un + " age: " + age); return SUCCESS; } |
八、 请求头RequestHeader
代码部分的实现 /** * 请求头的参数的信息 * 一般不经常使用 使用的方式和RequestParam是一样的 * @param al * @return */ @RequestMapping(value="/testRquestHeader") public String testRequestHeader(@RequestHeader(value="Accept-Language") String al){ System.out.println("TestRequestHeader : " + al); return SUCCESS; } 前端的代码部分 <a href="hello1/testRquestHeader">test testRequestHeader</a> |
九、 Cookie的值
实现部分的代码 /** * 映射一个cookie值 获得cookie的值 * 使用的方式和RequestPapam是一样的 * @param sessionid * @return */ @RequestMapping(value="/testCookieValue") public String testCookieValue(@CookieValue(value="JSESSIONID",required=false) String sessionid){ System.out.println("testCookieValue:" + sessionid); return SUCCESS; } 前端实现的代码部分 <a href="hello1/testCookieValue">test testCookieValue</a> |
十、 Object 的使用 经常用到表单形式提交对象的参数
代码段的部分 首先需要创建相应的对象 对象竟然不需要添加任何部分的代码或者注解 竟然支持级联属性 /** * testObject 表单的形式提交对象的参数 * 支持级联属性 使用较为平凡 * 其中级联属性的方式为:User->address address.city的方式进行提交 * @param user * @return */ @RequestMapping(value="/testObject") public String testObject(User user){ System.out.println("testObject : " + user); return SUCCESS; } 前端的表单部分的代码 <form action="hello1/testObject" method="post"> 名字:<input type="text" name="username"/><br> 密码:<input type="password" name="password"/><br> 城市:<input type="text" name="address.city"/><br> 省份:<input type="text" name="address.province"/><br> <button type="submit" value="提交">提交</button> <button type="reset" value="重置">重置</button> </form> |
十一、 testServletAPI
代码的实现部分 /** * 测试ServletAPI的情况 * 参数可以实现为(解释说明org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter) * * * 参数可以是: * HttpServletRequest: * HttpServletResponse * Local * Reader Writer * InputStream OutputStream */ @RequestMapping(value="/testServletAPI") public void testServletAPI(HttpServletRequest request,HttpServletResponse response,Writer out) throws IOException{ System.out.println("HttpServletRequest : " + request + "HttpServletResponse : " + response); out.write("测试ServletAPI的情况"); /*HttpServletRequest : org.apache.catalina.connector.RequestFacade@67959851 * HttpServletResponse : org.apache.catalina.connector.ResponseFacade@40353fac*/ /* return SUCCESS;*/ } |
十二、 处理模型数据的几种方式
1.ModelAndView
/** * 返回值是ModelAndView * 其中ModelAndView 中可以添加模型数据 * @return */ @RequestMapping(value="testModelAndView") public ModelAndView testModelAndView(){ String viewName = "success"; ModelAndView modelAndView = new ModelAndView(viewName); modelAndView.addObject("time", new Date()); return modelAndView; } |
2、ModelMap类型的
/** * 添加模型数据的第二种方式 * model And Map 实现 * 模型数据的填空可以是model或者是modelMap 两者都是可以的 * * @param map * @return */ @RequestMapping(value="testModelAndMap") public String testModelMap(Map<String,Object> map){ System.out.println(map.getClass().getName()); map.put("names", Arrays.asList("licunzhi","xiaojizai","damimi")); return SUCCESS; } |
3、@SessionAttribute
@SessionAttributes(value={"user"} , types={String.class}) @Controller @RequestMapping("/hello1") public class DouleHelloWorld {
private static String SUCCESS ="success"; /** * testSessionAttribute:如果希望在多个请求之间公用一个模型的属性 * 可以在类控制器上增加一个注解属性为:@SessionAttribute * * 简单来说就是以往的modelAndView或者是model map的形式主要是在Request中可以获取到相应的值 * 并不是实际存储在session中 数据只是单一的一次性获取 * * sessionAttribute实现数据存储在实际的session中 并且在session中可以获取到 * 其中:value={}里面存储的是字符串的数组,和实现put进去的存储的名字是一致的 * type={} 可以存储类 多个也是可以的,表示的是存储的内容只要满足这个类型也可以被输出 * @return */ @RequestMapping(value="testSessionAttribute") public String testSessionAttribute(Map<String ,Object> map){ User user = new User("licunzhi","123"); map.put("user", user); return SUCCESS; } |
4、ModelAttribute
/** * 说明:在使用struts中的prepareStatement的时候 * 进行更新数据的时候 ,首先是查询出相应的更新的对象,然后对需要更新的数据的部分进行更新 * 这样就避免了重要的数据在前端使用hidden属性暴露的危险更加安全 * 因此 在SpringMVC中同样有相应的方法对应相应的操作 * @ModelAttribute : 使用的时候会出现sessionAttribute的异常 后面在进行处理 * * 需要注意的是:在牵涉到的该控制其中的所有的方法在调用之前 都会执行一次被modelAttribute修饰的方法 * * 需求说明前端传入数据之后进行回显:原始数据:1,licunzhi,123,licunzhi@163.com * id name password email * @return */ @ModelAttribute public void prepareUser(@RequestParam(value="id",required=false) Integer id,Map<String ,Object> map){ if(id != null){ User user = new User(1, "licunzhi", "123", "licunzhi@163.com"); System.out.println("modelAttribute: " + user + " -----模拟数据库的操作");
map.put("user", user);
} } @RequestMapping(value="testModelAttribute") public String testModelAttribute(User user){ System.out.println("修改 user:" + user); return SUCCESS; }
备注:在名字不一样的的情况下 可以在方法中添加ModelAttribute注解 在注解中标注相应的名字 |
十三、 对于原码的追踪失败testInternalResourceResolver
/** * 模型试图解析器的工作流程 * * @return */ @RequestMapping(value="testInternalResourceViewResolver") public String testInternalResourceViewResolver(){ System.out.println("InternalResourceViewResolver: "); return SUCCESS; } |
十四、 JSTLResolverResourceView(国际化有问题)
编写国际化资源文件在src目录下面 命名方式记住: 文件的国际化的名字可以在浏览器中的语言关键选项里面查询出来 之后需要使用想用的jstl标签 模型视图解析器会自动切换默认的试图解析的方式 采用不用的类进行处理 需要使用国际化的方式需要在配置文件中增加下面的配置 <!-- 配置国际化的效果 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean> 实现之后的问题是 还是出现了中文乱码的问题 |
十五、 mvc:view-controller
<!-- 但是会引起相应的RequestMapping 失去作用 因此出现了解决的办法是:mvc:annotation-driven 实际开发中一般都需要配置 实际作用的含义后面进行补充 现在记住就行了 --> <!-- 配置可以实现不经过handler 直接到相应界面 --> <mvc:view-controller path="/success" view-name="success"/> <!-- 为了解决上面出现的问题 下面配置了 mvc:annotation-driven --> <mvc:annotation-driven></mvc:annotation-driven> |
十六、 自定义视图解析器
自定义视图解析器的作用可以实现按照自定定义进行跳转 尤其是在poi freechart excel上都可以使用 1、 首先需要自定义一个实现View接口的类 //自定义视图渲染器 @Component public class HelloView implements View{
/** * 得到的是返回值的类型 * @return */ @Override public String getContentType() { return "text/html"; } /** * 进行相应的渲染处理操作 * @param model * @param request * @param response * @throws Exception */ @Override public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.getWriter().print("helloView: + " + new Date()); }
//然后在配置文件中进行配置 使用自定义的视图解析的类
} 2、 配置文件中及配置BeanViewResolver <!-- 配置 BeanNameViewResolver 类 实现使用自定的视图解析器类 配置其中的order属性 实现加载的时候首先使用 其中order属性值越小 越是首先被加载 自定义的默认的加载的属性order是maxInteger --> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="100"></property> </bean> 3、 测试类中的代码 @RequestMapping(value="/testView") public String testView(){ System.out.println("testView : "); return "helloView"; } 在这里啊一般需要注意的是有关return的跳转的名字 一般写类型的第一个字母的小写的名字 |
十七、 测试重定向Redirect
代码实现的部分 /** * 默认的是转发的状态 * 可以通过添加redirect的方式实现重定向的方法 * @return */ @RequestMapping(value="/testRedirect") public String testRedirect(){ System.out.println("testRedirect"); return "redirect:/index.jsp"; }
追溯原码。。 |
十八、 整合
至于表单的提交的方式的设置
普通链接的提交的方式是GET请求 Springmvc中可以使用方法使其具备数据库持久化操作的增删改查: <!-- 配置HiddenHttpMethodFilter过滤器 实现post的方法转换成PUT/DELETE--> <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> 实现的方式是通过增加一个拦截器 拦截器会在进入控制器之前 对于表单进行预先的处理--------_method参数的设置等一系列的设置 |
至于form标签的使用
为什么选择使用form标签 优点就是可以简洁开发过程,实际上在世纪的开发过程中并没有多么的简洁,在我看来就是所谓的后端要霸占前端的一个铺垫 而且可以内含表单回显的优势 举例说明 <form:form action="emp" method="POST" modelAttribute="employee"> <!-- 这里的path就相当于标签中的中的 name 属性 --> LastName : <form:input path="lastName"/><br> Email : <form:input path="email"/><br> <% Map<String , Object> genders = new HashMap(); genders.put("1", "male"); genders.put("0", "female"); request.setAttribute("genders", genders);
%> Gender : <br><form:radiobuttons path="gender" items="${genders }" delimiter="<br>"/><br> Departments:<form:select path="department.id" items="${departments }" itemLabel="departmentName" itemValue="id"></form:select> <br><input type="submit" value="提交"/>
</form:form> 其中对于标签经常使用的一些属性做说明 *其中的form标签的modelAttribute属性 必须要求有:目的就是为了和域对象中的属性一一对应 支持级联属性 *path属性:对应的就相当于html标签中的name属性,和域对象的属性的值的名字一致 *itemValue : 标签实际提交的值 *itemLabel :标签上面显示的值 其中的radiobuttons的属性解释: itemLabel:显示在界面的属性的名字 itemValue:实际代码部分的提交属性值 |
至于介于delete(GET)到DELETE
有关静态资源的使用的配置作用:
Rest风格是的URL的默认是没有任何的后缀而言的,但是静态资源一般都是携带后缀名字的,例如css html xhtml js等一系类的
而Springmvc中的配置使用的是 / 意思就是过滤所有的东西 不能识别静态资源(携带了某种后缀)
因此便使用了:<mvc:default-servlet-handler/>
对应的处理的类:
org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler
在DispatcherServlet处理之前,首先查看是不是静态资源 如果是的话交由服务器的Servlet进行处理,如果不是的话交给DispatcherServlet继续进行处理
采用<mvc:resources />
<mvc:default-servlet-handler />将静态资源的处理经由Spring MVC框架交回Web应用服务器处理。而<mvc:resources />更进一步,由Spring MVC框架自己处理静态资源,并添加一些有用的附加值功能。
优点:灵活存放静态资源的位置,不受限制 位置可以由其中的location(属性是Resource类型的)决定 因此可以使用classpath:著名所在的位置等信息
/** * 删除部分的代码的实现 代码删除的操作是很简单的实现 * * 最难的是直接条转过来的是get请求 * 需要对跳转的方式进行处理 * * 既然处理 就是使用js代码进行跳转的方式的处理 * 紧接着就是springmvc对静态资源的特殊的处理 * 说明:SpringMVC对于静态资源的处理 在处理的时候不希望出现.html .do等一类的后置名 * DispatacherServlet的处理的配置是/ 过滤所有的 * * 因此需要配置另一个对于静态资源处理的配置代码<mvc:default-servlet/> * * 使得静态资源处理生效的代码会影响到的自定义的跳转 因此配置<mvc:annotation-driven></mvc:annotation-driven> * * @param id * @return */ @RequestMapping(value="/emp/{id}",method=RequestMethod.DELETE) public String delete(@PathVariable("id") Integer id){ employeeDao.delete(id); return "redirect:/emps"; } |
<!-- 配置静态资源的处理 --> <mvc:default-servlet-handler/>
<!-- 使用了处理静态资源的默认servlet跳转方式 正对自行使用的跳转的方式不冲突的解析的方式 使用下面的配置代码实现 --> <mvc:annotation-driven></mvc:annotation-driven> |
<script type="text/javascript"> $(function(){ $(".delete").click(function(){ alert("测试delete"); var href = $(this).attr("href"); $("#deleteform").attr("action",href).submit(); return false;/* 就是是链接本身的跳转失效 */ }); }); </script> |
<!-- 使用新建提交的表单 将普通的提交方式转换成delete --> <form action="" method="POST" id="deleteform"> <input type="hidden" name="_method" value="DELETE"> </form>
|
SpringMVC数据绑定
WebDataBinder->ConversionService->validator->convert() 举例说明 首先书写一个测试类:实现的目标是---将字符串employee指定格式的输入转换成employee对象 lastName-email-gender-department.id 测试前端界面 <!-- 实现目标: 字符串employee转换成对象employee lastname-email-gender-deapartment.id --> <form:form action="testEmployeeConversionService" method="POST"> <input type="text" name="employee"/> <input type="submit" value="提交"/> </form:form> 测试跳转的controller @Controller public class TestEmployeeConversionService { @Autowired private EmployeeDao employeeDao;
@RequestMapping(value="testEmployeeConversionService") public String testConversince(@RequestParam(value="employee") Employee employee){ System.out.println(employee); employeeDao.save(employee); return "redirect:/emps"; } } 测试自定义的Converter
@Component public class TestConversion implements Converter<String, Employee> {
/** * 重写Convert方法中的方法体 */ @Override public Employee convert(String source) { // TODO Auto-generated method stub String[] vals = source.split("-"); if(vals != null && vals.length == 4){ String lastName = vals[0]; String email = vals[1]; Integer gender = Integer.parseInt(vals[2]); Department department = new Department(); department.setId(Integer.parseInt(vals[3]));
Employee employee = new Employee(null, lastName, email, gender, department); System.out.println(source + "--convert--" + employee);
return employee; } return null; }
} 更改配置文件中的配置代码 <!-- 使用了处理静态资源的默认servlet跳转方式 正对自行使用的跳转的方式不冲突的解析的方式 使用下面的配置代码实现 --> <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置ConversionServiceFactoryBean --> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <ref bean="testConversion"/> </set> </property> </bean> 然后就是成功运行 |
MVC:annotation-driven
使用情况是在使用注解开发的时候:org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。(实现注解的原码类)
作用是:向工厂中注册一些实体类的bean,具体的参照下面的列举(也可以查看注解文档)
l RequestMappingHandlerMapping
@RequestMapping
l BeanNameUrlHandlerMapping
负责将Controller的实体类的名字映射成为URL
l RequestMappingHandlerAdapter
l HttpRequestHandlerAdapter
l SimpleControllerHandlerAdapter
上面的全部都是各种适配器 负责对应某个Controller或者是具体的方法
l ExceptionHandlerExceptionResolver
l ResponseStatusExceptionResolver
l DefaultHandlerExceptionResolver
各种异常处理
究竟有什么不同,那就是在自己定义的时候启用上面的bean 如果bean里面有优先于原生注解的@RequestMapping等注解的时候 首先用这些注册的bean中的方法进行优先的处理
@InitBinder
初始化参数的绑定
@InitBinder public void initBinder(WebDataBinder binder){ binder.setDisallowedFields("lastName"); } 举例说明应用 就是在执行赋值操作的时候 需要默认数据的处理 比如默认的权限 默认的参数转换集合之类的 需要提前使用这个方法处理一下 以方便后面的操作 |
Hibernate validator验证
数据验证完成之后跳转到正确的界面,如果输入的消息出现错误则跳转到错误的界面并且显示错误的信息问题 需要用到了hibernate的一个验证框架 hibernate validator-------讲解hibernate validator验证框架的以前的版本的下载的网站为:sourceForge: https://sourceforge.net/projects/hibernate/files/hibernate-validator/ 下载相关的源文件jar 导入相关的jar包文件
验证注解代码 需要在出入的方法的bean的参数之前加上需要验证的注解 @Valid Bean bean ,Error error 需要注意的是在bean和Error中间不能存在其他的参数的问题 |
国际化验证信息输出的配置
首先需要配置的是i18n格式的定制文件 文件的格式如下所示: 注解的名字.域对象的名字.定制报错的属性 NotEmpty.employee.laseName Springmvc.xml的具体配置的文件 <!-- 配置国际化的资源文件 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean> 备注说明: 每次校验一个属性的时候会生成有关该属性的四个消息代码 Pattern.user.password – required:必要的参数不存在。如 @RequiredParam(“param1”) |
Ajax AND Json
前端界面的显示问题
<br> <a href="testJson" id="testJson">Test Json</a> <script type="text/javascript"> $(function(){ $("#testJson").click(function(){ var href = this.href; var args = {}; $.post(href,args,function(data){ for(var i = 0;i < data.length;i++){ var id = data[i].id; var lastName = data[i].lastName;
alert( id + ": " + lastName); } }) return false; });
}); </script> Java实现代码
@RequestMapping(value="/testJson") @ResponseBody public Collection<Employee> testJson(){ return employeeDao.getAll(); } ResponseBody |
十九、 HttpMessageConvert
可以实现将传入的参数转换成为一个对象T 可以将一个对象T转换成为输出信息
@RequestBody / @ResponseBody实现文件的上传
/** * 实现一个文件上传的效果 * @param body * @return */ @ResponseBody @RequestMapping(value="/testHttpMessageConvert") public String testHttpMessageConvert(@RequestBody String body){ System.out.println(body); return "返回相应的方法体直接显示 : " + new Date(); } 并没有什么特殊的原理 只是在有ResponseBody的时候,返回的对象转换成为相应的小心显示 @requestBody修饰的时候 对于出入的对象会进行相关的格式换转 上面的用到了StringHttpMessageConverter |
HttpEntity<T> / ResponseEntity<T> 实现文件的下载
/** * 可以实现一个文件的下载的操作 * @return * @throws IOException */ @RequestMapping(value="/testResponseEntity") public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException{ ServletContext servletContext = session.getServletContext(); InputStream in = servletContext.getResourceAsStream("/files/index.txt"); byte[] body = new byte[in.available()]; in.read(body);
HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment;filename=licunzhi.txt");
HttpStatus statusCode = HttpStatus.OK;
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode);
return response; } |
二十、 国际化I18N
使用国际化的三个主要问题以及相应的解决办法
1使用国际化的显示问题: 可以使用JSTL的fmt标签辅助显示 2bean中读取locale中的信息的问题 可以使用ResourceBundleMessageSource 3通过网页端的超链接切换中英文的显示问题 可以使用LocaleChangeInterceptor和 localeResolver 界面显示问题
支持的配置文件
Bean中如何获取到locale中的值
|
二十一、 MultipartResolver文件长传
两个实现类可以使用 需要在Springmvc配置文件中配置一个,这里面选择的是CommonMultipartResolver
方法实现的代码
|
二十二、 自定义拦截器
拦截器的配置 多个拦截器执行的顺序
拦截器的实现类
public class FirstInterceptor implements HandlerInterceptor{
/** * 在调用目标方法之前使用 * return * 返回值是false的时候 后续的方法不再进行执行 * 返回值是true的时候 继续执行后面的方法 * * 作用:可以使用其设置权限 日志 事物 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("[FirstInterceptor] : preHandle"); return true; }
/** * 调用方法之后 渲染试图之前调用 * * 可以修改请求域中的属性 可以修改转向的视图 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("[FirstInterceptor] : postHandle"); }
/** * 渲染试图之后调用 * * 释放资源 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("[FirstInterceptor] : afterCompletion"); }
} |
单个拦截器的配置
<mvc:interceptors> <!-- 配置自定义的拦截器 --> <bean class="com.licunzhi.springmvc.interceptors.FirstInterceptor"></bean> |
多个拦截器的配置(指定方法不/调用)
<mvc:interceptors> <!-- 配置自定义的拦截器 --> <bean class="com.licunzhi.springmvc.interceptors.FirstInterceptor"></bean> <!-- 使用配置方法可以事项拦截器拦截指定的方法 --> <mvc:interceptor> <mvc:mapping path="/i18n"/><!-- 拦截指定的方法被调用的时候显示 --> <mvc:exclude-mapping path="/i18n2"/><!-- 排除指定的方法被调用的时候显示 --> <bean class="com.licunzhi.springmvc.interceptors.SecondInterceptor"></bean> </mvc:interceptor>
<!-- 配置拦截器 --> <!-- 配置localeChangeInterceptor --> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean> </mvc:interceptors>
|
二十三、 ExceptionHandlerExecptionResolver异常的捕捉和输出显示
类中的方法被ExceptionHandler修饰 /** * 有关异常的操作 @ExceptionHandlerExceptionResolver * * 1 @ExceptionHandlerExceptionresolver 在使用ModelAndView进行错误的信息封装之后显示到前端界面的时候 出现异常 * * 2 @ExceptionHandlerExceptionresolver 具有优先性的问题 * * 3 @ExceptionHandlerExceptionResolver 不能使用map进行修饰 * * 4 当handler找不到处理相关的方法的时候 查询@ControllerAdvice修饰类中的方法进行异常方法的处理 * */ @RequestMapping(value="/testExceptionHandlerExceptionResolver") public String testExceptionHandlerExceptionResolver(@RequestParam(value="i") int i){ int result = 10/i; System.out.println(result); return "success"; }
处理的方式 // @ExceptionHandler(value={RuntimeException.class}) // public ModelAndView testRuntimeException(Exception ex){ // System.out.println("[出现异常运行时异常]" + ex); // ModelAndView mv = new ModelAndView("error");//返回界面的名字信息 // mv.addObject("exception", ex); // return mv; // } // // @ExceptionHandler(value={ArithmeticException.class}) // public ModelAndView testArithmeticException(Exception ex){ // System.out.println("[出现异常数学运算]" + ex); // ModelAndView mv = new ModelAndView("error");//返回界面的名字信息 // mv.addObject("exception", ex); // return mv; // } @ControllerAdvice修饰的时候 @ControllerAdvice public class TestSpringMVCExceptionHandler { @ExceptionHandler({ArithmeticException.class}) public ModelAndView testException(Exception ex){ System.out.println("[被修饰的异常处理的类]: " + ex); ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", ex); return mv; }
} |
二十四、 @ResponseStatus
使用注解可以被其中的ResponseStatusExceptionResolver解析返回显示界面
可以使用在指定的方法上面 也可以修饰制定的类
/** * 状态消息显示的测试 * 定制错误信息显示的界面 ①可以注解在指定的方法上面 * ②可以注解在指定的类上面 * @return * @throws */ @RequestMapping(value="testResponseStatusExceptionResolver") @ResponseStatus(reason="状态错误自定义",value=HttpStatus.NOT_FOUND) public String testResponseStatusExceptionResolver(@RequestParam(value="i") int i ){
if(i == 12){ System.out.println("自定义显示异常界面调用"); throw new SelfDefineException(); }else{ return "success"; } } 自定义异常
@ResponseStatus(reason="自定义不让其正常",value=HttpStatus.FORBIDDEN) public class SelfDefineException extends RuntimeException{ private static final long serialVersionUID = 1L; public void testSelfDefineException(){ System.out.println("自定义显示异常问题"); }
} |
二十五、 DefaultHandlerExceptionResolver
某些特定的异常的处理
/** * 针对某些特殊异常的处理 * @return */ @RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST) public String testDefaultHandlerExceptionResolver(){ System.out.println("testDefaultHandlerExceptionResolver...."); return "success"; }
|
可以实现的异常处理的类可以查看源代码
二十六、 SimpleMappingExceptionResolver
其他异常的处理方法类 这里设置的是数组越界的异常显示 <!-- 配置一些其他的异常处理的bean SimpleMappingExceptionResolver --> <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!-- 类的处理实现将错误的消息信息存储 默认的名字是exception 这里的名字是可以自己定义配置的 --> <property name="exceptionAttribute"> <array> <value>exception</value> </array> </property> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean> |
二十七、 整合常见的问题
<!-- needed for ContextLoaderListener 项目启动的时候 启动spring IOC容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <!-- Bootstraps the root web application context before servlet initialization --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<servlet> <servlet-name>Springmvc03</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Springmvc03</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> |
Springmvc.xml
<!-- 配置自动扫描的包文件 --> <context:component-scan base-package="com.licunzhi.springmvc" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan> <!-- 配置视图解析器 --> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 配置静态资源的处理 --> <mvc:default-servlet-handler/> <!-- 注解扫描 --> <mvc:annotation-driven></mvc:annotation-driven>
<!-- Spring进行整合Springmvc的时候 Spring的容器相当于Springmvc来说是一个父容器 Spring可以调用SpringMVC容器中的bean 但是Springmvc不可以调用Spring中的bean
配置完成之后 由于配置文件扫面的注解的包的问题 会出现初始话两次bean 改变包的文件的名字结构是解决的办法之一 改变配合文件的内容是比较好的解决办法 --> |
Beans.xml
<context:component-scan base-package="com.licunzhi.springmvc"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>
<!-- 下面可以进行数据源 事物等一些列的配置。。。 --> |