博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ssm(3-2)Springmvc拓展
阅读量:7235 次
发布时间:2019-06-29

本文共 16978 字,大约阅读时间需要 56 分钟。

1.rest风格增删改查及druid数据源的配置及mybatis的配置

@AllArgsConstructor@NoArgsConstructor@Data@Accessors(chain = true)//lombokpublic class Book implements Serializable {    private   Integer  id;    private    String   name;    private    Integer  price;}
public interface BookMapper {    @Select("select isbn id,book_name name,price from books where  isbn=#{id}")    public Book  getBookById(Integer id);    @Update("")    public void updateBook(Book book);    @Delete("delete from books where  isbn=#{id}")    public void deleteBookById(Integer id);    @Insert("insert into  books(isbn,book_name,price)  values(trim(#{id}),trim(#{name}),trim(#{price}))")    @Options(useGeneratedKeys = true)    public void insertBook(Book book);}
@org.springframework.web.bind.annotation.RestControllerpublic class RestController {      @Autowired      private BookMapper  bookMapper;      @GetMapping("/book/{id:\\d+}")      public Book get(@PathVariable Integer id){            return  bookMapper.getBookById(id);      }      @PutMapping("/book")      public Book  put(Book  book){            bookMapper.updateBook(book);            Book bookNew = bookMapper.getBookById(book.getId());            return  bookNew;      }      @DeleteMapping("/book/{id:\\d+}")      public String   post(@PathVariable Integer id){            bookMapper.deleteBookById(id);            return   id+"删除成功";      }      @PostMapping("/book")      public Book  post(Book  book){            bookMapper.insertBook(book);          Book bookNew = bookMapper.getBookById(book.getId());          return  bookNew;      }}
@Configuration@ComponentScan(value = "springmvc.demo")@MapperScan("springmvc.demo.dao")public class MVCConfig  {}
@Configurationpublic class MVCConfigBean {    @ConfigurationProperties(prefix ="spring.datasource")    @Bean    public DataSource  getDataSource(){        return new DruidDataSource();    }    //配置druid监控页面    @Bean    //添加servlet    public ServletRegistrationBean   statViewServlet(){        ServletRegistrationBean
servlet = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); HashMap
map = new HashMap<>(); map.put("loginUsername", "admin");//账户 map.put("loginPassword", "123456");//密码 map.put("allow", "");//允许所以用户登录,默认允许所有用户登录 map.put("deny", "");//拒绝用户登录,可以是ip地址等 servlet.setInitParameters(map); return servlet; } @Bean //添加过滤器 public FilterRegistrationBean webStatFilter(){//假如拦截所有那么与标注@component注解作用一样,其他的也是 FilterRegistrationBean
filter = new FilterRegistrationBean<>(); filter.setFilter(new WebStatFilter()); HashMap
map = new HashMap<>(); map.put("exclusions", "*.js,*.css,*/druid/*,*.gif,*.jpg,*.png,*.ico"); filter.setInitParameters(map); filter.setUrlPatterns(Arrays.asList("/*")); return filter; } //添加配置mybatis的配置 @Bean public ConfigurationCustomizer configurationCustomizer(){ ConfigurationCustomizer configurationCustomizer = x->{ //设置驼峰命名法 x.setMapUnderscoreToCamelCase(true); }; return configurationCustomizer; }}
#编码处理spring.http.encoding.charset=UTF-8spring.http.encoding.force=truespring.http.encoding.enabled=trueserver.tomcat.uri-encoding=UTF-8#日志logging.level.springmvc.demo.mvcdemo=debug#与mysql数据库连接spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/book?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false&verifyServerCertificate=falsespring.datasource.username=rootspring.datasource.password=cgz12345678#使用druid连接池spring.datasource.type=com.alibaba.druid.pool.DruidDataSource#druid连接池连接池参数配置#初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时spring.datasource.initialSize=5#最大连接池数量spring.datasource.maxActive=10#获取连接时最大等待时间spring.datasource.maxWait=3000#最小连接池数量spring.datasource.minIdle=3# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒spring.datasource.timeBetweenEvictionRunsMillis=60000# 配置一个连接在池中最小生存的时间,单位是毫秒spring.datasource.minEvictableIdleTimeMillis=300000#验证数据库连接的有效性spring.datasource.validationQuery=SELECT 1 FROM DUALspring.datasource.testWhileIdle=truespring.datasource.testOnBorrow=falsespring.datasource.testOnReturn=falsespring.datasource.poolPreparedStatements=truespring.datasource.maxPoolPreparedStatementPerConnectionSize=20#stat功能(监控)、wall功能(sql防火墙)、logback功能(监控日志输出),需要配置添加相应的配置文件否则会报错spring.datasource.filters=stat,wall,logback# 通过connectProperties属性来打开mergeSql功能;慢SQL记录spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
@RunWith(SpringRunner.class)@SpringBootTestpublic class MvcDemoApplicationTests {    @Autowired    WebApplicationContext context;    MockMvc mockMvc;    Logger  logger;    @Before    public void init() {        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();        logger=LoggerFactory.getLogger(MvcDemoApplicationTests.class);    }    @Test    public void testGet() throws Exception {        String contentAsString = mockMvc.perform(MockMvcRequestBuilders.get("/book/1001")                .contentType(MediaType.APPLICATION_JSON_UTF8)).andReturn()                .getResponse().getContentAsString();        logger.debug(contentAsString);        System.out.println(contentAsString);    }    @Test    public void testInsert() throws Exception {        String contentAsString = mockMvc.perform(MockMvcRequestBuilders.post("/book")                .param("name", "     dokcer  ")                .param("price", "150")                .contentType(MediaType.APPLICATION_JSON_UTF8))                .andReturn().getResponse().getContentAsString();        System.out.println(contentAsString);    }    @Test    public  void   testDelete() throws Exception {        String contentAsString = mockMvc.perform(MockMvcRequestBuilders.delete("/book/1003")                .contentType(MediaType.APPLICATION_JSON_UTF8)).andReturn()                .getResponse().getContentAsString();        System.out.println(contentAsString);    }    @Test    public  void  testUpdate() throws Exception {        String contentAsString = mockMvc.perform(MockMvcRequestBuilders.put("/book")                .param("id","1009")                .param("price", "1500")                .contentType(MediaType.APPLICATION_JSON_UTF8))                .andReturn().getResponse().getContentAsString();        System.out.println(contentAsString);    }}

 检查数据源是否配置成功

 

 druid监控页面

