[JavaWeb学习日记]JSP+Cookie+Filter与登录+CRUD案例
目录
一.JSP
二.EL表达式与JSTL标签
三.Cookie
四.Session
五.Filter
六. 登录+CRUD:品牌增删改查案例
Demo一览
1.导包
2.构建包结构
3.创建数据库表tb_brand与user
4.创建实体类
5.mybatis的配置文件和logback配置文件
6.写接口
7.工具类:生成图片与SqlSession创建
8.写service方法
9.css
10. Filter过滤器限制必须登录
11.index.jsp,login.jsp与register.jsp
12.登录注册的Servlet
13.增删改查有关的jsp与Servlet
如今JSP已不再是热门的前端工具,不建议深入学习,而Cookie与Filter可以了解了解
通过maven建立web工程,工程目录如下,学习的内容为java代码以及两个jsp文件
pom需要导入的依赖:
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version></dependency><!--使用jsp需要导入的包--><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version></dependency><!--使用jstl标签需要导入的两个包--><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency>
一.JSP
1.JSP(JavaServerPages):既可以写html,又能写java代码会把jsp文件转换为java文件并编译执行,本质为Servlet服务资源 2.使用在jsp中引用别的类:需要导包 3.在jsp文件中写java代码:<%xxx%> 4.插入数据到前端代码上:<%=xxx%>
index.jsp:
<%@ page import="org.example.pojo.Brand" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<%List<Brand> brands = new ArrayList<>();System.out.println("HelloJSP!");String str="JSP!";
%>
<%="你好,"+str%><br>
</body>
</html>
IDE控制台与浏览器都会有输出
二.EL表达式与JSTL标签
案例:获取servlet传过来的集合对象中的数据
EL表达式:主要功能为获取在请求转发/cookie/session中存储的键为XXX的数据 JSTL:用标签替换JSP上面的java代码,如判断与循环 1.使用EL表达式开启需要声明:<%@page isELIgnored="false" %>jsp文件中使用el表达式获取数据:${xxx} 2.使用jstl标签需要1.pom文件导包2.引入taglib标签:<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>3.常见的jstl标签:c:if与c:forEach 3.c:if标签指定判断条件:test属性 4.c:foreach标签指定1.遍历的数据:items属性2.遍历数据中单个元素的名字:var属性(var.xxx会调用该对象的类中对应的getXxx方法)3.遍历过程中的序号名:varStatus属性varStatus的属性:index从0开始计数|count从1开始计数4.指定遍历时设置var的开始,结束,步长:begin,end,step
jstl.jsp:
<%@page isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title></head>
<body>
<c:if test="true"><h3>true</h3></c:if>
<c:if test="${status==1}"><h3>${status}</h3></c:if>
<table border="1" cellspacing="0" width="800"><c:forEach items="${brands}" var="brand" varStatus="status"><tr align="center"><td>${status.count}</td><td>${brand.brandName}></td><td>${brand.companyName}></td><td>${brand.ordered}</td><td>${brand.description}</td><td><c:if test="${brand.status==1}"><%="启用"%></c:if><c:if test="${brand.status==0}"><%="禁用"%></c:if></td><td><a href="">修改 </a><a href="">删除</a></td></tr></c:forEach>
</table>
<hr>
<c:forEach begin="1" end="10" step="1" var="i"><a href="">${i}</a>
</c:forEach>
</body>
</html>
public class Brand {private Integer id;private String brandName;private String companyName;private Integer ordered;private String description;private Integer status;public Brand() {}public Brand(Integer id, String brandName, String companyName, String description) {this.id = id;this.brandName = brandName;this.companyName = companyName;this.description = description;}public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {this.id = id;this.brandName = brandName;this.companyName = companyName;this.ordered = ordered;this.description = description;this.status = status;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrandName() {return brandName;}public void setBrandName(String brandName) {this.brandName = brandName;}public String getCompanyName() {return companyName;}public void setCompanyName(String companyName) {this.companyName = companyName;}public Integer getOrdered() {return ordered;}public void setOrdered(Integer ordered) {this.ordered = ordered;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered=" + ordered +", description='" + description + '\'' +", status=" + status +'}';}
}
Servlet: 把数据存储到request域中,再转发到jsp资源中。
@WebServlet("/jsp")
public class JSPDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {List<Brand> brands = new ArrayList<>();brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));request.setAttribute("status",1);request.setAttribute("brands",brands);request.getRequestDispatcher("/jstl.jsp").forward(request,response);}
}
三.Cookie
会话跟踪:HTTP协议每次向浏览器请求数据时,会将该请求视为新请求 服务器需要识别多次请求是否来自同一浏览器以便在多次请求间共享数据 1.查看cookies:谷歌控制台application 2.Cookies的实现基于HTTP协议(响应头,请求头),Session基于cookie实现(发送sessionId) 3.发送cookie:以键值对的形式创建cookie,使用响应对象添加cookie 4.设置cookie对象的在浏览器中的存活时间:单位为秒,cookie默认为浏览器关闭cookie消失 5.接收cookie:通过请求对象接收所有cookie数组并遍历
@WebServlet("/cookie")
public class CookieDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Cookie cookie = new Cookie("username", "zhangsan");cookie.setMaxAge(60);response.addCookie(cookie);Cookie[] cookies = request.getCookies();for (Cookie c : cookies) {System.out.println(c.getName() + ":" + c.getValue());}}
}
访问目标路径两次得到如下结果:
四.Session
1.存Session:通过请求对象存储数据到Session中 2.获取session对象中对应键的值,后移除键值对 3.在web.xml中设置session存活时间
@WebServlet("/session")
public class SessionDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response){HttpSession session=request.getSession();session.setAttribute("username","zhangsan");System.out.println(session.getAttribute("username"));session.removeAttribute("username");}
}
web.xml:
<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><session-config><!--单位分钟--><session-timeout>1</session-timeout></session-config>
</web-app>
五.Filter
用于拦截访问的资源
//拦截资源目录,和@WebServlet一样的写法
@WebFilter("/session")
public class FilterDemo implements Filter {public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("拦截资源后放行......");filterChain.doFilter(servletRequest,servletResponse);System.out.println("放行后输出......");}public void init(FilterConfig filterConfig) {}public void destroy() {}
}
六. 登录+CRUD:品牌增删改查案例
Demo一览
1.导包
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.32</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency>
2.构建包结构
3.创建数据库表tb_brand与user
4.创建实体类
public class Brand {private Integer id;private String brandName;private String companyName;private Integer ordered;private String description;private Integer status;public Brand() {}public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {this.id = id;this.brandName = brandName;this.companyName = companyName;this.ordered = ordered;this.description = description;this.status = status;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrandName() {return brandName;}public void setBrandName(String brandName) {this.brandName = brandName;}public String getCompanyName() {return companyName;}public void setCompanyName(String companyName) {this.companyName = companyName;}public Integer getOrdered() {return ordered;}public void setOrdered(Integer ordered) {this.ordered = ordered;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered=" + ordered +", description='" + description + '\'' +", status=" + status +'}';}
}
public class User {private Integer id;private String username;private String password;public User() {}public User(String username, String password) {this.username = username;this.password = password;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
5.mybatis的配置文件和logback配置文件
mybatis.config
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><typeAliases><package name="org.example.pojo"/></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///db1?useSSL=false"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><mappers><package name="org.example.mapper"/></mappers> </configuration>
logback.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration><appender name="Console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>[%level] %boldGreen(%logger{15}) - %msg %n</pattern></encoder></appender><root level="DEBUG"><appender-ref ref="Console"/></root> </configuration>
BrandMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.example.mapper.BrandMapper"><resultMap id="brandResultMap" type="Brand"><id column="id" property="id"/><result column="brand_name" property="brandName"/><result column="company_name" property="companyName"/></resultMap> </mapper>
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.example.mapper.UserMapper"> </mapper>
6.写接口
public interface BrandMapper {@ResultMap("brandResultMap")@Select("select * from tb_brand")List<Brand> selectAll();@Insert("insert into tb_brand values (null,#{brandName},#{companyName},#{ordered},#{description},#{status})")void add(Brand brand);@ResultMap("brandResultMap")@Select("select * from tb_brand where id=#{id}")Brand selectById(int id);@Update("update tb_brand set brand_name=#{brandName}," +"company_name=#{companyName}," +"ordered=#{ordered}," +"description=#{description}," +"status=#{status} " +"where id=#{id}")void update(Brand brand);@Delete("delete from tb_brand where id=#{id}")void deleteById(int id);
}
public interface UserMapper {@Select("select * from user where username = #{username} and password = #{password}")User select(@Param("username") String username, @Param("password") String password);@Select("select * from user where username = #{username}")User selectByUsername(String username);@Insert("insert into user values(null,#{username},#{password})")void add(User user);
}
7.工具类:生成图片与SqlSession创建
public class CheckCodeUtil {//生成验证码工具类public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";private static Random random = new Random();public static void main(String[] args) throws Exception{OutputStream fos=new FileOutputStream("D:\\IDEACode\\demo2\\Web\\web-demo4-brandDemo\\src\\main\\webapp\\imgs\\a.jpg");String checkCode=CheckCodeUtil.outputVerifyImage(100,50,fos,4);System.out.println(checkCode);}//输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多)//图片宽高,输出流与数据长度//返回验证码数据public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, os, verifyCode);return verifyCode;}//使用系统默认字符源生成验证码public static String generateVerifyCode(int verifySize) {return generateVerifyCode(verifySize, VERIFY_CODES);}//使用指定源生成验证码public static String generateVerifyCode(int verifySize, String sources) {// 未设定展示源的字码,赋默认值大写字母+数字if (sources == null || sources.length() == 0) {sources = VERIFY_CODES;}int codesLen = sources.length();Random rand = new Random(System.currentTimeMillis());StringBuilder verifyCode = new StringBuilder(verifySize);for (int i = 0; i < verifySize; i++) {verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));}return verifyCode.toString();}//生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少)public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, outputFile, verifyCode);return verifyCode;}//生成指定验证码图像文件public static void outputImage(int w, int h, File outputFile, String code) throws IOException {if (outputFile == null) {return;}File dir = outputFile.getParentFile();//文件不存在if (!dir.exists()) {//创建dir.mkdirs();}try {outputFile.createNewFile();FileOutputStream fos = new FileOutputStream(outputFile);outputImage(w, h, fos, code);fos.close();} catch (IOException e) {throw e;}}//输出指定验证码图片流public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {int verifySize = code.length();BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D g2 = image.createGraphics();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 创建颜色集合,使用java.awt包下的类Color[] colors = new Color[5];Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,Color.PINK, Color.YELLOW};float[] fractions = new float[colors.length];for (int i = 0; i < colors.length; i++) {colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];fractions[i] = rand.nextFloat();}Arrays.sort(fractions);// 设置边框色g2.setColor(Color.GRAY);g2.fillRect(0, 0, w, h);Color c = getRandColor(200, 250);// 设置背景色g2.setColor(c);g2.fillRect(0, 2, w, h - 4);// 绘制干扰线Random random = new Random();// 设置线条的颜色g2.setColor(getRandColor(160, 200));for (int i = 0; i < 20; i++) {int x = random.nextInt(w - 1);int y = random.nextInt(h - 1);int xl = random.nextInt(6) + 1;int yl = random.nextInt(12) + 1;g2.drawLine(x, y, x + xl + 40, y + yl + 20);}// 添加噪点// 噪声率float yawpRate = 0.05f;int area = (int) (yawpRate * w * h);for (int i = 0; i < area; i++) {int x = random.nextInt(w);int y = random.nextInt(h);// 获取随机颜色int rgb = getRandomIntColor();image.setRGB(x, y, rgb);}// 添加图片扭曲shear(g2, w, h, c);g2.setColor(getRandColor(100, 160));int fontSize = h - 4;Font font = new Font("Algerian", Font.ITALIC, fontSize);g2.setFont(font);char[] chars = code.toCharArray();for (int i = 0; i < verifySize; i++) {AffineTransform affine = new AffineTransform();affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);g2.setTransform(affine);g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);}g2.dispose();ImageIO.write(image, "jpg", os);}private static Color getRandColor(int fc, int bc) {//随机颜色if (fc > 255) {fc = 255;}if (bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}private static int getRandomIntColor() {int[] rgb = getRandomRgb();int color = 0;for (int c : rgb) {color = color << 8;color = color | c;}return color;}private static int[] getRandomRgb() {int[] rgb = new int[3];for (int i = 0; i < 3; i++) {rgb[i] = random.nextInt(255);}return rgb;}private static void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private static void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private static void shearY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(40) + 10; // 50;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}
}
public class SqlSessionFactoryUtil {static SqlSessionFactory sqlSessionFactory;static { try {sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));}catch (Exception e){e.printStackTrace();}}public static SqlSessionFactory getssf(){return sqlSessionFactory;}
}
8.写service方法
public class BrandService {SqlSessionFactory sqlSessionFactory= SqlSessionFactoryUtil.getssf();public List<Brand> selectAll(){SqlSession sqlSession=sqlSessionFactory.openSession(true);BrandMapper mapper =sqlSession.getMapper(BrandMapper.class);List<Brand> brands=mapper.selectAll();sqlSession.close();return brands;}public void add(Brand brand){SqlSession sqlSession=sqlSessionFactory.openSession(true);BrandMapper mapper =sqlSession.getMapper(BrandMapper.class);mapper.add(brand);sqlSession.close();}public Brand selectById(int id){//更新数据时回显数据SqlSession sqlSession=sqlSessionFactory.openSession(true);BrandMapper mapper =sqlSession.getMapper(BrandMapper.class);Brand brand=mapper.selectById(id);sqlSession.close();return brand;}public void update(Brand brand){SqlSession sqlSession=sqlSessionFactory.openSession(true);BrandMapper mapper =sqlSession.getMapper(BrandMapper.class);mapper.update(brand);sqlSession.close();}public void deleteById(int id){SqlSession sqlSession=sqlSessionFactory.openSession(true);BrandMapper mapper =sqlSession.getMapper(BrandMapper.class);mapper.deleteById(id);sqlSession.close();}
}
public class UserService {SqlSessionFactory sqlSessionFactory= SqlSessionFactoryUtil.getssf();public User login(String username, String password){//登录需要设置cookie给浏览器,需要返回用户对象SqlSession sqlSession=sqlSessionFactory.openSession(true);UserMapper mapper=sqlSession.getMapper(UserMapper.class);User user=mapper.select(username,password);sqlSession.close();return user;}public boolean register(User user){SqlSession sqlSession=sqlSessionFactory.openSession(true);UserMapper mapper=sqlSession.getMapper(UserMapper.class);User u=mapper.selectByUsername(user.getUsername());if(u==null){mapper.add(user);}sqlSession.close();return u==null;}
}
9.css
login.css
* {margin: 0;padding: 0;
}html {height: 100%;width: 100%;overflow: hidden;margin: 0;padding: 0;background: url(../imgs/Desert1.jpg) no-repeat 0px 0px;background-repeat: no-repeat;background-size: 100% 100%;-moz-background-size: 100% 100%;
}body {display: flex;align-items: center;justify-content: center;height: 100%;
}#loginDiv {width: 37%;display: flex;justify-content: center;align-items: center;height: 380px;background-color: rgba(75, 81, 95, 0.3);box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.5);border-radius: 5px;
}#name_trip {margin-left: 50px;color: red;
}p {margin-top: 30px;margin-left: 20px;color: azure;
}#remember{margin-left: 15px;border-radius: 5px;border-style: hidden;background-color: rgba(216, 191, 216, 0.5);outline: none;padding-left: 10px;height: 20px;width: 20px;
}
#username{width: 200px;margin-left: 15px;border-radius: 5px;border-style: hidden;height: 30px;background-color: rgba(216, 191, 216, 0.5);outline: none;color: #f0edf3;padding-left: 10px;
}
#password{width: 202px;margin-left: 15px;border-radius: 5px;border-style: hidden;height: 30px;background-color: rgba(216, 191, 216, 0.5);outline: none;color: #f0edf3;padding-left: 10px;
}
.button {border-color: cornsilk;background-color: rgba(100, 149, 237, .7);color: aliceblue;border-style: hidden;border-radius: 5px;width: 100px;height: 31px;font-size: 16px;
}#subDiv {text-align: center;margin-top: 30px;
}
#loginMsg{text-align: center;color: aliceblue;
}
#errorMsg{text-align: center;color:red;
}
register.css
* {margin: 0;padding: 0;list-style-type: none;
}
.reg-content{padding: 30px;margin: 3px;
}
a, img {border: 0;
}body {background-image: url("../imgs/reg_bg_min.jpg") ;text-align: center;
}table {border-collapse: collapse;border-spacing: 0;
}td, th {padding: 0;height: 90px;}
.inputs{vertical-align: top;
}.clear {clear: both;
}.clear:before, .clear:after {content: "";display: table;
}.clear:after {clear: both;
}.form-div {background-color: rgba(255, 255, 255, 0.27);border-radius: 10px;border: 1px solid #aaa;width: 424px;margin-top: 150px;margin-left:1050px;padding: 30px 0 20px 0px;font-size: 16px;box-shadow: inset 0px 0px 10px rgba(255, 255, 255, 0.5), 0px 0px 15px rgba(75, 75, 75, 0.3);text-align: left;
}.form-div input[type="text"], .form-div input[type="password"], .form-div input[type="email"] {width: 268px;margin: 10px;line-height: 20px;font-size: 16px;
}.form-div input[type="checkbox"] {margin: 20px 0 20px 10px;
}.form-div input[type="button"], .form-div input[type="submit"] {margin: 10px 20px 0 0;
}.form-div table {margin: 0 auto;text-align: right;color: rgba(64, 64, 64, 1.00);
}.form-div table img {vertical-align: middle;margin: 0 0 5px 0;
}.footer {color: rgba(64, 64, 64, 1.00);font-size: 12px;margin-top: 30px;
}.form-div .buttons {float: right;
}input[type="text"], input[type="password"], input[type="email"] {border-radius: 8px;box-shadow: inset 0 2px 5px #eee;padding: 10px;border: 1px solid #D4D4D4;color: #333333;margin-top: 5px;
}input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus {border: 1px solid #50afeb;outline: none;
}input[type="button"], input[type="submit"] {padding: 7px 15px;background-color: #3c6db0;text-align: center;border-radius: 5px;overflow: hidden;min-width: 80px;border: none;color: #FFF;box-shadow: 1px 1px 1px rgba(75, 75, 75, 0.3);
}input[type="button"]:hover, input[type="submit"]:hover {background-color: #5a88c8;
}input[type="button"]:active, input[type="submit"]:active {background-color: #5a88c8;
}
.err_msg{color: red;padding-right: 170px;
}
#password_err,#tel_err{padding-right: 195px;
}#reg_btn{margin-right:50px; width: 285px; height: 45px; margin-top:20px;
}#checkCode{width: 100px;
}#changeImg{color: aqua;
}
10. Filter过滤器限制必须登录
设置放行资源:通过获取的路径来判断是否包含目标字符串 检测用户是否登录:判断session里面是否有user
@WebFilter("/*")
public class LoginFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {HttpServletRequest req = (HttpServletRequest) request;String[] urls = {"/css/", "/img/", "/login.jsp", "/register.jsp", "/loginServlet", "registerServlet", "/checkCodeServlet"};String uri=req.getRequestURI();for (String u : urls) {if (uri.contains(u)||"/web_demo4_brandDemo_war/".equals(uri)) {System.out.println("[DEBUG]请求服务器资源..."+uri);chain.doFilter(request, response);return;}}if (req.getSession().getAttribute("user") == null) {System.out.println("[DEBUG]用户未登录访问数据资源,携带提示信息返回登录界面...");req.setAttribute("login_msg", "您尚未登陆");req.getRequestDispatcher("/login.jsp").forward(request, response);return;}System.out.println("[DEBUG]用户合法访问服务器资源..."+uri);chain.doFilter(request, response);}@Overridepublic void destroy() {}
}
11.index.jsp,login.jsp与register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
</body>
<script>location.href="/web_demo4_brandDemo_war/login.jsp"
</script>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>login</title><link href="css/login.css" rel="stylesheet">
</head><body><div id="loginDiv" style="height: 350px"><form action="/web_demo4_brandDemo_war/loginServlet" id="form" method="post"><h1 id="loginMsg">LOGIN IN</h1><%--el表达式获取请求转发中的提示信息--%><div id="errorMsg">${login_msg}${register_msg}</div><%--el表达式也可以获取cookie--%><p>Username:<input id="username" name="username" type="text" value="${cookie.username.value}"></p><p>Password:<input id="password" name="password" type="password" value="${cookie.password.value}"></p><p>Remember:<input id="remember" name="remember" value="on" type="checkbox"></p><div id="subDiv"><input type="submit" class="button" value="login up"><input type="reset" class="button" value="reset"><a href="register.jsp">没有账号?</a></div></form></div>
</body></html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>欢迎注册</title><link href="css/register.css" rel="stylesheet">
</head><body><div class="form-div"><div class="reg-content"><h1>欢迎注册</h1><span>已有帐号?</span> <a href="login.jsp">登录</a></div><form id="reg-form" action="/web_demo4_brandDemo_war/registerServlet" method="post"><table><tr><td>用户名</td><td class="inputs"><input name="username" type="text" id="username"><br><span id="username_exi" class="err_msg" style="display: none">用户已存在</span><br><span id="username_err" class="err_msg">${register_msg}</span></td></tr><tr><td>密码</td><td class="inputs"><input name="password" type="password" id="password"><br><span id="password_err" class="err_msg" style="display: none">密码格式有误</span></td></tr><tr><td>验证码</td><td class="inputs"><input name="checkCode" type="text" id="checkCode"><%--访问图片生成服务请求图片资源--%><img id="checkImg" src="/web_demo4_brandDemo_war/checkCodeServlet"><a href="" id="changeImg">看不清?</a></td></tr></table><div class="buttons"><input value="注 册" type="submit" id="reg_btn"></div><br class="clear"></form></div>
</body>
<script>//在这里如果不加后面的问号与数据,点击图片不会改变changeImg= function () {document.getElementById("checkImg").src = "/web_demo4_brandDemo_war/checkCodeServlet?" + new Date().getMilliseconds();}document.getElementById("changeImg").onclick = changeImgdocument.getElementById("checkImg").onclick = changeImg
</script></html>
12.登录注册的Servlet
生成图片:通过响应数据的输出流生成图片,并且把验证码设置为Session的键值对
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {String checkCode= CheckCodeUtil.outputVerifyImage(100,50,response.getOutputStream(),4);System.out.println("[DEBUG]验证码为:"+checkCode);System.out.println("[DEBUG]返回生成的图片...");request.getSession().setAttribute("checkCodeGen",checkCode);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");String username=request.getParameter("username");String password=request.getParameter("password");User user=new UserService().login(username,password);if (user==null){System.out.println("[DEBUG]登录失败,携带提示消息登陆界面...");request.setAttribute("login_msg","用户名密码错误");request.getRequestDispatcher("/login.jsp").forward(request,response);return;}System.out.println("[DEBUG]登录成功,添加session,跳转到查询界面...");if("on".equals(request.getParameter("remember"))) {System.out.println("[DEBUG]用户点击了记住我,添加cookie...");Cookie[] cookies = {new Cookie("username",username),new Cookie("password",username)};for (Cookie cookie : cookies) {cookie.setMaxAge(60);response.addCookie(cookie);}}request.getSession().setAttribute("user",user);response.sendRedirect(request.getContextPath()+"/selectAllServlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("utf-8");if(!((String)request.getSession().getAttribute("checkCodeGen")).equalsIgnoreCase(request.getParameter("checkCode"))){System.out.println("[DEBUG]验证码错误,携带提示信息返回注册界面...");request.setAttribute("register_msg","验证码错误");request.getRequestDispatcher("/register.jsp").forward(request,response);return;}boolean flag=new UserService().register(new User(request.getParameter("username"),request.getParameter("password")));if(flag){System.out.println("[DEBUG]用户注册成功,携带提示消息返回登录界面...");request.setAttribute("register_msg","注册成功,请登录");request.getRequestDispatcher("/login.jsp").forward(request,response);}else {System.out.println("[DEBUG]用户登录失败,携带提示消息返回注册界面...");request.setAttribute("register_msg","用户名已存在,注册失败");request.getRequestDispatcher("/register.jsp").forward(request,response);}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request, response);}
}
13.增删改查有关的jsp与Servlet
brand.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title>
</head><body><h2>${user.username},欢迎您</h2><br><input type="button" value="新增" id="add"><br><hr><table border="1" cellspacing="0" width="800"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><c:forEach items="${brands}" var="brand" varStatus="status"><tr align="center"><td>${status.count}</td><td>${brand.brandName}</td><td>${brand.companyName}</td><td>${brand.ordered}</td><td>${brand.description}</td><c:if test="${brand.status==1}"><td><%="启用"%></td></c:if><c:if test="${brand.status==0}"><td><%="禁用"%></td></c:if><td><a href="/web_demo4_brandDemo_war/selectByIdServlet?id=${brand.id}">修改</a><a href="/web_demo4_brandDemo_war/deleteServlet?id=${brand.id}">删除</a></td></tr></c:forEach></table>
</body>
<script>document.getElementById("add").onclick = function () {location.href = "/web_demo4_brandDemo_war/addBrand.jsp";}
</script>
</html>
@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("[DEBUG]查询并显示所有数据...");request.setAttribute("brands",new BrandService().selectAll());request.getRequestDispatcher("/brand.jsp").forward(request,response);}//这里的doPost在jsp中不访问,但最好写,如果别的资源使用post方式请求转发@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}
@WebServlet("/deleteServlet")
public class DeleteServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("[DEBUG]用户选择删除数据...");req.setCharacterEncoding("UTF-8");new BrandService().deleteById(Integer.parseInt(req.getParameter("id")));;resp.sendRedirect("/web_demo4_brandDemo_war/selectAllServlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}
addBrand.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>添加品牌</title>
</head><body><h3>添加品牌</h3><form action="/web_demo4_brandDemo_war/addServlet" method="post">品牌名称:<input name="brandName" value="淘宝"><br>企业名称:<input name="companyName" value="阿里巴巴"><br>排序状况:<input name="ordered" value="10"><br>描述信息:<textarea rows="5" cols="20" name="description">阿里巴巴</textarea><br>状态信息:<input type="radio" name="status" value="0" checked>禁用<input type="radio" name="status" value="1">启用<br><input type="submit" value="提交"></form>
</body></html>
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("[DEBUG]用户添加数据...");req.setCharacterEncoding("UTF-8");new BrandService().add(new Brand(null,req.getParameter("brandName"),req.getParameter("brandName"),Integer.parseInt(req.getParameter("ordered")),req.getParameter("description"),Integer.parseInt(req.getParameter("status"))));resp.sendRedirect("/web_demo4_brandDemo_war/selectAllServlet");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}
update.jsp
<%@page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPEhtml>
<html lang="en"><head><meta charset="UTF-8"><title>修改品牌</title>
</head><body>
<h3>修改品牌</h3>
<form action="/web_demo4_brandDemo_war/addServlet" method="post"><%--隐藏id--%><input name="id" value="${brand.id}" type="hidden">品牌名称:<input name="brandName" value="${brand.brandName}"><br>企业名称:<input name="companyName" value="${brand.companyName}"><br>排序状况:<input name="ordered" value="${brand.ordered}"><br>描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br>状态信息:<input type="radio" name="status" value="0" <c:if test="${brand.status==0}">checked</c:if>>禁用<input type="radio" name="status" value="1" <c:if test="${brand.status==1}">checked</c:if>>启用<br><input type="submit" value="提交">
</form>
</body></html>
<%@page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPEhtml>
<html lang="en"><head><meta charset="UTF-8"><title>修改品牌</title>
</head><body>
<h3>修改品牌</h3>
<form action="/web_demo4_brandDemo_war/updateServlet" method="post"><%--隐藏id--%><input name="id" value="${brand.id}" type="hidden">品牌名称:<input name="brandName" value="${brand.brandName}"><br>企业名称:<input name="companyName" value="${brand.companyName}"><br>排序状况:<input name="ordered" value="${brand.ordered}"><br>描述信息:<textarea rows="5" cols="20" name="description">${brand.description}</textarea><br>状态信息:<input type="radio" name="status" value="0" <c:if test="${brand.status==0}">checked</c:if>>禁用<input type="radio" name="status" value="1" <c:if test="${brand.status==1}">checked</c:if>>启用<br><input type="submit" value="提交">
</form>
</body></html>
相关文章:

