赞
踩
什么是MVC
最典型的MVC就是JSP+servlet+JavaBean的模式
Spring-web
public class MyServlet extendsHttpServlet{
@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException{
String username= req.getParameter("username");
req.getSession().setAttribute("username", username);
req.getRequestDispatcher("index.jsp").forward(req, resp);
}
@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException{this.doPost(req. resp);
}
}
web.xml配置servlet
springmvc.xml
idea,添加lib文件夹
public classHelloController{public voidhello(){
System.out.println(this.getClass().getName());
}public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throwsException{//创建对象
ModelAndView mv = newModelAndView();//添加视图名称, 要跳转的页面名称
mv.setViewName("hello");//向前端页面添加属性值
mv.addObject("hello", "hello, springmvc");return null;
}
}
Spring的处理过程
@Controllerpublic classHelloController{
@RequestMapping("/hello")publicString hello(){
map.put("hello", "hello,SpringMVC");return "hello";
}
@RequestMapping("/hello")public String hello2(Mapmap){
map.put("hello", "hello, SpringMVC");return "hello";
}
@RequestMapping(value= "/hello", method =RequestMethod.POST)public String hello2(Mapmap){
map.put("hello", "hello, SpringMVC");return "hello";
}
@RequestMapping(value= "/hello", param = {"username"})public String hello2(Mapmap){
map.put("hello", "hello, SpringMVC");return "hello";
}
@RequestMapping(value= "/hello", param = {"username=zs", "age"})public String hello2(Mapmap){
map.put("hello", "hello, SpringMVC");return "hello";
}//headers 表示限制请求头中的相关属性值, 用来做请求的限制
@RequestMapping(value = "/hello", headers = {"User-Agent=..."})public String hello2(Mapmap){
map.put("hello", "hello, SpringMVC");return "hello";
}//produces: 限制请求中的Content-Type//consumers: 限制响应中的Content-Type//@RequestMapping可以进行模糊匹配//?: 替代任意一个人字符//*: 提供多个字符//**: 替代多层路径
}
常用的注解
参数列表
@Controllerpublic classPathVariableController{
@RequestMapping("/testPathVariable/{name}")public String testPathVariable(@PathVariable String name){//rest方式用的比较多
request.getParameter("name");
System.out.println(name);return "hello";
}
}
@Controllerpublic classPathVariableController{
@RequestMapping("/testPathVariable/{id}")public String testPathVariable(@PathVariable("id") String name){//rest方式用的比较多
request.getParameter("name");
System.out.println(name);return "hello";
}
}
@Controllerpublic classPathVariableController{
@RequestMapping("/testPathVariable/{id}")public String testPathVariable(@PathVariable("id") Integer id, @PathVariable("name") String name){//rest方式用的比较多
request.getParameter("name");
System.out.println(name);return "hello";
}
}
web.xml
springmvc.xml
如果不使用rest,那么增删改查就需要建立四个接口,如果用rest那么用GET,POST,PUT,DELETE四个提交方式对应增删改查
public classUserDao{public voidsave(User user){
System.out.println("save");
}public voidupdate(Integer id){
System.out.println("update");
}public voiddelete(Integer id){
System.out.println("delete");
}public voidquery(){
System.out.println("query");
}
}public classUser{
}
@Controllerpublic classUserController{
@AutowiredprivateUser userDao;
@RequestMapping("/save")publicString save(){
userDao.save(newUser());return "success";
}
@RequestMapping("/update")publicString update(Integer id){
userDao.update(id);return "success";
}
@RequestMapping("/delete")publicString delete(Integer id){
userDao.delete(id);return "success";
}
@RequestMapping("/query")publicString query(){
userDao.query();return "success";
}
}
REST
POST:创建 /user/1
GET:获取 /user
PUT:更新资源 /user/1
DELETE:删除资源 /user/1
导包
web.xml
public classUserDao{public voidsave(User user){
System.out.println("save");
}public voidupdate(Integer id){
System.out.println("update");
}public voiddelete(Integer id){
System.out.println("delete");
}public voidquery(){
System.out.println("query");
}
}public classUser{
}
@Controllerpublic classUserController{
@AutowiredprivateUser userDao;
@RequestMapping(value= "/user", method =RequestMethod.POST)publicString save(){
userDao.save(newUser());return "success";
}
@RequestMapping(value= "/user", method =RequestMethod.PUT)publicString update(Integer id){
userDao.update(id);return "success";
}
@RequestMapping(value= "/user", method =RequestMethod.DELETE)publicString delete(Integer id){
userDao.delete(id);return "success";
}
@RequestMapping(value= "/user", method =RequestMethod.GET)publicString query(){
userDao.query();return "success";
}
}public class MyFilter implementsFilter{public voiddoFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){
filterChain.doFilter(servletRequest, servletResponse);
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
}
}
SpringMVC的使用
RequestParam和PathVariable不要混淆
RequestParam获取的是问号后面的键值对
PathVariable获取的是路径后面的值
RequestParam的参数
value:获取的参数值
required:表示当前属性值是否存在,默认值是true,如果没有,400,bad request
defaultValue:如果有传递参数就是用传递进来的参数,如果没有就是用默认值
乱码问题解决
需要设置过滤request和response的编码方式,可以自己手动编写过滤器,也可以由现成的框架实现
post:分别设置request和response编码格式
get:在tomcat的server.xml文件中,添加URIEncoding=utf-8
调整顺序可以解决乱码问题
在一个应用程序中,可能包含n多个过滤器,一般没有顺序要求,如果设置了编码过滤器,必须要将编码过滤器设置到最上面,保证编码过滤器,优先执行
编码过滤器,要放在最上面的位置
@Controllerpublic classRequestController{
@RequestMapping("/testRequest")public String testRequest(@RequestParam(value = "username", required = false) String name){
System.out.println(name);return "success";
}
}//获取请求头信息
@Controllerpublic classRequestController{
@RequestMapping("/testRequest")publicString testRequestHeader(@testRequestHeader String userAgent){
System.out.println(userAgent);return "success";
}//request.getCookie()
@RequestMapping("/testCookie")public String testCookie(@CookieValue("JSESSIONID"), String jsid){
System.out.println(jsid);return "success";
}
}
@Controllerpublic classUserController22{
@RequestMapping("/testUser")publicString testUser(User user){
System.out.println(user);return "success";
}
}
每次tomcat可以启动,可以自己启动
SessionAttribute
@Controller
@SessionAttributes(value= {"username", "msg"}, types = Integer.class) //每次向request设置作品用于的时候, 顺带向session中保存一份
public classOutputController{
@RequestMapping("/output")public String output(Mapmap){
map.put("msg", "hello,output");
System.out.println(model.getClass());return "success";
}
@RequestMapping("/output1")public String output(Mapmap){
map.put("msg", "hello,output1");return "success";
}
@RequestMapping("/output2")public String output(Mapmap){
model.addAttribute("msg", "hello, output2");return "success";
}
@RequestMapping("/output3")public String output(Mapmap){
map.put("msg", "hello,output3");return "success";
}
@RequestMapping("/output4")public ModelAndView output(Mapmap){
ModelAndView mv= newModelAndView();
mv.setViewName("success");
mv.addObject("msg", "output4");returnmv;
}
@RequestMapping("/testSession")publicString testSession(Model model){
model.addAtttibute("username", "zs");return "success";
}
}
被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用
@Controllerpublic classUserController{
Object o1= null;
Object o2= null;
Model m1= null;
@RequestMapping("update")public String update(@ModelAttribute("user2") User user, Model model){
o2=user;
System.out.prinltn(user);
System.out.println(o1 == o2);//true 指向同一个对象
System.out.println(m1 == model);//false
return "success";
}
@ModelAttributepublic voidtestModelAttribute(Model model){
User user= newUser();
user.setId(1);
user.setName("name");
user.setPassword("1234");
model.addAttribute("user2", user);
o1=user;
m1=model1;
}
}
SessionAttributes要注意,在使用的时候如果没有对应的值
@Controllerpublic classUserController{
Object o1= null;
Object o2= null;
Model m1= null;
@RequestMapping("update")public String update(@ModelAttribute("user2") User user, Model model){
o2=user;
System.out.prinltn(user);
System.out.println(o1== o2);//true 指向同一个对象
System.out.println(m1 == model);//false
return "success";
}//加一个user2标识, 可以匹配到user2
@ModelAttribute("user2")public voidtestModelAttribute(Model model){
User user= newUser();
user.setId(1);
user.setName("name");
user.setPassword("1234");
model.addAttribute("user2", user);
o1=user;
m1=model1;
}
}
forward转发
在使用转发的时候,要添加forward: 前缀
可以实现多次转发请求,可以回到页面,也可以转发到其他页面请求中
@Controllerpublic classForWardController{
@RequestMapping("/forward")publicString forward(){
System.out.printfln("forward");return "forward:/index.jsp";
}
@RequestMapping("/forward2")publicString forward2(){
System.out.printfln("forward2");return "forward:/forward";
}
}
redirct重定向
重定向操作也不会经过视图处理器
@Controllerpublic classRedirctontroller{
@RequestMapping("/redirect")publicString forward(){
System.out.printfln("forward");return "redirect:/index.jsp";
}
@RequestMapping("/redirect2")publicString forward2(){
System.out.printfln("redirect2");return "redirect:/redirect";
}
}
转发与重定向的区别
转发是服务端
重定向是客户端
springmvc.xml
默认的servlet处理类
保证动态请求和静态资源能够访问
自定义视图解析器
InternalResourceViewResolver
public class MyViewResolver implementsViewResolver, Ordered{private int order = 0;
@Overridepublic View resolveViewName(String viewName, Locale locale) throwsException{if(viewName.startsWith("test")){
System.out.println(viewName);returnMyView();
}else{return null;
}
}
}public void setOrder(intorder){this.order =order;
}
@Overridepublic intgetOrder(){return 0;
}public class MyView implementsView{
@OverridepublicString getContentType(){return null;
}
@Overridepublic void render(Map model, HttpServletRequest request, HttpServletResponse response) throwsException{
System.out.println("model:" +model);
PrintWriter writer=response.getWriter();
writer.write("test");
writer.write("gogogo");
}
}
@Controllerpublic classViewResolverController{
@RequestMapping("/test")publicString testView1(){
System.out.println("testView");return "test:/index";
}
@RequestMapping("/test2")publicString testView2(){
System.out.println("testView");return "test2:/index";
}
}
springmvc.xml
value的值越大,优先级越小
添加自定义的类型转换器到ConversionServiceFactoryBean中
@Componentpublic class MyConverter implements Converter{
@OverridepublicObject convert(Object source){
User user= null;if(source != null && "".equals(source) && (source.split("-").length == 4)){
user= newUser();
user.setId(Integer.parseInt(source.split("-")[0]));
user.setName(source.split("-")[1]);
user.setAge(Integer.parseInt(source.split("-")[2]));
user.setPassword(source.split("-")[3]);
}return null;
}
}//自定义类型转换器的时候, 注意对应的属性值跟方法中参数值对应起来
@Controllerpublic classMyConverterController{
@RequestMapping("/converter")publicString testConverter(User user, Model model){
System.out.println(user);
model.addAttribute("user", user);return "success";
}
}
自定义日期转换器
springmvc.xml
如果需要添加日期格式化器,只需要在实体类上添加@DataTimeFormat("格式")即可
如果配置日期格式化器的时候,同时配置了类型转换器,那么就会失效
需要使用 FormattingConversionServiceFactoryBean 对象
//如果使用默认的类型转换器, 那么在输入日期的时候使用/作为分隔
@Controllerpublic classDateConverterController{
@RequestMapping("/testDateConverter")publicString testDateConverter(User user){
System.out.println(user);return "success";
}
}public classUser{
@DateTimeFormat(pattern= "yyyy-MM-dd")privateDate birth;
}
数据校验
JSR303提供的标准校验
Hibernate Validator 扩展注解
JSR校验框架
导包
日期格式化器
public classPerson{
@NouNullprivateInteger id;
@Length(min= 3, max = 10)privateString name;privateInteger age;privateString gender;
@Past//设置的日期只能是之前的日期
privateDate birth;
@EmailprivateString gmail;
}
@Controllerpublic classValidationController{
@RequestMapping("/validation")publicString validate(@Valid Person person, BindingResult){if(BindingResult.hasErrors()){
System.out.println("验证失败");//获取到当前所有的错误
List fieldErrors =bindingResult.getFieldErrors();for(FieldError fieldError : fieldErrors){
System.out.println(fieldError.getField());
System.out.println(fieldError.getDefaultMessage());
map.put(fieldError.getField(), fieldError.getDefaultMessage());
}
model.addAttribute("errors", map);return "forward:/login.jsp";
}else{
System.out.println("登陆成功");return "success";
}
}
}
springmvc_json
@RequestBody 表示把当前请求的内容
@ResponseBody 解析字符串为标签
@Controllerpublic classJsonController{
@ResponseBody
@RequestMapping("/json")publicString json(){
List list = new ArrayList();
list.add(new User("test1", 12, "man"));
list.add(new User("test2", 13, "woman"));
list.add(new User("test3", 14, "man"));returnlist;
}
@ResponseBody//该注解会解析字符串为标签
@RequestMapping("/json2")publicString json2(){return "
}
@RequestMapping("/testRequestBody")publicString testRequestBody(@RequestBody String body){
System.out.println(body);return "success";
}
@RequestMapping("/testRequestJson")publicString testRequestJson(@RequestBody User user){
System.out.println(user);return "success";
}
}public classUser{privateInteger id;privateString name;privateInteger age;privateString gender;publicUser(){
}publicUser(String name, Integer age, String gender){
}
}
自定义响应ResponseEntity
@Controllerpublic classEntity{
@RequestMapping("test")public String test(HttpEntityhttpEntity){
System.out.println(httpEntity);
String body=httpEntity.getBody();return "success";
}//自定义响应相关的信息, 包含body和header
@RequestMapping("testResponseEntity")publicString teestResponseEntity(){
String body= "
MultiValueMap header = newHttpHeaders();
header.add("set-cookie", "name=zs");return new ResponseEntity(body, header, HttpStatus.OK);
}
}
servlet下载文件
@Controllerpublic classDownController{
@RequestMapping("/download")publicString download(HttpServletRequest request){//获取下载路径
ServletContext servletContext =request.getServletContext();
servletContext.getRealPath("/scripts/...");//通过io流对文件读写
FileInputStream FileInputStream = newFileInputStream(realPath);byte[] bytes = new byte[FileInputStream.available()];
FileInputStream.read(bytes);
FileInputStream.close();
HttpHeaders httpHeaders= newHttpHeaders();
httpHeaders.set("Content-Disposition", "attachment:filename=...");return new ResponseEntity(bytes, httpHeaders, HttpStatus.OK);
}
}
servlet上传文件
springmvc.xml
添加jar包
多文件上传
@Controllerpublic classUploadController{
@RequestMappin("upload")public String upload(@RequestParam("file") MultipartFile multipartFile, @RequestParam(value = "desc", required = false) String desc){
System.out.println(desc);for(MultipartFile file: multipartFile){if(!file.isEmpty()){
System.out.println(file.getOriginalFilename());
multipartFile.transferTo(new File("d:\\file\\" +multipartFile.getOriginalFilename()));
}
}return "success";
}
}
拦截器和过滤器的区别
springmvc.xml
执行顺序,preHandler->目标方法->postHandler->页面跳转->afterCompletion
如果执行过程中抛出异常,那么afterCompletion依然会继续执行
执行顺序
public class MyInterceptor implementsHandlerInterceptor{public booleanpreHandle(HttpServletRequest request, HttpServletResponse response){
System.out.println(this.getClass().getName());return true;//返回指控制流程是否停止
}public booleanpostHandle(HttpServletRequest request, HttpServletResponse response){
System.out.println(this.getClass().getName());return true;
}public booleanafterCompletion(HttpServletRequest request, HttpServletResponse response){
System.out.println(this.getClass().getName());return true;
}
}
@Controllerpublic classInterceptorController{
@RequestMapping("/testInterceptor")publicString testInterceptor(){//如果此处抛出异常, after依然会执行
System.out.println(this.getClass().getName());return "success";
}
}
国际化
login_en_US.properties
login_zh_CN.properties
jsp文件body内容
springmvc.xml
jsp文件的body标签前不要漏下以下配置
@Controllerpublic classI18nController{
@AutowiredprivateMessageSource messageSource
@RequestMapping("/i18n")publicString i18n(Locale locale){
System.out.println(locale);
String username= MessageSource.getMesssage("username", null, locale);
System.out.println(username);return "login";
}
@RequestMapping("/i18n")public String i18n(@RequestParam("locale") String localStr, Locale locale, HttpSession session){
Locale locale1= null;
System.out.println(locale);if(localStr != null && !"".equals(localStr)){
locale1= new Locale(localStr.split("_")[0], localStr.split("_")[1]);
}else{
locale1=locale;
}
session.setAttribute(SessionLocaleResolver.class.getName() + ".LOCALE", locale1);return "login";
}
}public class MyLocaleResolver implementsLocaleResolver{publicLocale resolveLocale(HttpServletRequest request){
Locale locale= null;
String localeStr= request.getParameter("locale");if(localeStr != null && !"".equals(localStr)){
locale= new Locale(localeStr.split("_")[0].localeStr.split("_"))
}else{
locale=request.getLocale();
}returnlocale;
}
}
mvc异常处理机制
容器启动好后,进入DispatcherServlet之后,会对HandlerExceptionResolver进行初始化操作
可以通过@ControllerAdvice注解进行标注,表示为全局异常处理类
如果有了全局异常,若当前类抛出了异常会现在本类查找,然后再查找全局异常
@Controllerpublic classExceptionController{
@RequestMapping("/exception1")publicString exception(){
System.out.println(this.getClass().getName());int i = 10/0;return "success";
}
@ExceptionHandler(value= ({ArithmeticExcepton.class, NullPointerException.class}))publicString handlerException(Exception exception){
ModelAndView mv= newModelAndView();
mv.setViewName("error");
mv.addObject("exce", exception);returnmv;
}
@ExceptionHandler(value= (Exception.class))publicString handlerException2(Exception exception){
ModelAndView mv= newModelAndView();
mv.setViewName("error");
mv.addObject("exce", exception);returnmv;
}
}
@ControllerAdvicepublic classMyGlobalExceptionHandler{
@ExceptionHandler(value= ({ArithmeticExcepton.class, NullPointerException.class}))publicString handlerException(Exception exception){
ModelAndView mv= newModelAndView();
mv.setViewName("error");
mv.addObject("exce", exception);returnmv;
}
@ExceptionHandler(value= (Exception.class))publicString handlerException2(Exception exception){
ModelAndView mv= newModelAndView();
mv.setViewName("error");
mv.addObject("exce", exception);returnmv;
}
}
ResponseStatus
@Controllerpublic classExceptionController{
@ResponseStatus(reason= "", value =HttpStatus.NOT_ACCEPTABLE)
@RequestMapping("/exception")publicString handlerException(Exception exception){
System.out.println("exception")return "success";
}
}
@ResponseStatus,可以标注在方法中,但是不推荐使用
@Controllerpublic classExceptionController{
@RequestMapping("/exception")publicString handlerException(String username){
System.out.println("exception")if("admin".equals(username)){return "success";
}else{throw newUsernameException();
}return "success";
}
}
Springmvc流程图
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。