2.@Pathvariable注解

2.1配置正则实例

@AllArgsConstructor@NoArgsConstructor@Data@Accessors(chain = true)  //lombokpublic class User implements Serializable {    private  String  name;}
@RestController   //responsebody +controllerpublic class UserController {    @GetMapping("/user/{name:.*}")       public User  testUser(@PathVariable(required = false,value = "name") User user){        System.out.println(user.getClass());        return  user;    }}
@SpringBootApplicationpublic class MvcDemoApplication  {    public static void main(String[] args) {        SpringApplication.run(MvcDemoApplication.class, args);    }}
@Configuration@ComponentScan(value = "springmvc.demo")//扫描包public class MVCConfig  {}
spring.http.encoding.charset=UTF-8 spring.http.encoding.force=truespring.http.encoding.enabled=trueserver.tomcat.uri-encoding=UTF-8

 

3.@valid与@Validated

@valid与@Validated的区别,@Validated是spring中的,是在@valid基础上而来的,在@valid的基础上增加分组功能,这里就直接说@Validated,没有加分组都需要认证,加了分组只有符合分组的才需要认证,一般不使用分组

3.1基本使用

@AllArgsConstructor@NoArgsConstructor@Data@Accessors(chain = true)public class User implements Serializable {    @NotNull(message="不能为空")//含有属性groups    private  String  name;}
@RestControllerpublic class UserController {    @GetMapping("/user")    public User  testUser(@Validated User user, BindingResult  result){        result.getAllErrors().stream().forEach((x)->{            System.out.println(x.getObjectName()+":"+x.getDefaultMessage());        });        return  user;    }}

输出结果:user:不能为空

备注:假如没有BindingResult result,那么在进入testUser之前就会被拦截,message="不能为空"并没有什么作用,加入BindingResult result之后,才会进入testUser方法,在没有进入方法时的异常页面见后该篇4

3.2自定义符合valid的注解

这里定义的是@NoNull注解

//会自动加载,不需要其他的配置public class MyValidAnnotation implements ConstraintValidator
{ /* obj:需要验证的参数 */ @Override public boolean isValid(Object obj, ConstraintValidatorContext constraintValidatorContext) { System.out.println(obj); return false; } @Override public void initialize(MyNotNull constraintAnnotation) { }}
@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)@Constraint(validatedBy =MyValidAnnotation.class )//添加在@validated的必要注解public @interface MyNotNull {    String message() default "{javax.validation.constraints.NotNull.message}";    Class
[] groups() default {}; Class
[] payload() default {};}
@AllArgsConstructor@NoArgsConstructor@Data@Accessors(chain = true)public class User implements Serializable {    @MyNotNull(message="不能为空---MyNotNull")    private  String  name;}
@RestControllerpublic class UserController {    @GetMapping("/user")    public User  testUser(@Validated User user, BindingResult  result){        result.getAllErrors().stream().forEach((x)->{            System.out.println(x.getObjectName()+":"+x.getDefaultMessage());        });        return  user;    }}

