硬核!springmvc全面详解,包含各种核心知识点!

您所在的位置:网站首页 项目讲解的重点内容 硬核!springmvc全面详解,包含各种核心知识点!

硬核!springmvc全面详解,包含各种核心知识点!

2024-07-15 17:25:55| 来源: 网络整理| 查看: 265

已同步微信公众号乐享Coding,获取更多Java学习资源,技术交流群 期待你的关注!

SpringMVC总结整理

web开发底层是servlet,框架是在servlet基础上面加一些功能,方便web开发。

SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品。它通过一套注解,让一个简单的Java类成为处理请求的控制器,而无须实现任何接口。同时还支持Restful编程风格的请求。

将应用程序分为Controller,Model,View三层,Controller接收用户请求,调用Model生成业务数据,传递给View。

核心组件 前端控制器(DispatcherServlet)

**【总指挥】**负责接收用户的提交的所有请求,如传统的jsp文件,调用其他的控制器Controller对象,并把请求处理的结果显示给用户。

// web.xml文件中配置 DispatcherServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:spring_mvc.xml 1 DispatcherServlet / 处理器(Handler)

完成具体的业务逻辑,相当于servlet或action。

// 就是一个方法 请求到处理器映射(HandlerMapping)

DispatcherServlet接收到请求之后,通过HandlerMapping将不同的请求映射到不同的请求映射到不同的Handler。

// @RequestMapping注解将URL请求与业务方法(Handler)映射 处理器适配器(HandlerAdapter) Handler执行业务方法之前,需要进行一系列的操作,如表单数据的验证,数据类型的转换,将表单数据封装成JavaBean等,因此开发者只需将注意力集中到业务逻辑的处理上,DispatcherServlet通过HandlerAdapter执行不同的Handler。 视图解析器(ViewResolver)

DispatcherServlet通过它将逻辑视图转换为物理视图,最终将渲染结果响应给客户端。

// resource文件夹下spring_mvc.xml配置视图解析器 处理器拦截器(HandlerInterceptor) 是一个接口,如果需要完成拦截处理,实现该接口。 处理器执行链(HandlerExecutionChain) 处理器执行链,包含两部分,HandlerInterceptor和Handler ModelAndView

装载了模型数据和视图信息,作为Handler的处理结果(业务方法返回ModelAndView对象),之后返回给DispatcherServlet做下一步处理。

工作流程 客户端请求被DispatcherServlet接收。根据HandlerMapping映射到Handler。生成Handler和HandlerInterceptor。Handler和HandlerInterceptor以HandlerExecutionChain的形式一并返回给DispatcherServlet。DispatcherServlet通过HandlerAdapter调用Handler的方法完成业务逻辑处理。Handler返回一个ModerAndView对象给DispatcherServlet。DispatcherServlet将获取的ModerAndView对象传给ViewResolver视图解析,将逻辑视图解析为物理视图View。ViewResolver返回一个View给DispatcherServlet。DispatcherServlet根据View进行视图渲染(将模型数据Model填充到视图View中)DispatcherServlet将渲染后的结果响应给客户端。

实际开发

流程非常复杂,实际开发中使用极其简单,因为大部分的组件不需要开发者创建,管理,只需要通过配置文件的方式完成配置即可,真正需要开发者进行处理的只有Handler,View。

Tomcat运行配置 打war包

IDEA中按快捷键ctrl+alt+shift+s打开project Structure

之后在tomcat中配置war包启动

注意

每次pom.xml中导入新的依赖,需要看war包中是否也导入成功了,有时会没有导入就手动添加上。

