JavaWeb三大组件和环境特点
SpringMVC简介(M:mode V:view C:controller)
SpringMVC是一个基于Spring开发的MVC轻量级框架,SpringMVC和Spring可以无缝整合,使用DispatcherServlet最为前端控制器,其内部提供了处理器映射器、处理器适配器、视图解析器等组件,可以简化JavaBean封装,Json转化、文件上传等操作
加载applicationConext
核心流程:ServletContextListener–>获取ServletContext初始化参数(配置文件路径)–>创建ApplicationContext
如下:
public class ApplicationListener implements ServletContextListener {
private final String CONTEXTCONFIGLOCATION="contextConfigLocation";
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContextListener");
final ServletContext servletContext = servletContextEvent.getServletContext();
final String contextLocation = servletContext.getInitParameter(CONTEXTCONFIGLOCATION);
// 初始化加载 applicationContext
final String substring = contextLocation.substring("classpath:".length());
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(substring);
servletContext.setAttribute("applicationContext", applicationContext);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
框架配置-初始化加载applicationContext
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
SpringMVC:框架设计思想和思路
SpringMVC:请求的处理流程
- 用户发送请求至前端DispatcherServlet(核心)
- DispatcherServlet收到请求调用HandlerMapping映射处理器
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如有有则生成)一并返回给DispatcherServlet
- DispatcherServlet调用HandlerAdapte适配处理器
- HandlerAdapter经过适配器调用具体的处理器(Controller,也叫后端控制器)
- Controller执行完成返回ModeAndView
- HandlerAdapter将controller执行结果ModeAndView返回给DispatcherServlet
- DispatcherServler将ModelAndView传给ViewReslover视图解析器
- ViewReslover解析后返回具体的View
- DispatcherServlet根据View进行渲染视图(即将模型填充至视图中),DispatcherServlet响应用户
框架配置-前端控制器DispatcherServlet
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
源码
默认配置
核心:加载流程, 先去IOC容器查找组件,如果找不到则执行配置文件所配置的
SpringMVC请求处理
请求映射的处理
配置映射路径,映射器处理器才能找到Controller的方法资源,目前主流的配置方式是@RequestMapping
@RequestMapping(value=“/test”,method=RequestMethod.POST,params={“userName”,“age!=10”},headers={}):
- value=url;
支持通配符
ant风格模糊路径
?:匹配任意一个字符
* : 匹配任意的字符,以及一层路径
**:代替多层路径 - method:请求方式
- params:请求参数控制
- 1、设置必传参数
- 2、设置参数校验
- headers:请求头信息
请求数据的接收
1. 请求参数为key=value,请求的参数和处理方法的参数名一致接收
// localhost/input?username=xusx&age=12
public String intputParam(String name,int age){
请求参数为key=value,请求的参数和处理方法的参数不一致
为解决参数名不一致异常:产生RequestParam来解决请求参数相关问题
@RequestParam(value=“name”,requird=false,defaultVlue=“a”) String username
- value:请求参数名
- requird: 是否必传
- defaultVlue: 默认值
// localhost/input?username=xusx&age=12
public String intputParam(@RequestParam(value = "username",required = false,defaultValue = "111") String name,int age){}
- 请求参数数组 key=value1&key=value2&key=value3 数组接收
// localhost/inputArr?hobby=a&hobby=b&hobby=c
- 方式1: public String inputArr(String[] hobby){}
- 方式2: public String inputArr(@RequestParam List<String> hobby){}
- 请求参数为key=value,Map接收
// localhost/inputMap?username=xusx&age=12
public String inputMap(@RequestParam Map<String,String> map){}
RequestParam则,指定无需封装对象直接放入即可
2. 请求参数与JavaBean属性一致,则经行自动封装为JavaBean
// http://localhost:8099/inputObj?username=xusx&age=12&address.city=xj
// http://localhost:8099/inputObj {"username":"xusx","age":"12"}
public String inputObj(User user){}
public class User {
private String username;
private String age;
private Address address;
}
public class Address {
private String city;
}
3. @请求参数为字符串Requestbody将请求体参数封装到指定的参数
get方式无请求体
@RequestMapping("/inpuBody")
public String inpuBody(@RequestBody String string){}
- 当请求体中的数据为json字符串
- 使用jackson可以经行Json字符换和JavaBean直接转换(单接口处理)
ObjectMapper mapper = new ObjectMapper();
final User user = mapper.readValue(string, User.class);
- 配置RequestMappingHandleAdapter指定消息转换器统一处理Json字符串和JavaBean转换(全接口处理)
<!--消息转换器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</list>
</property>
</bean>
/*
{"username":"xusx","age":"1","address":{ "city":"tj"}}
*/
@RequestMapping("/inpuJson")
public String inpuJson(@RequestBody User user) throws IOException {}
4. @请求参数对对象集合
/*
[ {"username":"xusx","age":"1","address":{ "city":"tj"}, {"username":"zj","age":"12","address":{ "city":"bj"}]
*/
@RequestMapping("/inputJsonArr")
public String inputJsonArr(@RequestBody List<User> userList) throws IOException {}
文件上传
- 表单提交方式为Post
- 表单的enctype必须为multipart/form-data
补充:multipart/form-data和x-www-form-urlencode区别
默认状况下是 application/x-www-urlencoded,当表单使用 POST 请求时,数据会被以 x-www-urlencoded 方式编码到 Body 中来传送
multipart/form-data 用以支持向服务器发送二进制数据
而若是 GET 请求,则是附在 url 连接后面来发送。
-
文件上传项必须有name属性
配置文件上传解析器
单文件:MultipartFile file或不同名称的多个参数
多文件:MultipartFile[] files 多个同名称参数
// id 必须屋为:multipartResolver,因为查找文件上传解析是根据id查找的
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property> -- 编号格式
<property name="maxInMemorySize" value="1048576"></property> --
<property name="maxUploadSizePerFile" value="1048576"></property>
<property name="maxUploadSize" value="3145728"></property> -- 最大上传大小
</bean>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
// MultipartFile 去指定接收类型
@RequestMapping("/inputFile")
public String inputFile(@RequestBody MultipartFile myFile) throws IOException {
System.out.println(myFile);
final InputStream inputStream = myFile.getInputStream();
OutputStream outputStream = new FileOutputStream("D:\\"+myFile.getOriginalFilename()+".txt");
IOUtils.copy(inputStream, outputStream);
inputStream.close();
outputStream.close();
return "index.jsp";
}
请求头@RequestHeader
@RequestMapping("/queryHead")
public String queryHead(@RequestHeader("Connection") String connection) {}
cook获取@CookieValue
@RequestMapping("/queryCook")
public String queryCook(@CookieValue("JSESSIONID") String sessionId){
原生API
String getAPI(HttpServletRequest request)
httpservletrequest,
httpservletresponse,
httpsession,
java.security.princioal,
loacl,
inputstream,
outputstream,
reader,
writer.
获取Request域中属性@RequestAttribute
@RequestMapping(“/setResAttr”)
public String setResAttr(HttpServletRequest request){
request.setAttribute(“attr”,“撒哇哇阿斯顿”);
return “/getRstAttr”;
}
@RequestMapping("/getRstAttr")
public String getRstAttr(@RequestAttribute("attr") String attr){
System.out.println(attr);
return "index.jsp";
}
静态资源访问
JavaWeb原始开发时静态资源文件时可以直接被访问当
原因为: tomcat-config-web.xm提供了默认的servlet处理静态资源的访问
处理方式:
- 再次激活Tomcat下的defaultServlet去经行url-pattern匹配
- Springmvc配置静态资源的映射
<!--配置静态资源访问映射-->
<mvc:resources mapping="/img/*" location="/img/"></mvc:resources>
- Springmvc配置注册DefaultServletHttpRequestHandle出处理(用的最多)
<mvc:default-servlet-handler/>
2.3同理源码:根据命名空间去寻找
查找
注册SimpleUrlHandlerMapping
[SimpleUrlHandlerMapping优先加载注册在IOC容器中的则会造成]re(#centre)
annotation-driven注解
此注解会帮我们在内部注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter并注入Json消息转换器
还提供以下支持:
1、支持使用ConversionService实例对表单参数进行类型转换
2、支持使用@NumberFomat annotion、@DataTimeFormat注解完成数据类型的格式化
3、支持使用 @Valid 注解对JavaBean实例进行JSR303验证
4、支持使用 @RequestBody 和@ResoponseBody注解
<mvc:annotation-driven/>
替换
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!--Json消息转换器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</list>
</property>
</bean>
SpringMVC响应处理
传统同步业务数据响应
- 请求资源转发
@RequestMapping("/forwardJsp")
public String forwardJsp(){
return "forward:index.jsp";
}
- 请求资源重定向
@RequestMapping("/redirectJsp")
public String redirectJsp(){
return "redirect:index.jsp";
}
- 响应数据模型 ModelAndView
将ModelAndView中添加的数据放入 request域中,path路径为视图解析器的路径。
@RequestMapping("/modelandview")
public ModelAndView modelandview(ModelAndView modelAndView){
User user = new User();
user.setUsername("xusx");
modelAndView.addObject("user", user);
modelAndView.setViewName("index.jsp");
return modelAndView;
}
- 直接回写客户端 @ResponseBody注解
告知SpringMVC框架,以响应体返回数据并非视图名
前后端分离异步数据响应
注:同步与异步数据响应的区别
- 同步方式回写数据,时将数据响应给浏览器经行页面展示的,而异步方式回写数据一般是回写给Ajax引擎的,即谁访问服务器端,服务器端就将数据响应给谁
- 同步方式回写的数据,一般就是一些无特定格式的字符串,而异步方式回写的数据大多都是JSON格式字符串
- 直接回写客户端 @ResponseBody注解
ResponseBody会调用配置的消息转换器,将对象转换为JSON字符串输出
RestController=@Controller+@ResponseBody
@RequestMapping("/jsonStr")
@ResponseBody
public User jsonStr() throws JsonProcessingException {
User user=new User();
user.setUsername("dasd");
user.setAge("11");
return user;
}
SpringMVC的拦截器
拦截器Interceptor简介
SpringMVC的拦截器Interceptor规范,主要是对Controller资源访问时经行拦截操作的技术,当然拦截后可以经行授权控制,功能增强等;
Filter和Interceptor区别
HandlerInterceptor接口方法的作用及其参数、返回值详解如下:
拦截器Interceptor配置
自定义类实现HandlerInterceptor接口,实现:preHandle、postHandle、afterCompletion
afterCompletion是否执行取决与preHandle返回true|false
<!--拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/> <!-- 拦截路径 -->
<bean class="com.yinhai.xusx.inteceptor.Myinteceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截器执行顺序
其顺序是按照配置时的顺序执行的
当Interceptor1和Interceptor2处于放行,Inteceptore处于不放行时,执行如下
afterCompletion是否执行取决与preHandle返回true|false
全注解开发
spring-mvc.xml转化为注解
- <mvc:annotation-driven/> <mvc:default-servlet-handler/> <mvc:interceptor>替换
@EnableWebMvc
源码
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();// 开始默认DefaultServlet
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new Myinteceptor()).addPathPatterns("/*");
}
}
web.xml 转发为注解
待定吧
前端控制器DispatcherServlet
前端控制器初始化
主要两作用
- 初始化Spring和Springmvc容器
Spring是Springmvc的父容器。获取Bean时,子可以查父(getParent),父无法查子
- 初始化九大组件
前端控制器主流程
SpringMVC异常处理机制
SpringMVC异常处理流程
一直往上抛,都抛给前端控制器DispatcherServlet,后由其调用异常处理器去处理
SpringMVC异常处理的方式
- 简单的异常处理器:使用SpringMVC内置的异常处理器处理SimpleMappingExceptionResolver
主要作用:异常控制视图跳转
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 默认异常跳转-->
<property name="defaultErrorView" value="error.jsp"></property>
<!--具体异常的处理-->
<property name="exceptionMappings">
<props>
<prop key="java.lang.NullPointerException">null.jsp</prop>
<prop key="java.io.FileNotFoundException">fileNot.jsp</prop>
</props>
</property>
</bean>
- 自定义异常处理器:实现HandlerExceptionRexolver接口,自定义异常处理
主要作用:ModelAndView为返回值视图控制
@Component
public class MyExceptionHandle implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();
// 默认
System.out.println(e.getCause());
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
modelAndView.setViewName("error.jsp");
return modelAndView;
}
}
- 注解方式:使用@ControllerAdvice+@ExceptionHandler来处理,异常处理器:异常处理器指定要处理的异常类型包括自定义异常,最后控制视图或响应体(常用)
主要作用:既可以控制视图,也可以响应体方式返回异常
@ControllerAdvice
public class ExceptionHandle {
// 视图
@ExceptionHandler(Exception.class)
@ResponseBody
public ModelAndView exceptionHandle(Exception ex){
ModelAndView mv = new ModelAndView();
mv.setViewName("error.jsp");
return mv ;
}
// 自定义异常
@ExceptionHandler(MyException.class)
@ResponseBody
public Result returnErrStr(MyException ex) throws JsonProcessingException {
Result result=new Result();
result.setCode(ex.getCode());
result.setMsg(ex.getMsg());
return result ;
}
// 异常类型
@ExceptionHandler(IOException.class)
@ResponseBody
public String returnErr(Exception ex){
String str="{\"code\":\"1\",\"msg\":\""+ex.getMessage()+"\"}";
return str ;
}
}
@ControllerAdvice
public class ExceptionHandle {
@ExceptionHandler(Exception.class)
@ResponseBody
public ModelAndView exceptionHandle(Exception ex){
ModelAndView mv = new ModelAndView();
mv.setViewName("error.jsp");
return mv ;
}
@ExceptionHandler(IOException.class)
@ResponseBody
public String returnErr(Exception ex){
String str="{\"code\":\"1\",\"msg\":\""+ex.getMessage()+"\"}";
return str ;
}
}
补充
设置字符编码:
<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>
<!--响应编码与请求编码同步-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
其他+视图解析器
配置自定掃描包:
<context:component-scan base-package="com.xusx"></context:component-scan>.
配置Spring注解:
<context:annotation-config></context:annotation-config>
配置切面注解:
<aop:aspectj-autoproxy expose-proxy="false"></aop:aspectj-autoproxy>
配置静态资源访问注解:
<mvc:default-servlet-handler></mvc:default-servlet-handler>
配置springmvc注解:
<mvc:annotation-driven></mvc:annotation-driven>
配置spring視圖解析器:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property> 前缀
<property name="suffix" value=".jsp"></property> 后缀
</bean>