4.异常消息的处理

4.1验证异常消息的处理上述已经说明

4.2直接被拦截的异常处理

 

springboot会相应的转向我们在resources下新建的resources的error的相应的错误代码的页面

还可以是如下这样,表示以4开头的错误页面,例如

4.3运行过程中出现的异常

4.3.1直接抛出异常

@GetMapping("/user/error")    public User  testUser1(@Validated User user, BindingResult  result) throws Exception {        throw  new Exception("出错了");    }

 

4.3.2 throw自定义异常类

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR,reason = "内部出错了!")public class MyException extends RuntimeException {}
@GetMapping("/user/error")    public User  testUser1(@Validated User user, BindingResult  result) throws Exception {        throw  new MyException();    }

 

4.3.3 使用@ExceptionHandler注解

@ResponseBody    @GetMapping("/testExceptionHandler")    public User  testUser1(@Validated User user, BindingResult  result) throws Exception {        int  i=10/0;        return user;    }
@ExceptionHandler({Exception.class})    public String  testExceptionHandler(){        return   "redirect:/error.html"; //重定向,/站点目录    }

 4.3.4 修改状态码及原因,@ResponseStatus也能在

   @ExceptionHandler({Exception.class})    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR,reason = "内部错误")    public void  testExceptionHandler(){    }

 备注:这样之后不会去相应的页面,也就是加入有返回值例如return "redirect:/error.html";,会失效

4.3.5@ControllerAdvice定制全局的异常,类中的@ExceptionHandler优先级高于@ControllerAdvice中的@ExceptionHandler优先级

@ControllerAdvicepublic class MyExceptionHandler {    @ExceptionHandler({Exception.class})    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR,reason = "内部错误")    public void  testExceptionHandler(){    }}

5.jsonview

@NoArgsConstructor@AllArgsConstructor@Data@Accessors(chain = true)public class User implements Serializable {    public   interface  UserSimpleView{} ;    public   interface  UserDetailView  extends UserSimpleView{} ;   @JsonView(UserSimpleView.class)    private  String username;   @JsonView(UserDetailView.class)    private   Integer password;}
@RestControllerpublic class UserController {    @Autowired    UserMapper userMapper;    @GetMapping("/user/{username}")    @JsonView(User.UserSimpleView.class)    public  User   testGet(@PathVariable String  username){        User user = userMapper.getUserById(username);        return user;    }}

 

6.异步

6.1直接使用callable

@RestControllerpublic class AsyncController {    @Autowired    UserMapper  userMapper;    @GetMapping("/async/{username}")    @JsonView(User.UserSimpleView.class)    public  Callable
get(@PathVariable String username){ long id = Thread.currentThread().getId(); long start= Instant.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); Callable
callable = ()->{ long id1 = Thread.currentThread().getId(); long start1= Instant.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); User user = userMapper.getUserById(username); long end1= Instant.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); System.out.println("副线程"+id1+":"+(end1-start1)); return user; }; long end= Instant.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant().toEpochMilli(); System.out.println("主线程"+id+":"+(end-start)); return callable; }}

 

6.2 使用DeferredResult实现异步