中文乱码问题 前端发起请求后端收到却包含中文乱码 解决办法,只需在web.xml配置SpringMVC自带的过滤器即可。 encodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 encodingFilter /* 后端响应前端JSON数据时乱码 解决办法,spring_mvc.xml配置消息转换器 注解 【@RequestMapping】

将URL请求与业务方法进行映射,在Handler的类定义处以及方法定义处都可以添加@RequestMapping。

相关参数

value:指定URL请求的实际地址,是@RequestMapping的默认值。

@RequestMapping(value = "/index") @RequestMapping("/index")

method:指定请求的method类型,GET,POST,PUT,DELET

@RequestMapping(value = "/index",method = RequestMethod.GET)

表示只能接受GET请求。

params:指定请求中必须包含某些参数,否则无法调用该方法。

@RequestMapping(value = "/index", method = RequestMethod.GET, params = {"name", "id"= 1 })

该代码表示请求中必须包含name和id两个参数,同时id的值必须是1。

方法中可以传递请求中接收的参数,分两种情况

假设是index方法

请求参数与形参名称相同

@RequestMapping(value = "/index", method = RequestMethod.GET, params = {"name", "id"= 1 }) public String index(String name,int id) { System.out.println(name+id); return "index"; }

请求参数与形参名称不相同【需要加@RequestParam注解进行参数绑定】

@RequestMapping(value = "/index", method = RequestMethod.GET, params = {"name", "id"= 1 }) public String index(@RequestParam("name") String str,@RequestParam("id") int sid) { System.out.println(name+id); return "index"; }

该代码表示将请求的参数name和id分别赋值给了形参str和sid,同时完成了数据类型的转换,将字符串类型“1”转换为了int类型1,再赋给sid,这些工作都是由HandlerAdapter来完成的。

Restful风格的URL

传统类型传递参数 http://localhost:8080/index?name=xiaole&id=1

Restful传递参数 http://localhost:8080/index/xiaole/1

@RequestMapping("/restful/{name}/{id}") public String restful(@PathVariable("name") String name,@PathVariable("id") int sid) { System.out.println(name+id); return "index"; }

Tips:无论请求参数名和业务方法中形参是否相同,都需要加@PathVariable注解进行映射

映射 Cookie

Spring MVC通过映射可以直接在业务方法中获取Cookie的值。

@RequestMapping("/cookie") public String cookie(@CookieValue(value = "JSESSIONID") String sessionId) { System.out.println(sessionId); return "index"; }

使用JavaBean绑定参数

Spring MVC 会根据请求参数名和JavaBean属性名进行自动匹配,自动为对象填充属性值,同时支持级联属性(对象中包含对象的属性)

实体类 User 和 Address(文件夹Entity) @Data //必须加,否则接收不到 public class User { private Integer id; private String name; private Address address; //级联属性 } @Data public class Address { private String value; } JSP文件的前端表单 用户id : 用户名: 地址: html Controller包下的handler类业务方法 @RequestMapping(value = "/hello/save", method = RequestMethod.POST) public String save(User user) { System.out.println(user); return "index"; } @RequestMapping("/hello") public String submit() { return "register"; }

测试地址:http://localhost:8080/hello

Tips:需要配置解决乱码(过滤器)

html页面进行转发和重定向

【转发】默认

return "forward:/index"; == return "index";

【重定向】

return "redirect:/index"; 【@Controller】

在类定义处添加,将该类交给IOC容器来管理(结合springmvc.xml的自动扫描配置使用),同时使其成为一个控制器,使得每一个业务方法的返回值都会交给视图解析器进行解析。

【@Requestbody】

不进行视图解析

在类定义处添加,也可以单独在方法中添加,表示直接将业务方法的返回值响应给客户端,不加的话返回的话,会将返回值传递给DispatcherServlet,再由DispatcherServlet调用ViewResolver对值进行解析,映射到一个jsp资源或html资源。

【@RestController】

@Requestbody+@Controller,在类定义处添加,包含两个注解的功能,即其类下的所有业务方法都不进行解析视图。

数据绑定

在后端的业务方法中直接获取客户端HTTP请求中的参数,将请求的参数映射到业务方法的形参中,Spring MVC中数据绑定的工作是由HandlerAdapter来完成的。

【基本数据类型】 @ResponseBody //直接将业务方法的返回值响应给客户端,不需要视图解析 public String base(int id) {}; //业务方法中传基本数据类型int 【包装类】

建议使用,因为可以接收null值,当HTTP请求没有参数时,不会抛出异常,基本数据类型不行。

@ResponseBody //直接将业务方法的返回值响应给客户端,不需要视图解析 public String pack(Integer id) {}; //业务方法中传包装类Integer public String pack(@RequestParam(value = "num",required = false,defaultValue = "10") Integer id) {}; //也可以加@RequestParam注解,required属性是必须加或否,范围布尔值,false情况下可设默认值 【集合】 创建userList实体类 @Data public class userList { private List userList; } JSP前端页面 用户1id : 用户1名: 1地址: 用户2id : 用户2名: 2地址: 业务方法 @RequestMapping("/list") @ResponseBody public String submitList(userList userList) { StringBuffer str= new StringBuffer(); //解决+号影响效率 for (User user:userList.getUserList() ) { str.append(user); } return str.toString(); }

测试地址:http://localhost:8080/List.jsp

【Map】 创建UserMap实体类 @Data public class UserMap { private Map userMap; } 业务方法 @RequestMapping(value = "/map", method = RequestMethod.POST) @ResponseBody public String submitMap(UserMap userMap) { StringBuffer str = new StringBuffer(); for (String key : userMap.getUserMap().keySet()) { str.append(userMap.getUserMap().get(key)); //根据key找到value } return str.toString(); } JSP前端页面 用户1id : 用户1名: 1地址: 用户2id : 用户2名: 2地址:

测试地址:http://localhost:8080/Map.jsp

【JSON数据】 引入jquery静态文件,需要注意,js文件不需要被DispatcherServlet处理,因此在web.xml中配置静态文件过滤。 default *.js 通过Ajax异步向后台传递JSON数据,前端代码: $(function () { var User = { "id": 1, "name": "寒风" } $.ajax({ url: "/json", data: JSON.stringify(User), type: "POST", contentType: "application/json;charset=UTF-8", dataType: "JSON", success: function (data) { alert(data.id + "____" + data.name); } }) })

后端业务方法

还需要考虑到前端JSON数据传来需要阿里工具包fastjson在后端转换为JavaBean!

pom.xml导入fastjson依赖 com.alibaba fastjson 1.2.62 spring_mvc.xml进行配置fastjson text/html;charset=UTF-8 application/json;charset=UTF-8 @RequestMapping(value = "/json", method = RequestMethod.POST) @ResponseBody public User submitJson(@RequestBody User user) { //@RequestBody 接收前端Json数据 System.out.println(user); user.setId(56); user.setName("小红"); return user; }

测试地址:http://localhost:8080/json.jsp

可能出现两个问题

springMVC版本太高不兼容,这里推荐

5.2.6.RELEASE

fastjson的jar包为打进war包,需要手动导入。

自定义数据转换器

数据转换器是指将客户端 HTTP 请求中的参数转换为业务方法中定义的形参,自定义表示开发者可以自主设计转换的方式,HandlerApdter 已经提供了通用的转换,String 转 int,String 转 double,表单数据的封装等,但是在特殊的业务场景下,HandlerAdapter 无法进行转换,就需要开发者自定义转换器。

概括:前端请求参数 ( 映射–>) 业务方法中的形参 ,参数的数据类型也可能需要转换。

举例

Date类型与String类型的转换

创建 DateConverter 转换器,实现 Conveter 接口。 public class DateConverter implements Converter { private String pattern; public DateConverter(String pattern){ this.pattern = pattern; } @Override public Date convert(String s) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.pattern); Date date = null; try { date = simpleDateFormat.parse(s); } catch (ParseException e) { e.printStackTrace(); } return date; } } springmvc.xml 配置转换器。 text/html;charset=UTF-8 application/json;charset=UTF-8 JSP表单页面 请输入日期:(yyyy-MM-dd) Handler(业务方法) @RestController @RequestMapping("/converter") public class ConverterHandler { @RequestMapping("/date") public String date(Date date){ return date.toString(); } }

测试地址http://localhost:8080/date.jsp

模型数据解析

JSP 四大作用域对应的内置对象:pageContext、request、session、application。

模型数据的绑定是由 ViewResolver 来完成的,实际开发中,我们需要先添加模型数据(model),再交给 ViewResolver 来绑定(View)。

Spring MVC 提供了以下几种方式添加模型数据:

【Map】【Model】【ModelAndView】【@SessionAttribute】【@ModelAttribute】 绑定到request 对象

JSP页面

Title ${requestScope.user} 1、Map //通过map将数据传到request域对象里面 @RequestMapping("/map") public String map(Map map){ User user = new User(); user.setId(1); user.setName("寒风"); map.put("user",user); return "view"; }

测试地址http://localhost:8080/map

// User(id=1, name=寒风, address=null) 2、Model //通过model将数据传到request域对象里面 @RequestMapping("/model") public String model(Model model){ User user = new User(); user.setId(1); user.setName("寒风"); model.addAttribute("user",user); return "view"; }

测试地址http://localhost:8080/model

// User(id=1, name=寒风, address=null) 3、ModelAndView //通过ModelAndView将数据传到request域对象里面 @RequestMapping("/modelAndView") public ModelAndView modelAndView(){ User user = new User(); user.setId(1); user.setName("寒风"); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("user",user); modelAndView.setViewName("view"); return modelAndView; } @RequestMapping("/modelAndView2") public ModelAndView modelAndView2(){ User user = new User(); user.setId(1); user.setName("寒风"); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("user",user); View view = new InternalResourceView("/view.jsp"); modelAndView.setView(view); return modelAndView; } @RequestMapping("/modelAndView3") public ModelAndView modelAndView3(){ User user = new User(); user.setId(1); user.setName("寒风"); ModelAndView modelAndView = new ModelAndView("view"); modelAndView.addObject("user",user); return modelAndView; } @RequestMapping("/modelAndView4") public ModelAndView modelAndView4(){ User user = new User(); user.setId(1); user.setName("寒风"); View view = new InternalResourceView("/view.jsp"); ModelAndView modelAndView = new ModelAndView(view); modelAndView.addObject("user",user); return modelAndView; } @RequestMapping("/modelAndView5") public ModelAndView modelAndView5(){ User user = new User(); user.setId(1); user.setName("寒风"); Map map = new HashMap(); map.put("user",user); ModelAndView modelAndView = new ModelAndView("view",map); return modelAndView; } @RequestMapping("/modelAndView6") public ModelAndView modelAndView6(){ User user = new User(); user.setId(1); user.setName("寒风"); Map map = new HashMap(); map.put("user",user); View view = new InternalResourceView("/view.jsp"); ModelAndView modelAndView = new ModelAndView(view,map); return modelAndView; } @RequestMapping("/modelAndView7") public ModelAndView modelAndView7(){ User user = new User(); user.setId(1); user.setName("寒风"); ModelAndView modelAndView = new ModelAndView("view","user",user); return modelAndView; } @RequestMapping("/modelAndView8") public ModelAndView modelAndView8(){ User user = new User(); user.setId(1); user.setName("寒风"); View view = new InternalResourceView("/view.jsp"); ModelAndView modelAndView = new ModelAndView(view,"user",user); return modelAndView; }

测试地址http://localhost:8080/modelAndView

4、HttpServletRequest @RequestMapping("/request") public String request(HttpServletRequest request){ User user = new User(); user.setId(1); user.setName("寒风"); request.setAttribute("user",user); return "view"; } 5、@ModelAttribute 定义一个方法,该方法专门用来返回要填充到模型数据中的对象。 @ModelAttribute public User getUser(){ User user = new User(); user.setId(1); user.setName("寒风"); return user; } @ModelAttribute public void getUser(Map map){ User user = new User(); user.setId(1); user.setName("寒风"); map.put("user",user); } @ModelAttribute public void getUser(Model model){ User user = new User(); user.setId(1); user.setName("寒风"); model.addAttribute("user",user); } 业务方法中无需再处理模型数据,只需返回视图即可。 @RequestMapping("/modelAttribute") public String modelAttribute(){ return "view"; } 绑定到 session 对象 1、原生的 Servlet API @RequestMapping("/session") public String session(HttpServletRequest request){ HttpSession session = request.getSession(); User user = new User(); user.setId(1); user.setName("寒风"); session.setAttribute("user",user); return "view"; } @RequestMapping("/session2") public String session2(HttpSession session){ User user = new User(); user.setId(1); user.setName("寒风"); session.setAttribute("user",user); return "view"; } 2、@SessionAttribute @SessionAttributes(value = {"user","address"}) public class ViewHandler { }

对于 ViewHandler 中的所有业务方法,只要向 request 中添加了 key = “user”、key = “address” 的对象时,Spring MVC 会自动将该数据添加到 session 中,保存 key 不变。

@SessionAttributes(types = {User.class,Address.class}) public class ViewHandler { }

对于 ViewHandler 中的所有业务方法,只要向 request 中添加了数据类型是 User 、Address 的对象时,Spring MVC 会自动将该数据添加到 session 中,保存 key 不变。

绑定到 application 对象 @RequestMapping("/application") public String application(HttpServletRequest request){ ServletContext application = request.getServletContext(); User user = new User(); user.setId(1); user.setName("寒风"); application.setAttribute("user",user); return "view"; } REST

REST:Representational State Transfer,资源表现层状态转换,是目前比较主流的一种互联网软件架构,它结构清晰、标准规范、易于理解、便于扩展。

资源(Resource)

网络上的一个实体,或者说网络中存在的一个具体信息,一段文本、一张图片、一首歌曲、一段视频等等,总之就是一个具体的存在。可以用一个 URI(统一资源定位符)指向它,每个资源都有对应的一个特定的 URI,要获取该资源时,只需要访问对应的 URI 即可。

表现层(Representation)

资源具体呈现出来的形式,比如文本可以用 txt 格式表示,也可以用 HTML、XML、JSON等格式来表示。

状态转换(State Transfer)

客户端如果希望操作服务器中的某个资源,就需要通过某种方式让服务端发生状态转换,而这种转换是建立在表现层之上的,所以叫做"表现层状态转换"。

特点 URL 更加简洁。有利于不同系统之间的资源共享,只需要遵守一定的规范,不需要进行其他配置即可实现资源共享。 如何使用

REST 具体操作就是 HTTP 协议中四个表示操作方式的动词分别对应 CRUD 基本操作。

GET 用来表示获取资源。

POST 用来表示新建资源。

PUT 用来表示修改资源。

DELETE 用来表示删除资源。

Handler业务方法(增删改查)

@RestController @RequestMapping("/rest") public class RestfulHandler { @Autowired private StudentRepository studentRepository; //查 发送get请求 @GetMapping("/findAll") public Collection findAll(HttpServletResponse response){ response.setContentType("text/json;charset=UTF-8"); return studentRepository.findAll(); } @GetMapping("/findById/{id}") public Student findById(@PathVariable("id") Integer id){ return studentRepository.findById(id); } //增 发送post请求 @PostMapping("/save") public void save(@RequestBody Student student){ studentRepository.saveOrUpdate(student); } //改 发送put请求 @PutMapping("/update") public void update(@RequestBody Student student){ studentRepository.saveOrUpdate(student); } //删 发送delete请求 @DeleteMapping("/deleteById/{id}") public void deleteById(@PathVariable("id") Integer id){ studentRepository.deleteById(id); } }

模拟Service层接口

public interface StudentRepository { Collection findAll(); Student findById(Integer id); void saveOrUpdate(Student student); void deleteById(Integer id); }

Service层实现类+模拟数据库(Dao层)

@Repository //交给IOC容器 public class StudentRepositoryImpl implements StudentRepository { private static Map studentMap; static { studentMap = new HashMap(); studentMap.put(1, new Student(1, "小寒", 22)); studentMap.put(2, new Student(2, "小肖", 18)); studentMap.put(3, new Student(3, "小乐", 18)); } @Override public Collection findAll() { return studentMap.values(); } @Override public Student findById(Integer id) { return studentMap.get(id); } @Override public void saveOrUpdate(Student student) { studentMap.put(student.getId(), student); } @Override public void deleteById(Integer id) { studentMap.remove(id); } }

实体类Student

@Data @AllArgsConstructor public class Student { private Integer id; private String name; private Integer age; }

测试地址: http://localhost:8080/rest/findAll (查) 注:增删改用Postman

文件上传下载 单文件上传

底层是使用 Apache fileupload 组件完成上传,Spring MVC 对这种方式进行了封装。

pom.xml导入commons-io和commons-fileupload的jar包 commons-io commons-io 2.5 commons-fileupload commons-fileupload 1.3.3 upload.jsp页面 Title

1、input 的 type 设置为 file。

2、form 的 method 设置为 post(get 请求只能将文件名传给服务器)

3、from 的 enctype 设置为 multipart-form-data(如果不设置只能将文件名传给服务器)

Handler业务方法 @Controller @RequestMapping("/file") public class FileHandler { @PostMapping("/upload") public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) { if (file.getSize() > 0) { //获取保存上传文件的file路径 String path = request.getServletContext().getRealPath("/upload"); File realpath = new File(path); //获取上传的文件名 String name = file.getOriginalFilename(); //保存上传之后的文件路径 System.out.println("上传文件保存地址为:" + realpath); if (!realpath.exists()) realpath.mkdir(); try { file.transferTo(new File(realpath + "/" + name)); request.setAttribute("path","/upload/" + name); } catch (IOException e) { e.printStackTrace(); } } return "upload"; } } spring_mvc.xml配置上传组件 web.xml 配置静态文件(.png和.jpg)过滤,否则客户端无法访问 png和jpg文件 default *.png default *.jpg 多文件上传 pom.xml还需额外导入jstl和taglibs的jar包 jstl jstl 1.2 taglibs standard 1.1.2 uploads.jsp页面 Title file1: file2: file3: Handler业务方法 @PostMapping("/uploads") public String uploads(@RequestParam("files") CommonsMultipartFile[] files,HttpServletRequest request){ List fileList = new ArrayList(); for (MultipartFile file:files){ if(file.getSize()>0){ //获取保存上传文件的file路径 String path = request.getServletContext().getRealPath("/upload"); //获取上传的文件名 String name = file.getOriginalFilename(); File realpath = new File(path); //如果不存在upload文件夹,就自动创建 if (!realpath.exists()) realpath.mkdir(); try { file.transferTo(new File(realpath + "/" + name)); //保存上传之后的文件路径 fileList.add("/upload/"+name); } catch (IOException e) { e.printStackTrace(); } } } request.setAttribute("Files",fileList); return "uploads"; } 文件下载 Handler业务方法 @GetMapping("/download/{name}") public void download(@PathVariable("name") String name, HttpServletRequest request, HttpServletResponse response){ if(name != null){ name += ".png"; String path = request.getServletContext().getRealPath("/upload"); File file = new File(path,name); OutputStream outputStream = null; if(file.exists()){ response.setContentType("application/forc-download"); response.setHeader("Content-Disposition","attachment;filename="+name); try { outputStream = response.getOutputStream(); outputStream.write(FileUtils.readFileToByteArray(file)); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if(outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } } download.jsp页面 Title 1.png 2.png 3.png 后端数据校验 Annotation JSR - 303 标准

使用 Annotation JSR - 303 标准进行验证,需要导入支持这种标准的依赖 jar 文件,这里我们使用 Hibernate Validator。

创建实体Person类 @Data public class Person { @NotEmpty(message = "用户名不能为空") private String username; @Size(min = 6, max = 12, message = "密码6-12位") private String password; @Email(message = "请输入正确的邮箱格式") private String email; @Pattern(regexp = "^(13[0-9]|14[01456879]|15[0-3,5-9]|16[2567]|17[0-8]|18[0-9]|19[0-3,5-9])\\d{8}$", message = "请输入正确的电话") private String phone; } 业务方法 @Controller public class validationHandler { @GetMapping("/validator") public String register(Model model){ model.addAttribute("person",new Person()); return "validator"; } @PostMapping("/validator") public String register(@Valid Person person, BindingResult bindingResult){ if(bindingResult.hasErrors()){ return "validator"; } return "index"; } } validator.jsp页面 Title 用户名: 密码: 邮箱: 电话: 测试页面



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