[JavaWeb学习日记]JSP+Cookie+Filter与登录+CRUD案例
目录 一.JSP 二.EL表达式与JSTL标签 三.Cookie 四.Session 五.Filter 六. 登录CRUD:品牌增删改查案例 Demo一览 1.导包 2.构建包结构 3.创建数据库表tb_brand与user 4.创建实体类 5.mybatis的配置文件和logback配置文件 6.写接口 7.工具类:生成图片与…...
Ruby网络爬虫教程:从入门到精通下载图片
概述 网络爬虫技术在信息时代扮演着重要的角色,它可以自动化地获取互联网上的信息,为用户提供便利的数据服务。本文将带领读者从零开始,通过学习Ruby编程语言,逐步掌握网络爬虫的设计与实现,重点介绍如何利用网络爬虫技…...

各中间件性能、优缺点对比
参考资料: Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?...

修改表中某个字段等于另一个字段减去 2 小时的 SQL
需求:将表中到达时间按照客户要求改为比赛时间的提前 N 小时,具体如下: 表结构 update contestSchedule SET mainRefereeArrivalTimeDATE_FORMAT(CONCAT(2024-03-04 ,gameTime)- INTERVAL 2 HOUR, %H:%i), assistantRefereeArrivalTimeDAT…...

Jetpack Compose: Hello Android
Jetpack Compose 是一个现代化的工具包,用于使用声明式方法构建原生 Android UI。在本博文中,我们将深入了解一个基本的 “Hello Android” 示例,以帮助您开始使用 Jetpack Compose。我们将探讨所提供代码片段中使用的函数和注解。 入门 在…...
蓝桥每日一题 (差分)3月3号
//3279改变数组元素 自己做TLE:奈何想不出怎么用差分 #include<bits/stdc.h> using namespace std; //3279 改变数组元素(超时) const int N2e510; vector<int>a; int t,n; int main() {cin>>t;while(t--){cin>>n;…...
Mybatis和Spring Data Jpa的优缺点比较(八股文)
ORM(Object-Relational Mapping)框架是一种用于实现对象与关系数据库之间映射的工具或库。它可以将数据库中的表和记录映射成对象和属性,使开发人员可以使用面向对象的方式操作数据库,而不需要编写复杂的SQL语句。ORM框架的主要功…...
LeetCode买卖股票的最佳时机
LeetCode买卖股票的最佳时机 121 买卖股票的最佳时机Ⅰ 题目描述 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计…...
Codeforces Round 932 (Div. 2)----->A. Entertainment in MAC
一,思路: 简单的字符串处理,当反转字符串后如果字典序减小了,那么肯定不会再执行反转操作,而是执行操作2,将反转后的字符串拼接(这样必定构造一个回文串),那么之后的操作…...
【JavaScript】 短路运算的妙用 ||
短路运算的妙用 下方举例中的写法技巧,在实际开发中,经常用到。这种写法,是一种很好的「容错、容灾、降级」方案,需要多看几遍。 1、JS 中的&&属于短路的与: 如果第一个值为 false,则不会执行后面的…...
密码学之椭圆曲线
引言 DH(Diffie-Hellman)密钥交换算法于1976年提出,是第一个公开密钥交换算法。其基础是数学中的群论,群论也是大多数公开密钥密码的基础。简单来说,群是一组元素的集合以及在这些元素上定义的特殊二元运算。 一个群需要满足如下性质: 封闭性:群中两个元素的运算结果仍…...