@Bean("queue")    public ConcurrentLinkedQueue
concurrentLinkedQueue() throws IOException { ConcurrentLinkedQueue
queue = new ConcurrentLinkedQueue<>(); return queue; } @Bean("map") public Map
> map(){ return new HashMap(); }
@Autowired    ConcurrentLinkedQueue
queue;@Autowired Map map; @GetMapping("/async/deferredResult") public Object message(@RequestParam(required = false) String message){ if(StringUtils.isNotBlank(message)){ queue.add(message); DeferredResult
result = new DeferredResult<>(); map.put(message, result); return result; } return "输入格式不正确"; }
@Componentpublic class QueueListener implements ApplicationListener {//启动监听器    @Autowired    ConcurrentLinkedQueue
queue; @Autowired Map
> map; @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { new Thread(()->{ while (true){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } if(queue.size()>0){ String msg = queue.poll(); System.out.println(msg); map.get(msg).setResult(msg); map.remove(msg); }else { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }}

 7.swagger

依赖

io.springfox
springfox-swagger-ui
2.9.2
io.springfox
springfox-swagger2
2.9.2

添加注解

@EnableSwagger2public class ControllerTest {

访问页面

http://127.0.0.1:8080/swagger-ui.html

 

增加描述信息

public class Book implements Serializable {    private   Integer  id;    @ApiModelProperty("名称")    private    String   name;    @ApiModelProperty("价格")    private    Integer  price;}

@GetMapping("/book/{id:\\d+}")      public Book get(@PathVariable @ApiParam("书本id") Integer id){            return  bookMapper.getBookById(id);      }

 

8.拦截器

8.1 HandlerInterceptor

@Componentpublic class MyHandlerIntercepter implements HandlerInterceptor {    //在调用目标方法之前执行    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        return true;//false表示后续拦截器不在执行    }    //在调用目标方法之后, 但渲染视图之前,    // 可以对请求域中的属性或视图做出修改.,出现异常不会执行该方法    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {       //能获取类名,方法名,但是不能获取方法的参数        System.out.println(((HandlerMethod)handler).getBean().getClass().getName());        System.out.println(((HandlerMethod)handler).getMethod().getName());    }    //之后执行,出现异常也会执行    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {    }}
@Configuration@ComponentScan(value = "springmvc.demo")@MapperScan("springmvc.demo.dao")public class MVCConfig implements WebMvcConfigurer {    @Autowired    MyHandlerIntercepter myHandlerIntercepter;    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(myHandlerIntercepter);    }}

 8.2 AOP(拦截的增强版)

org.springframework.boot
spring-boot-starter-aop
@Aspect@Componentpublic class MyAOP {    @Pointcut("execution(* springmvc.demo.controller..*(*))")    public  void pointcut(){}    @Around("pointcut()")    public  Object before(ProceedingJoinPoint joinPoint)  {        try {            Object[] args = joinPoint.getArgs();            Arrays.stream(args).forEach(System.out::println);            Object proceed = joinPoint.proceed();//相当于拦截器的dochain方法,否则不会执行下去            return proceed;//返回结果后才会有值        } catch (Throwable throwable) {            return throwable.getMessage();        }    }}

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/gg128/p/9940941.html

你可能感兴趣的文章
透视Facebook算法帝国 ,我们只是工程思维的螺丝钉
查看>>
AI和机器学习的快速发展惠及数据存储行业
查看>>
IPv4的消逝之路将漫长而缓慢
查看>>
论数据库运维的全流程管控技术
查看>>
打造"数据供应链"百分点发布大数据战略
查看>>
Relay2携边缘计算产品参加中国移动盛会
查看>>
21世纪编程语言死亡名单,Java、Python、Go等均在劫难逃
查看>>
小心!使用网页版的WhatsApp时,请选择隐私模式
查看>>
三招防护! 别让你的设备不经意中招
查看>>
炒鸡棒的模糊测试技术
查看>>
“一中心三平台”:智慧洪泽迈入成效年
查看>>
英特尔收购Movidius进军计算机人工智能视觉领域
查看>>
关于自动化网络监控的真相
查看>>
嵌入式开发正在迎来“软实力”革命
查看>>
世界最大OpenStack私有云是如何运营的
查看>>
黑客租用阿里云平台攻击淘宝,9900万账户信息遭窃取
查看>>
开发者的实用Vim插件(一)
查看>>
使用Azure托管磁盘简化云存储管理
查看>>
爱数助力中国银行苏州分行信息化建设
查看>>
我国已建成全球规模最大4G网络
查看>>