overleaf latex 笔记
overleaf: www.overleaf.com 导入.tex文件 1.代码空一行,代表文字另起一段 2. 1 2 3 排序 \begin{enumerate} \item \item \item \end{enumerate} 3.插入图片 上传图片并命名 \usepackage{float}导包\begin{figure}[H]:表示将图…...

第十五届蓝桥杯青少组STEMA测评SPIKE初级真题试卷 2024年1月
第十五届蓝桥杯青少组STEMA测评SPIKE初级真题试卷 2024年1月 来自:6547网 http://www.6547.cn/doc/vywur8eics...
10个常见的Java面试问题及其答案
问题: Java的主要特性是什么? 答案: Java的主要特性包括面向对象、平台无关、自动内存管理、安全性、多线程支持、丰富的API和强大的社区支持。 问题: 什么是Java的垃圾回收机制? 答案: Java的垃圾回收机…...
Vue跳转页面传递参数
Vue跳转页面传递参数 🌟 前言 欢迎来到我的小天地,这里是我记录技术点滴、分享学习心得的地方。📚 🛠️ 技能清单 编程语言:Java、C、C、Python、Go、前端技术:Jquery、Vue.js、React、uni-app、EchartsUI…...

【已解决】conda环境下ROS2 colcon build编译选择特定python解释器
目录 1 问题背景2 问题探索3 问题解决4 告别Bug 1 问题背景 环境: ROS2 HumbleUbuntu22.04 现象:运行colcon build后由cpp编译生成的python导出库(如自定义消息、服务等),其版本与由python setup.py安装的python库版本不一致,导致…...
QT C++实践| 连接数据库的登录界面实现| 附源码
前言 在之前的两篇博客中QT C实战:实现用户登录页面及多个界面跳转、QT C实践|超详细数据库的连接和增删改查操作|附源码分别详细讲解了:登录界面的制作(UI布局、页面跳转、登录逻辑等)、QT如何连接Mysql数据库,并进行…...

html样式排版
<template><div class"box"><div class"header">头部</div><div class"main"><div class"left">菜单</div><div class"right"><div class"right-contentr"&g…...
Java:性能优化细节31-45
Java:性能优化细节31-45 31、合理使用java.util.Vector 在使用java.util.Vector时,需要注意其性能特性和最佳实践,以确保应用程序运行高效。Vector是一个同步的集合类,提供了动态数组的实现。由于它是线程安全的,所以…...

YOLOv9独家原创改进|增加SPD-Conv无卷积步长或池化:用于低分辨率图像和小物体的新 CNN 模块
专栏介绍:YOLOv9改进系列 | 包含深度学习最新创新,主力高效涨点!!! 一、文章摘要 卷积神经网络(CNNs)在计算即使觉任务中如图像分类和目标检测等取得了显著的成功。然而,当图像分辨率较低或物体较小时&…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...